SOA 将很多异类服务连接为一个具有内聚性的互操作环境。可以在单个事务期间同步调用其中一些或全部服务,从而形成互连服务组件链。链中的每个服务都依赖于下游服务——即在接收到所调用的下游服务发回的响应前,服务将不会继续执行。随着不可预测的情况的出现(如连接互操作服务的总线突然出现大幅度延迟),可能会导致服务阻塞和失败。这些失败将传播到链中,导致其他服务失败,并可能会降低整个 SOA 部署的稳定性。
无法响应的服务对整个 SOA 基础设施的影响程度取决于 SOA 的弹性。弹性(即服务的持续可用性和性能,不会受其环境的负面更改的影响)对于维护状况良好的 SOA 至关重要。本文将讨论各种短期解决方案,以提高容易形成同步互连服务组件链的 SOA 的弹性。
短期解决方案
短期解决方案 是能够方便地应用到现有 SOA 框架的解决方案,无需更改(或只需少量更改)整个体系结构。这些解决方案涉及配置调整和其他小的优化,仅需要对 SOA 进行极少的重构。在最糟的情况下,所需的重构工作是可管理的,可以快速而方便地实现。
短期解决方案的主要目标是:
本文重点讨论两个短期解决方案:
短期解决方案 1:紧密耦合 SOA 服务的搭配
搭配 实际上就是 SOA 服务或应用程序在同一物理系统上的部署。术语紧密耦合 描述同步调用的两个或更多服务之间的关系,即调用服务(客户机)在服务调用时阻塞,直到从其调用的服务接收到响应才能继续。多个紧密耦合的服务可能会参与单个事务,在 SOA 内形成同步互连组件链。
此部分讨论的短期解决方案将要把在同步互连组件链中作为组件的紧密耦合的业务应用程序部署在一起(在可能的情况下)。其重点是部署到独立服务器上但共享大量同步相互通信(即彼此紧密耦合)的业务应用程序。通过重新部署到相同的服务器上,这些业务应用程序可能会获得很大的好处,从而改进 SOA 的整体状况和稳定性。
搭配的好处
将紧密耦合业务应用程序部署在一起的最明显原因之一是可测定的性能改进。将应用程序部署在一起可利用进程内通信协议,而这样通常可促进应用程序间的直接通信。进程内通信可以避免远程服务调用的所有开销,包括序列化、加密、遍历网络堆栈和网络延迟。
将紧密耦合业务应用程序部署在一起的第二个原因是可减少对资源的压力,特别是任务或线程级别的资源。通过本地进程内通信协议的同步服务调用通常对本地服务器资源的压力要比通过远程通信协议进行的调用带来的压力要小得多。可以通过示例对此进行最好的说明,详见下面的部分。
问题场景:高工作负载与有限资源
请看图 1,其中部署在服务器 1 上的业务应用程序 A 将同步调用服务 B,而服务 B 承载于业务应用程序 B 中,部署在服务器 2 上。这两个服务器通过服务总线(通常是网络连接)以物理方式连接。
图 1. 承载彼此不同但同步的依赖应用程序(通过某种通信通道连接,如 HTTP 或 RMI)的应用服务器
外部客户机调用服务器 1 中的应用程序 A。工作请求将派发到服务器 1 中的托管任务。因为应用程序 A 和服务 B 之间的通信是同步的(例如,通过 Remote Method Invocation over Internet InterORB Protocol (RMI/IIOP)),因此服务器 1 中的对应用程序 A 派发工作的托管任务必须阻塞,直到从服务 B 收到响应为止。阻塞时,托管任务不能执行其他工作。
如果承载服务器(服务器 1)负荷非常重,仅有部分托管任务资源可用,则可能会出现问题。随着越来越多的托管任务在同步远程服务调用上阻塞,服务器调度工作的能力将降低,从而导致服务器的总体服务速率降低。
如果服务速率低于新工作的到达速率,则服务器将会跟不上,在有托管任务可对其进行调度前,新工作都将排队等候。如果所有托管任务都被阻塞,服务器完全不能执行任何工作,看起来像挂起了一样。如果此情况持续很久,队列中的工作和已派发的工作将超时并失败。
图 2. 外部服务可能会通过长时间阻塞线程动态地降低服务器的服务速率
服务器 1 的总体服务速率会受到影响,服务器 1 承载的所有服务的服务速率也都会下降。尽管实际问题可能分为故障或应用程序 A 和服务 B 之间的长延迟通信,但问题的影响贯穿整个服务器。托管任务资源是共享资源——服务器 1 承载的所有应用程序都共享相同的一组托管任务。由于应用程序 A 使用并阻塞了托管任务,因此其他应用程序无法调度。这可能会导致其他状况良好的服务失败,因为无法获得执行所需的足够资源。