简单地说, 面向服务架构 (Service-Oriented Architecture, SOA) 是一种 IT 架构策略,其基于面向服务的概念之上。自从 2002 开始为大家熟知以来,SOA 已经逐渐地成为业界的标准,也得到了广泛的应用。
因为 SOA 经常和 Web Service 相提并论,所以导致大家一直有一个误区,认为这两者是等同的,其实不然。虽然两者有很多的关联,但它们是截然不同的两个概念,或者说考虑问题的角度不同。虽然 SOA 最初的流行离不开 Web Service 的贡献,但如今 SOA 早已超越了 Web Service 的范畴,变成一个独立的设计理念。
SOA 主要从系统解构的角度入手,它侧重于将整个应用分解为一系列独立的服务,并指定各种标准和基础设施来使得这些服务易于重用,能够很容易地被各种平台上的应用来使用。但是在服务实际业务时出现了一些问题,因为 SOA 更多地是关注静态的信息,所以不能很好地与动态业务匹配。比如 SOA 不能很好地回答类似下面的一些问题:
比如在一个证券公司,有很完善的交易系统、后台系统、账务系统和头寸管理系统等,当一个客户的下单在交易所执行后,所有的这些系统都应该得到通知,并做出相应的处理。这里面其实包含了几个问题:谁来负责触发这样一个事件,各个系统如何得到通知?如何保证各个系统行动的一致性? SOA 架构由于其关注点的限制,并不能很好地解决上述问题,而这些问题往往又是实际系统非常需要的特性。因此,EDA 与 SOA 的集成引起了人们的注意。
通过引入面向事件的机制,使得系统具备了感知和快速响应业务事件的能力。其实不管是 SOA 还是 EDA 都不是什么新技术,无非是在一些旧的概念上添加了一些新元素。
其实你可以从 SOA 或 EDA 的身上很容易看到以前的技术 ( 比如 CORBA 或者 DCOM) 的影子。任何系统都可以简化为组件 / 服务加上通道 (channel,解决通讯的问题 ),如果说 SOA 关注于组件和服务的话,那么 EDA 更多地关注通道。
我们一般将 SOA 和 EDA 的集成体称之为事件驱动的面向服务架构 (Event-Driven SOA),可以将其理解为 SOA 的一种衍生。SOA 和 EDA 的交互主要体现在以下几个方面:
将事件处理的能力引入到 SOA
一个事件的产生可以触发一个或多个服务被调用,这样就把这些静态的功能动态地串联起来。
服务本身也可以产生事件
服务除了完成特定的功能外,也可以根据自身需要产生某个事件。
有人将 EDA 和 SOA 的关系与人体做了一个形象的比喻,如果把 SOA 比作手和脚的话,那 EDA 就像人的眼睛和耳朵。当眼睛发现一只狮子正朝你奔来时,一个消息被发送到大脑,然后大脑向你的手脚发出指令:赶快跑。
当然,任何一种架构模式都有其适用的场景,Event-Driven SOA 自然也不例外。
首先,它适用于异步的环境。如果你的系统对实时性要求比较高,请不要使用该架构。
第二,如果你的系统需要面对复杂的异构环境——跨平台 / 跨语言,那么面向服务的架构能够很好地应对。
第三,将系统功能分解为适当粒度并且重用性高的一个个服务,可以显著地提高 IT 系统的适应性和效率,进而提高投资回报率 (ROI)。
第四,引入事件处理的能力以后,每个服务都是由不同的事件驱动,这样当某个事件发生后,系统的不同服务就能够自动地进行触发。这对那些有更高自动化要求的系统来说非常适合。
第五,与面向过程的系统中客户端必须轮询更改请求 ( 通过 API 调用 ) 不同,事件驱动架构允许系统和组件在事件发生时实时动态地做出响应。事件驱动架构通过引入长时间运行的处理功能来弥补 SOA 的不足。这一点对于金融系统来说尤其重要,比如说一次股票买卖从客户下单到最终交割会经历几天的生命周期。
最后,Event-Driven SOA 使得增加事件的 consumer 和 producer 非常容易,这样就使得增加系统吞吐量也变得很简单,系统的弹性非常好,非常适合那些业务量持续增加的系统。在这方面,有一个 EDA 的变体 SEDA(Staged Event-Driven Architecture)将这方面的设计发挥到了极致,详细的介绍请参考正文后的参考资料。
在当今社会,市场变化莫测,商机稍纵即逝,企业需要有极强的灵活性和应变能力,金融行业尤其如此,特别是在中国这样一个金融行业处于快速发展的市场里。企业要求 IT 系统能够快速地对业务需求做出应对,否则就会丧失先发优势。这有点类似于现代战争条件下,各国都要求部队具备快速反应能力,这种能力主要体现在 IT 部门能够通过快速开发或者重用 / 整合现有资源来达到快速响应业务需求。还有,金融行业业务越来越庞大复杂,所涉及的第三方系统或者遗留系统非常多,这就要求 IT 系统有很强的整合能力及对异构环境的适应能力。最后,由于金融行业的发展日新月异,特定金融业务都会在其初期发展后迎来一个快速膨胀期,业务量和业务类型会急剧增加,这也要求 IT 系统有很好的可扩展性。
对照前面提到的 Event-Driven SOA 的特点,我们可以很直观地发现该架构可以很好地满足金融系统的实际需求。当然,金融系统也是包罗万象,特点各不一样,这里可能更偏重于金融行业的交易系统。
为什么选择 Event-Driven SOA ——适用性讨论
除了上面提到的这些大的因素之外,我们还可以深入到具体系统的内部,从一些微观层面来考虑 Event-Driven SOA 是否仍然能够符合我们的要求。下图是一个证券公司股票交易系统的简图:
从上图我们可以看出,整个应用被分为很多子系统,各个子系统之间存在着大量的信息交互。而且大部分应用输入都需要经历一个比较长的生命周期,比如说一个客户订单输入到系统后,会先后经历前台系统 (Front Office),中台系统 (Middle Office) 以及后台系统 (Back Office),而且每个系统内部又包括很多服务组件。除了系统层面的跨度外, 这个生命周期也体现在时间长度上。而且,如今所有的金融系统都追求 STP (Straight Through Processing) 的能力,主张尽可能少的人工干预,这样所有的服务组件都需要具备自触发的能力。
架构师在着手每次的架构设计时,其实都是在提出并回答一系列的问题,把这些问题都回答了,架构设计也就出来了。比如我们每次肯定都会问:系统的最终用户是谁,他们会如何来使用该系统,他们的核心诉求是什么。当然,不是所有的问题都能有一个圆满的答案,更多的时候其实是一个取舍的过程。比如说系统的关键指标我们很难一下子全部满足,就需要结合具体的业务需求和人力物力以及时间的具体情况来做取舍。下表就列出了一些我在做 Event-Driven SOA 架构设计时认为比较关键的问题(在遵循一般架构设计的原则的基础之上),看看你是否也有同感。
表一:Event-Driven SOA 架构设计时的几个关键考虑
领域 | 关键考虑 |
---|---|
设计原则 | 业务为先 |
坚持简单适用的原则 | |
系统的关键指标有哪些?互联互通最重要 | |
设计演变 | 功能分解,服务定义,事件的定义及分类 |
基础架构的选择 | |
EDA 的实现途径 | |
最佳实践 | 如何重用已有的基础组件 |
下面我就其中的几点具体展开讨论一下:
任何的技术或者架构思想都是由具体的业务需求驱动的,比如 SOA 的出现是由于人们打破竖井应用 (application silos) 并追求功能重用的强烈需求,而 EDA 的出现也迎合了业务流程化、自动化的趋势。所以,任何的架构设计都要服从于自身业务的具体需求,没有最好的架构设计,只有最合适的。
在 SOA 实践中,尤其强调业务为先的原则,因为我们必须先进行业务流程的整合重组,然后才是 IT 系统的服务化。业务流程本身的问题还是需要从业务本身去解决,再好的技术也解决不了业务的问题。试想一下,如果一个企业各个部门之间各自为战,缺乏协作和沟通,那么可能开发出一个好的面向服务的 IT 系统吗?
除了业务部门的努力外,IT 部门在做任何架构设计的决定前,必须确保理解清楚了业务部门的具体需求。所以说,项目前期 IT 部门和业务部门之间的协作和交流非常重要。
这里很容易有一个误区,尤其是对那些经验丰富的架构师。他们往往拥有丰富的 IT 经验和业务知识,自认为已经非常了解业务部门的需求,甚至有些时候都能够指导业务部门如何去改进。在这种自负的情绪中,他们觉得可以先把所谓先进的 IT 系统开发出来,然后再去推广,他们认为用户肯定会欣然接受这些系统,因为他们代表着先进的理念,但往往事与愿违。姑且不去深究究竟孰对孰错,退一万步讲,一个没有充分听取用户意见,没有用户参与的系统能够那么容易得到用户的认可吗?即便你是对的。
在 Event-Driven SOA 的实施过程中,有几个关键指标:服务的分类和创建,事件的定义和管理,服务的互联互通,业务流程的理解和 IT 实现等。那我们应该更加关注哪个指标呢?因为我们往往很难一下子兼顾所有的指标。个人认为这其中最重要的就是服务的互通互联。当然这里所讲的互通互联并没有那么简单,并不是仅仅建立起通讯的通道就可以,它包括以下几个方面的内容:
- 无论通讯的方式如何,最好做到自动化
实现通讯的方式有很多种:同步调用,异步消息,Socket 甚至是文件,无论采用哪种,最好做到自动化的实现。任何人工的干预都容易引起错误和延迟。
- 通讯的双方之间需要定义清晰的接口,有共同的异常应对机制
特别是当通讯的双方是由不同的开发团队来完成,一定要在开始阶段就定义清楚接口,并在随后的开发过程中严格遵守,同时保持实时的沟通。这里面需要强调的一点就是异常的应对机制,要让双方都充分理解可能面对的异常情况及应对措施。
- 基础数据的共享
在金融系统中,会用到大量的基础数据(一般称之为 Reference Data),这些数据在各个系统都会用到。但事实上情况往往并不如此,经常是各个系统各自为战,不用或者是使用不同的数据源,导致在通讯过程中的识别歧义。
做到以上这些,技术上并不困难,更重要的是项目之间的协作和执行力强的领导团队。
结合到实际的例子,比如美国三军联合作战系统,其核心就是其“数据链”系统,它使得战场上的指挥中心、作战部队和武器平台能够实时交换数据,达到精确协作的目的。从下面这段描述我们就能感受到这种高效无缝协作的威力:
“在 7 年之后的海湾战争中,初级的“数据链”就已显威战场。以美军拦截导弹作战为例,就可以看到“数据链”的作用。伊军的“飞毛腿”导弹一发射,12 秒钟之后,位于太平洋上空的美国防支援计划(DSP)的导弹预警卫星就发现了“飞毛腿”,并迅速测出它的航行轨道及预定着陆地区,报警信息及有关数据迅速传递到位于澳大利亚的美国航天司令部的一个数据处理中心,数据中心的巨型计算机紧急处理这些数据之后,得到对“飞毛腿”导弹进行有效拦截的参数,然后航天司令部将这些参数通过卫星传给位于沙特阿拉伯的“爱国者”防空导弹指挥中心。防空导弹指挥中心立刻将数据装填到“爱国者”导弹上并发射,整个过程只需要 3 分钟左右的时间,而“飞毛腿”至少要飞行 4 ~ 5 分钟才能到达预定目标的上空,这就为拦截导弹创造了条件。…”
在明确了以上这些设计原则外, 我们需要一步步考虑整个架构的实现途径。首先面临的就是一些基础架构的选择。
- 基础架构的选择
在这里我们需要回答一系列的问题:自己开发还是购买?开源的还是商业的?选择什么 Web Service 的基础平台?选择什么样的消息中间件(Message Oriented Middleware, MOM)?是否采用企业服务总线(Enterprise Service Bus, ESB)?
这其中讨论的最多的就是是否以及如何使用 ESB。个人观点,ESB 是有价值的,仅当系统确实需要 ESB 的功能时。Accenture 首席技术官 Don Rippert 在他的一次早期访谈中提到发挥 SOA 的全部潜力大致需要以下 4 个步骤:
- 开始采用 SOA 架构,使用 XML 等标准的方式来使用应用程序接口
- 捕获一些业务过程,并将它们转化为 Web 服务
- 引入并全面使用企业服务总线
- 将业务过程执行语言(Business Process Execution Language, BPEL)集成进来,利用业务过程建模工具和 BPEL 可以创建不同的应用行为,而无需修改软件
为什么将 ESB 的使用放在第三个步骤呢,那我们需要从 ESB 的定义入手,来了解 ESB 究竟带给我们些什么。ESB 应该被理解为模式而不是产品,它应该至少具备以下这些功能:
- 服务的虚拟化,支持虚拟化通讯参与方之间的服务交互并对其进行管理。意思就是服务只需要关注完成自己的功能,不需要关心哪个服务调用它以及它需要调用哪个服务。
- 服务的转化、包装以及桥接
- 消息的传递、过滤以及路由
- 服务编制(Orchestration)
还记得前面将 EDA/SOA 和人体进行类比的例子吗?如果按照该思路,ESB 就可以看作是人体的中枢神经系统。其接受眼睛传入的“狮子来了”的信息,整体加工后成为协调的运动性传出,手脚也就开始动作了。
从上面的定义可以看出,ESB 更多地关注应用流程方面的信息,将业务流程剥离出来并将其交由 ESB 来统一管理。因此,有一个非常简单的标准来判断是否需要采用企业服务总线:就是看你的应用本身是否有很复杂的业务流程,而且可能这些流程会经常发生变化。依据这条标准,我觉得很多应用一开始都没有复杂到需要立即采用企业服务总线,比如说一个股票的后台管理系统,其业务流程相对来说比较简单固定,就没有必要引入企业服务总线这样重量级的解决方案。
当然,ESB 中分解流程信息的思想我们还是可以借鉴的,只不过我们可以用更简单的方法来实现。
- EDA 的实现途径
在 EDA 中,按照事件简易程度的不同,事件处理模型可以分为以下三种:
- 简单事件处理 (Simple Event Processing)
- 流事件处理 (Stream Event Processing)
- 复杂事件处理 (Complex Event Processing, CEP)
在一个成熟的事件驱动架构中,这三种往往会混合在一起使用。目前,很多公司都推出了支持 CEP 功能的产品。但是在实际应用过程中,我们还是需要秉承由简入繁的原则。能用简单的事件处理解决问题,就没必要使用复杂的。
实现事件驱动架构最简单、直观的方式就是使用消息。在 JMS 的体系架构里,我们很容易来实现事件驱动的一些基础元素:事件的生产者、消费者和通道。下图为在发布 / 订阅模式下,消息发布者、订阅者以及消息通道和主题之间的交互。
(图片来自 http://www.ibm.com/developerworks/cn/opensource/os-ag-eventdriven/index.html)
严格意义上来说,事件和消息是不同的概念。消息代表非直接交互时简短的信息,而事件往往代表状态的显著变化。可以把事件看作消息的子类,因为后者还包括包含数据的消息等。而且,在实际应用中,一个消息中往往同时包含事件和数据的内容。比如系统接收客户的订单后,它会发布一条消息:其中既包括事件(新增客户订单),又包括新订单的具体数据。
在确定了系统的架构后,我们需要着手来实现它。经过这么多年的实践,人们也总结出一些基础的组件,这些组件对于事件驱动的面向服务架构来说是必不可少的,或者说经常被使用到的。
- Web 服务基础架构 (XML,SOAP,WSDL,UDDI 和 Quality of services)
- 企业服务总线(针对复杂应用)
- 消息中间件
- 监控体系
- 异常处理的讨论
- 配置和规则引擎
其中第一、二项大家讨论得最多,第三项也经常被提及。作为消息运转的基础,消息中间件(Message-Oriented Middleware,MOM)必须做到安全、可靠和快捷。市面上有很多很成熟的产品,比如 WebSphere MQ,Apache ActiveMQ 等。而且还有些针对特定行业的特色化产品,比如 WebSphere MQ Low Latency Messaging 是一款专门针对金融行业的中间件,用来满足高吞吐量、低延迟的业务需求。
而后三项讨论的并不多,但这些对于我们的应用来说又都是非常关键的。我会在后续的文章中逐一进行介绍。
采用某个概念非常简单,我们实际需要的是如何结合自身项目的实际需求,真正地利用这些概念背后那些好的思想。利用这些智慧结晶来解决面临的问题,这就需要大家多从实际出发来思考问题。很多时候,过多的概念只会让你更加混淆,我们真正需要记住的不是这些名词,而是这些名词背后的思想——这些在软件架构中一直被传承的东西