当前大多数 SOA 方面的文章书籍都集中在个别的业务服务的定义和实现。构建企业的解决方案通常都需要结合多个现有的企业服务。这些复合而成的服务又可以与其他服务再次复合成更高级的解决方案。这种业务服务的递归复合是 SOA 最重要的特性之一,它使我们可以快速地在现有业务服务的基础上构建新的解决方案。随着业务服务(及其复合)的数量增长,要实现新的企业解决方案也变得更加容易。
按照《 Toward a pattern language for Service-Oriented Architecture and Integration 》的定义,产生复合服务的主要推动力来自以下方面:
- 简化使用。当若干业务服务同时被多个消费者使用时,要向所有消费者披露其中每个服务及它们之间协作的规则等信息,这会令消费者的实现更加复杂。而当创造复合服务时,封装参与其中的服务以及强制对它们的调用规则,都能显著简化使用上的复杂性。
- 提升重用性。原先没有计划到的新方案经常都可以用现有的服务组装出来。即使这些服务是为构造特定的方案而设计的,我们仍然能够以不同的组合方式用这些业务服务来实现原先没有预料到的方案。而且,手上可用的服务会促使我们想到前所未有的新方案。这些新方案常常可以由相对较少的服务发展或增强而产生,既低成本又快速。
- 方案的配分、可见度、控制和变更管理。复合服务可以看作是整体方案的一种配分机制。跟 EJB 的本地和远程接口的情况类似,引入复合服务,并且只对外部用户暴露部分接口,使我们能够控制什么是对消费者可见的。这使得底层软件架构(复合服务的实现)有能力对需求变化做出快速反应,每当需求变化,底层软件架构就调整它的下一级服务的实现以及它们之间的相互联系,而对消费者没有或者只有轻微影响。。
复合服务有两个方面(按照《 Tools for Composite Web Services: A Short Overview》的说法):复合设计,关注的是综合的规范,来确定如何协调各组件服务(Component Service)去满足客户请求;复合的实现,即如何执行由复合设计产生的规范,以实际达成各服务之间的协调。
在本文中,我们将分别从设计和实现两方面讨论复合服务的主要方式。
复合设计
复合设计是关于如何在一组现有服务的基础上设计出一个解决方案。它要做的是确定复合设计中用到的各个服务、它们之间交互的方式、以及复合的拓扑。
服务的交互
根据《 Service–Oriented Composition in BPEL4WS》,复合的交互主要有两种设计方式:
- 分层复合
- 会话复合
对于分层复合,复合服务的实现对于服务的消费者是完全不透明的(黑盒)。调用服务的消费者一直等待到执行完成,然后(直接或间接地)使用执行的输出结果(图 1)。
图 1 分层服务复合
这种复合方式对于实现逐层分解的系统来说非常自然。每个层次被实现成一个独立的复合服务,并协调低一层的(符合)服务的执行。这也是工作流系统中对高层方案通常采用的建模方式——对一系列活动进行组合,而每个活动可对应一个低层的业务过程、或者由人或程序执行的一项任务。虽然任意复合服务可被使用它的外部系统监控和中断,但除了最初的调用之外,复合服务并不与服务的消费者发生任何其它功能性的交互 1 。
虽然黑盒复合方式(分层复合)是对付复杂性的强有力工具,但在某些情况下消费者仍然需要根据执行的即时结果来控制复合服务的执行。会话复合可以完成这种功能。在会话复合的情形中,复合服务的实现对于服务的消费者仍然是完全不透明的,但特定的即时执行结果可被暴露给消费者(灰盒)。
这是通过支持显式的会话状态来实现的(会话状态和执行状态的区别请见 [4])——复合服务然后向消费者暴露出多个接口:一个用作原来的服务调用,其他的用作获取即时结果以及依此控制服务的执行(图 2)。
图 2 会话服务复合
在这种复合类型中,进行交互的消费者和提供者被看作是对等的伙伴,互相交换数据和控制信号。
两种交互方式都是可行的复合设计方案。运用严格的层次结构是对复杂业务过程建模的地有效途径,工作流技术的成功是一个证明。另一方面,会话的丰富表现方式让它更容易抓住日常业务交互的精髓——谈判的行为、对结果的监控等等——通过明确地为消费者和服务之间的信息交互建立模型。
复合的拓扑
复合服务的设计不光需要定义服务的交互活动,也需要为其实现定义成员和拓扑。复合服务的拓扑有两种主要设计方式("《 Service–Oriented Composition in BPEL4WS》"):
- 基于中介的拓扑
- 对等(Peer-to-Peer)拓扑
基于中介的拓扑(图 3)假设存在一个被称为中介者的服务,它担当着一个特殊角色,既与服务的消费者交互,又控制参与本复合的其他服务(或复合服务)的执行。
图 3 基于中介的复合拓扑
在基于中介的分层复合服务中,中介者实现一个编制规划(Orchestration Schema)以定义成员服务的调用序列,从而在特定的约束下完成特定的目标。中介者的实现可以采用不同的方式,包括编制语言 / 引擎、OWL-S 复合、Petri Net 等等。
在基于中介的会话复合服务中,中介者按照消费者的输入实现服务状态和状态的转换。中介者的典型实现一般都基于转换系统(Transition System)或有限状态机。
在对等拓扑中不存在中介者的概念。每个参与的服务(成员服务)都可以(部分地)执行复合服务(图 4)。
图 4 对等(Peer-to-Peer)复合拓扑
复合,在这里被定义为一个消息发送模板,成员服务可被插入其中。其目标行为被定义为一个允许的消息交换序列的家族,并应由系统具现化。一般这种拓扑仅被用于实现分层复合服务,因为它缺乏支持会话状态所必需的机制(即实现会话型交互的需求)。
复合的各种实现方式
看起来实现服务中介者的最简单方式是使用通用编程语言(图 5)。
图 5 编程实现复合服务
不幸的是,这种方案有几个缺陷:
- 这种方式硬编码了复合服务的编制面,因而产生出一个相当刚性的实现。对复合服务的任何改变都必须重新编写服务中介者的实现。
- 这种方式常常导致出现“意大利面式的服务”实现,每个服务都要为其他服务的访问特设接口。“意大利面式的服务”通常导致服务实现之间产生紧密耦合。服务调用的网络本质以及由不同团队开发不同服务,常常导致“意大利面式的服务”最终变得无法维护。
- 实现会话复合服务以及维护异步调用的服务之间的一致性等需求,更是大大增加了整体实现的复杂程度,因此在复合应用中需要线程支持。支持服务上下文的需求通常要求为每个复合服务创建特别的数据库。
- 复合服务的实现要求实现某种形式的事务支持,来确保参与的服务在失败时仍然有正确的行为。
虽然已经存在若干实现复合服务的框架(例如 WS-CAF ),用编程方式实现复合服务看起来并非一个正确的选择。
另一种实现复合服务的可能方式是基于事件的复合。这种复合实现建立在基与事件的服务交互的基础上:服务消费者向发布 / 订阅代理(Publish/Subscribe Intermediary)发布事件,代理再向实际的服务提供者投递事件(图 6)。
图 6 通过发布 / 订阅机制的服务交互
在这种情形中,发布 / 订阅引擎作为一个中间层,在服务消费者和提供者之间起到了解耦的作用,因此可以允许极其灵活的复合服务实现。复合服务可以被实现成下面的样子(图 7):
图 7 用事件实现复合服务
服务消费者将初始化事件(通过发布 / 订阅引擎)投递到订阅了此事件的若干服务。随后,每个服务可以发送另一个消息来(通过同样的发布 / 订阅引擎)调用另外一些服务。这样的事件序列有效地创造出了一个复合服务。通过发布 / 订阅机制实现的复合服务有以下特点:
- 与编程实现的方式相比,它有非常显著的灵活性。通过更换一组服务订阅的主题,可以完全改变复合服务的实现。或者更换消费者发送的事件主题也可以达到同样的效果。
- 基于事件的实现没有一个很好的地方可以用来放置复合服务的上下文信息。这增加了实现复合服务的复杂程度。其中一种解决方案是将上下文数据附加到事件内容中,这会导致消息的体积增大,因而导致网络流量上升和性能下降。
- 基于事件的实现中不存在“复合服务实例”的概念,这使得协调各种事件,实现出复合服务的实例变得非常困难。
- 要实现任何形式的事务支持,以确保参与的服务在失败时仍然有正确的行为,也同样变得非常困难。
通过使用编制引擎(Orchestration Engine)来实现服务中介者,可以进一步完善复合服务的实现(图 8):
图 8 用编制引擎(Orchestration Engine)实现复合服务
这种实现方式通过采用编制语言(Orchestration Language)而非通用语言,从而改进了前述的编程实现方式。这意味着我们可以使用量身定做的可视化编辑器来编写 / 维护复合逻辑。这也意味着我们可以利用编制引擎的强大功能,编制引擎内建支持异步调用、状态管理、事务的补偿(Compensation)等等。使用编制引擎来实现复合服务有以下优点:
- 编制语言是实现编制得更好选择,也因此简化了复合服务的实现。
- 可通过可视化编辑器进一步简化编程。
- 内建支持编制实例和上下文的编制引擎,这是实现复合服务的必须。
- 支持补偿(Compensation)的编制语言,大大简化了事务性支持的实现。
综上所述,在前面讨论的三种方式中,基于编制的实现看起来是创建复合服务最可行的方式。
结论
复合服务在 SOA 实现中扮演了重要角色,它带来了以下优点:
- 改善可重用性。复合服务为重用现有的服务提供了一种自然的方式。服务提供者可通过复合服务来增加价值。
- 更快投入市场。新的方案可以在更短时间内被构造出来。现存的服务(假设它们可被复合)以及一个结合并管理它们的机制,或多或少地能够减少构造新服务新方案的时间和精力。尤其是我们可以用现存的已达到生产级质量的服务快速地组装出一个可操作的原型。
- 改善安全性和审核能力。复合服务代表了一系列底层服务的单一访问入口。单一访问入口是确保服务调用契约的一种简单而有效的方式,使能够我们控制和测量队成员服务的访问。
- 更低的重复性。冗余被减少或消灭。与其多次复制同样的业务功能,实现所需功能的一个业务服务可以在多个复合中被重用。
- 改善可修改性。因为同一个底层服务可以是许多复合服务的组成部分,也就是说对一个地方的修改就可以在整个企业的范围内改变一项功能。
本文讨论的各种复合服务的设计方式针对了多种多样的业务场景,因此我们可以为特定的业务需要设计出最适合的复合服务(及其拓扑)。
最后,我们建议使用编制引擎来实现复合服务。
关于作者
Boris Lublinsky 在软件工程和技术架构上有超过 25 年的经验。在最近几年中,他主要关注企业架构、SOA 和过程管理。在他的整个职业生涯中,Dr. Lublinsky 经常作技术演讲和写作工作。他在不同杂志上出版了超过 40 篇技术文章,包括 Avtomatika i telemechanica、IEEE Transactions on Automatic Control、Distributed Computing、Nuclear Instruments and Methods、Java Developer’s Journal、XML Journal、Web Services Journal、JavaPro Journal、Enterprise Architect Journal 和 EAI Journal。最近 Dr. Lublinsky 为一家大型咨询公司工作,职责包括开发和维护 SOA 策略和框架。可以通过 blublinsky@hotmail.com 联系他。
参考资料
- Ali Arsanjani. Toward a pattern language for Service-Oriented Architecture and Integration, Part 2: Service composition . Developworks, December 2005.
- Richard Hull, Jianwen Su. Tools for Composite Web Services: A Short Overview .
- Rania Khalaf, Nirmal Mukhi, Sanjiva Weerawarana. Service–Oriented Composition in BPEL4WS .
- B. Lublinsky. Defining SOA as an architectural style . IBM Developworks, January 2007
- Web Services Composite Application Framework (WS-CAF)
查看英文原文: Service Composition
评论