理论上这无疑是正确的。在客户应用程序和服务之间惟一需要的公共元素是发送、接收和解码 SOAP 消息的能力。当然,还有比这更多一点的要求,即客户和服务都必须在这些消息的模式上达成协议,或者提供像 Web Service 描述语言( WSDL , Web Services Description Language )这样的机制,让客户来确定合适的模式。
但通常,松耦合的应用程序组件概念很少要求协作。假设已经协商好了模式,那么客户应用程序与服务之间的通信就可以进行。
除非它不行时。这听起来可能有点矛盾,但是实际上它是指对事物完全了解的一种状态。应用程序里的许多东西可能会出错,通常源于拙劣的需求分析、糟糕的设计、编码中的错误和导致性能或可扩展问题的无效的东西。所有这些问题以及更多的问题都可能在将服务与一个或多个客户结合时发生。
这里仅仅是客户应用程序开发人员在使用 Web Service 时可能会遇到的一些问题的几个例子:彻底失效——这可能意味着它有 Bug 或对象泄漏;返回错误回答——这可能是逻辑错误或意外行为;返回结果时太慢——它是 Web Service 还是数据库;进一步缩小范围对应用程序开发人员而言太困难了;它不能扩展——在许多情况下,这是由于直到加载应用程序之前才发现的低效代码或瓶颈造成的。
当 Web Service 采用与客户应用程序不同的平台时,这些问题更加复杂。如前所述, Web Service 的一个关键优点是其概念是平台是不可知的。可以用任何语言在任何平台上编写 Web Service ,这使得 Web Service 存在以下问题:构建客户应用程序的任何开发人员小组都要能理解和评估其应用程序所调用服务的强度和限制。
即使客户平台和服务平台是不同的,除了 Web Service 通常由构建应用程序之外的一组人员开发和维护以外,这些听起来仍像是围绕应用程序开发的普通问题。使用 Web Service 的一些应用程序开发人员缺少对应用程序细节的洞察,甚至不了解构建服务的平台。
当然,可以就这样假定它,但实际上,那些构建客户应用程序的人对于 Web Service 的工作细节也的确有很好的技术鉴赏力。这可能有助于解决如何调用服务以及调用服务的频率等有关问题,比如,或者它能够帮助开发人员解决服务本身所固有的问题。
后一个原因代表真正的问题——在除了知道所需的输入和期望的输出以外不了解 Web Service 其他任何东西的情况下使用 Web Service 。应用程序开发人员经常对分析和诊断他们所遇到的 Web Service 问题感到迷茫。如果很少看见或根本看不见 Web Service ,并且应用程序不能像预期的那样工作或者执行的话,那么开发人员可能只能分析他们自己编写的代码,而不是分析整个应用程序。对应用程序开发人员而言, Web Service 就是暗面。
窥探 Web Service
让我们近距离看一下企业中的典型场景可能是怎样的。一种情况是当 Web Service 在 Java 平台上运行,同时客户机应用程序使用 Microsoft .Net 技术的时候。在这个例子中,客户应用程序无法扩展到需要的用户数。实际上,在实际使用中,它只同时支持 10 个用户,而要求是同时支持 100 个用户。特别是,在只有 10 个用户时,它最终还是瘫痪了。
解决这样的问题应该遵循标准过程。这个过程看起来可能是这样的:遇到一个问题,描述问题的特点,分析问题参数,对问题进行一些诊断,然后将分析和诊断移交给 Web Service 的拥有者。
一旦遇到这种可伸缩性问题,初始任务是将它定位到客户应用程序或 Web Service 。合理的做法是将这二者分开来单独测试。比如,比较合理的做法是编写一个作为客户应用程序后端的测试装置模块,并产生类似的期望从 Web Service 那里获得的批量应答。同样,可直截了当地编写一个演习 Web Service 的测试装置模块。
虽然这些测试装置模块可生成适当的应答,但是它们不会去模仿应用程序上多个用户的特性。除测试装置模块以外,还需要一个用于负载测试的载体。虽然在许多企业中,负载测试仍是手工过程,还是有一些方法可自动化这个过程。可以使用商业测试装载工具,该工具实际上可以减少所涉及的人工干预,并获得 Web Service 响应时间和系统特性的真实数据。
图 1 显示了用商业测试负载产品执行负载测试所产生的结果。数据显示 Java 虚拟机( JVM , Java Virtual Machine )上下文中的内存使用在随着时间推移而增加,而且在模拟用户退出系统后并没有减少。
图 1.用像 Compuware QACenter Performance Edition 这样的商业化自动负载测试工具使负载测试自动化,从而允许应用程序开发人员无需大量工作就能够收集数据
合理的可能出事故的地方是应用程序使用内存的方式。虽然许多开发人员相信,像 Java 这样的可管理平台不可能有重大的内存问题,开发人员必须全神贯注于构建使用内存管理来提高应用程序性能和可靠性的可靠战略,而不是专注于分配、初始化、使用和释放特定大小和位置内存区的战术性技巧。
这怎么可能在 Java 平台上发生呢?请考虑以下简单的 Java 方法:
在该方法中,分配一个新的字符串 r 作为迭代中使用的临时对象。在这个迭代中,当前的 r 被复制到新的实例中。此外, compute(i) 方法的结果被增加到新的 r 字符串中。每一次循环都这么做一次。结果是每次通过该循环进行迭代时都会创建一个新的临时对象。
这有几层含义。首先,临时对象的激增意味着内存持续分配。虽然内存分配耗费不是特别大,但是它确实会导致性能恶化。而且较大量的内存占用意味着要访问更多的内存单元。这也不用花大量的时间,但是它会带来相关的性能恶化。
主要的性能恶化来自过量内存的垃圾收集。垃圾收集代价很高,因此值得花一些精力去避免分配任何不必要的内存,而这么做的方法就是编写减少临时对象使用的代码。一个替代方法可能是:
这段代码使用 append() 方法来执行添加操作,消除了为 JVM 生成临时对象的需要。这些类型的内存问题是新出现的,大多数开发人员(甚至 Web Service 开发人员)对它还不熟悉。很多情况下,开发人员只是缺少经验和了解,不知道何时服务存在内存问题,以及是否能对此做些什么。他们假定自己无法控制内存的使用、分配和再分配方式,并且对设计和实现决定如何影响内存使用不加注意。
Web Service 中的诸如此类的性能问题可使得它们不根据要求执行,或者不能扩展。这类问题可在任何 SOA 平台上发生,这个例子恰巧发生在了 Java 上,但在 .Net 的 C# 中,这类问题也同样很容易发生。
远程诊断 Web Service
应用程序开发人员可能不熟悉服务平台或是语言。但是通过收集和分析应用程序中上下文中的数据,开发人员能够帮助服务拥有者,使之可防止问题。通过提供在其应用程序上下文中进行负载测试而确定的一些 Web Service 问题诊断,开发人员做到了这一点。
在这种情况下,既然负载测试已经识别了潜在的内存问题,那么通过使用商业内存分析产品对服务进行内存分析使得诊断更进了一级。通常可能不需要服务的源代码就可以做到这一点。至少可以安装和远程控制一个产品,这使得不出现在服务器旁边就能分析 Web Service 成为可能。
比如, 图 2 显示了源自 JVM 的一个对象泄漏。进一步深入研究表明,对象泄漏源自一个打开数据库连接的方法。结果,每次访问数据库,连接都被打开,但是最后从不关闭。最终结果是:每次调用数据库都泄漏 48 字节。随着时间过去,有许多用户调用数据库,这会产生一个稳步增长的、可降低性能并终至崩溃的应用程序图像。
图 2. 使用 Compuware DevPartner Java Edition 深入研究 Web Service 的内存使用,提供对服务内对象泄漏的深入了解。
这些结果是可控诉的,虽然不是由服务消费者。作为替代,可以将它们移交给服务的拥有者做额外的诊断和修复。
Web Service 开发人员对于 Web Service 应该做什么,以及如何实现这些要求,有很好的理解。然而,他们缺乏设计直接支持终端用户应用程序的实际经验。通过提供对客户应用程序的性能和可靠性的反馈,客户应用程序开发人员可帮助 Web Service 。
这使得应用程序开发人员可以更好地理解 Web Service 的强度和限制,同时为服务开发人员提供关于服务使用的宝贵信息。在构造和构建企业 SOA 时,这类信息对这两个团队都很必要。服务消费者可实地测试服务提供者的工作,这可提供 Web Service 最好的真实测试,而且这么做时可以帮助使用 SOA 的应用程序防止出现问题。
SOA 战略有提高和加速企业应用程序开发的潜力,同时让应用程序更加健壮,有更好的可扩展性。但是,这只在应用程序可依赖其服务的性能和可伸缩性时才有效。
服务消费者可通过两种方式提供帮助,首先通过使用他们的应用程序来测试服务,其次,通过分析和诊断其应用程序上下文中的问题。如果企业希望构建一个真正能防止问题的 SOA ,那么服务消费者在这一层面上的参与就比较关键。