由 Marc Fiammante 编著的新书《动态 SOA 和 BPM:业务流程管理和 SOA 敏捷的最佳实践》描述了如何构建灵活的 SOA/BPM 系统的方法,这些方法是作者从多年来所参与的数十个 SOA 项目实施的经验中总结而来的。
包括:
- 为使动态 BPM 和 SOA 的企业架构更高效,要回答一下问题:
- “哪里需要灵活性?哪个企业目标要求提高动态性?”
- 驱动变更的企业业务优先级如何?变更的顺序是什么?最先改变的是哪些条件?
- 实施这种动态性的收益风险比怎样?有无内部赞助?
- 实现动态企业信息,探讨企业信息变更对 SOA 实施的影响。
- “尽管处理信息变更是 IT 界的家常便饭,我们仍致力于让信息变更产生的影响达到最小,特别是对服务接口所承载的在跨企业的业务流程中流转的信息。”
- 实现动态服务,探讨服务实现的模式。
- “实现服务动态性是降低服务消费者和服务提供者之间影响的关键。”
- 实现动态业务流程,探讨如何通过基于服务的自动化端到端的企业流程构建敏捷的企业。
- “企业必须快速有效地响应善变的市场需求、规定以及客户需求。在竞争激烈的市场中,他们必须盯着新产品。”
该书还涵盖了很多关于 IBM 的 SOA/BPM 工具的信息,这些信息可用于这些主要步骤的实现。
IBM 出版社向 Infoq 读者提供了本书的样章,这一章描述了如何确保流程动态性的技术。
为了更详细地理解本书背后的动机和理念,InfoQ 与Marc Fiammante 进行了一次访谈:
Infoq:虽然很多出版物有其他说法,但在本书中你认为 BPM 和 SOA 是紧密关联的甚至暗指二者应该捆绑在一起。你有考虑过单独实施 BPM 或 SOA 吗?
尽管你可以孤立地从 SOA 或者 BPM 的方法开始,但是请允许我强调一下 SOA 和 BPM 最好合在一起的前提条件。
首先,我认为 SOA 不该是 C/S 结构的方式或者面向对象的 Web 服务的方式,而是各业务派系间的业务合约性方式。该方式一方面保护了双方的所有权,因为他们既要实现各自合约的部分,又要将二者结合起来。
如果在设计流程时没有考虑所有权问题,而且具体实现也是自由的,那么所有派系的实现都会被全局地展示出来。其结果是多个派系或业务所有者在不同的生命周期中控制公共的模型。改来自任何派系的对流程元素的任何更,即便他们自己认为是私有的,也需要和其他派系进行磋商,而合约性方式则会降低对接口造成的影响。我经常使用火车作类比:火车工程师需要关心每节车厢里装的是什么吗?不需要,他们只需要关心这些车厢一节节连接在一起就好了,而把每节车厢中的具体事情交由相应的责任人即可。
将一节节车厢连起来就形成了一个隐式的(或抽象的)流程,好比一个灵活的流程应该有这样的能力:当一节车厢被替换成另一节车厢时不会对整列火车造成什么影响。
车厢之间的连接的实现如同灵活的业务接口,其具体实现即是灵活的服务。
回到 BPM 和 SOA,我们必须要辨别高层的端到端模型,它们必须要为(描述服务的)业务契约背后的私有的实现保留灵活度。
另一方面的考虑是流程交付和测试成本,它们与流程模型的圈复杂度成正比。我的经验是,对一个流程模型的变更,即便可能只涉及到流程的一小部分,也会导致大约半个人天乘以圈复杂度的测试工作。为了降低变更的成本,流程必须模块化。但仍然需要将流程模块或组件连接在一起。该连接一定不能传递变更,而顺理成章的方法就是通过定义灵活的服务进行连接。
Infoq:游击 SOA(guerilla SOA)的倡导者们认为全盘 SOA 化可能会招致灾难。你认为“基于项目的”SOA 实施是合理的起步吗?或者你是否认为 SOA 只有在企业级才能发挥真正价值?
我把 SOA 看成灵活性的缔造者,并且对我的客户这么说:“如果你不需要它,就不要用它”。考虑 SOA 的一种方法是:人们不会在一栋楼中的每个地方都放置扩展接合点,而是将接合点只放置在被连接体时常变化的那些位置。合理的起步项目甚至可以是一个只包含一个服务的小项目。我的印象中有两个简单的例子:第一个例子来是某汽车制造商,它们对“物料清单服务”进行评估,其第一年的投资回报率是几百万欧元,原因是该服务降低了原件损坏的保修费用。第二个例子是某邮递公司,他们有一个服务,它能够根据国家的差异(本地的,国际的,或者其他国家相关的差异)创建相应的邮包标签。
为了寻找 SOA 的价值在何处,我们通常要进行 OSIMM 成熟度模型评估,而且,通过该模型我们还能建立一个远景以及通往 SOA 价值的路线路。在第二阶段(下图中的 step 2)我们从小项目开始,建立业务价值和可行性。在稳固阶段(下图中的 step 3)我们将在已经明确的 SOA 业务价值的基础上寻找新的机会。
Infoq:在描述动态企业信息的方法时,你建议使用“xsd:any”以及(或者)名字 / 值对描述可变信息。这种方法所基于的前提是至少要对部分净荷(payload)进行客户化编组(mashalling)。那么,对整个文档进行客户化编组会不会更简单呢?你有其他 XML 设计方法推荐吗?
因为我们通常推荐 WS-I(作为互操作性和标准)和标准 J2EE JAX-WS(其前身是 JAX-RPC),所以我们默认这些标准包含了 JavaBean 的编组 / 反编组。一篇来自Sun 的文章明确表明xsd:any 将被当作 ajavax.xml.soap.SOAPElement
处理。
然而我并不推荐使用 xsd:any,但事实是工业标准(如 OAGIS)都使用它来实现可扩展性,客户也使用它。我个人更愿意使用电信管理论坛(TeleManagement)所使用的字符值模式(Characteristic Value pattern)而且它等同于 XML。
至于通过“xsd:any”带来灵活性,让我给你看一个例子,这个例子来自我的一个大客户。他们针对同一服务有三个 WSDL 文件:
1)客户端 WSDL; 2)企业服务总线(ESB)和注册库暴露的 WSDL,它用 xsd:any 获得更大的兼容性; 3)服务端 WSDL。
这 3 个 WSDL 文件都能装载兼容的 XML 净荷。该方法降低了服务提供端的更改所造成的影响,也使得该服务的先前版本与服务端的更新相兼容。
Infoq:参照 W3C Web 服务活动宣言,你写到,Web 服务为运行在各种平台或框架之上的不同软件应用之间提供了标准的互操作方式。但是 Web 服务并没有指定实际的业务数据交换,所以基本没有提供语义数据交换的能力。你是否认为在没有语义数据交换的情况下也能获得互操作和松耦合?
我的确认为 Web 服务的真正价值来自(服务双方)对由此服务承载的业务信息的一致理解。语义可以通过诸如 SAWSDL 等标准进行描述,或者它还可以是内含的,因为有行业上一致的用于整合的公开且灵活的信息模型:由美国联邦数据参考模型(US Federal Data Reference Model)命名的“数据共享”空间(“Data Sharing” space)。
所以,总的来说,如果所遵循合约性方法也解决了业务净荷问题,就能获得松耦合,但该方法并不需要通过 RDF 或者 OWL 捕获正式的语义。
Infoq:你在书中这样写到“从语义上,Web 服务就是某目标资源上的参数化状态转换请求”。这意味着二者在语义上等同吗?在你看来,他们有何区别?
在 Restful Web 服务的上下文中我是这么写的,而且是回答这个问题的:总能使用 Restful 服务完成用经典的 Web 服务干的工作吗?我的回答是:没错。我认为,如果资源有着清晰的定义,我们总能在 Web 服务操作、事件、动作和资源的状态转换之间找到语义等价。
例如:一个操作 transferMoney 也可以用创建 MoneyTransfer 资源的方式表示,而其内部的状态转换从已提交转变已完成。
将该方法扩展到正在进行中的工业标准,主要是 Web 服务的操作,一个动词(verb)和一个名词(noun)以及两个转换对象(请求对象和响应对象)。我将使用 OAGIS 9.3 的方法,用动词 + 名词来描述 Web 服务, http://www.oagi.org 。以下列表包含了 OAGIS 定义的实体(名词)上的 13 个动词。我在 OAGIS 动词旁边填入了相应的 REST 动词,如果有必要,还附加了承载状态的资源对象。
Acknowledge(PUT 一个应答对象); Cancel(DELETE); Change(POST); Confirm(PUT 一个确认对象); Get(GET); Load(PUT); Notify(PUT 一个通知对象); Post(PUT); Process(为响应的实体 PUT 一个指令); Respond(PUT 一个响应对象); Show(GET); Sync(向数据的所有者之外的用户 POST 一个更新)和 Update(向数据所有者 POST 更新)。
以下是 OAGIS 使用的名词,它们对应于各种对象,供参考:
ActualLedAllocateResource, AllocateResource, BOM, BudgetLedger, CarrierRoute, Catalog, ChartOfAccounts, ConfirmWIP, CostingActivity, Credit, CreditStatus, CreditTransfer, CreditTransferIST, CurrencyExchangeRate, CustomerPartyMaster, DebitTransfer, DebitTransferIST, DispatchList, EmployeeWorkSchedule, EmployeeWorkTime, EngineeringChangeOrder, EngineeringWorkDocument, Field, InspectDelivery, InventoryBalance, InventoryConsumption, InventoryCount, Invoice, InvoiceLedgerEntry, IssueInventory, ItemMaster, JournalEntry, Location, LocationService, MaintenanceOrder, MatchDocument, MergeWIP, MoveInventory, MoveWIP, OnlineOrder, OnlineSession, Operation, Opportunity, PartyMaster, Payable, PaymentStatus, PaymentStatusIST, Personnel, PickList, PlanningSchedule, PriceList, ProductAvailability, ProductionOrder, ProductionPerformance, ProductionSchedule, ProjectAccounting, ProjectMaster, PurchaseOrder, Quote, Receivable, ReceiveDelivery, ReceiveItem, RecoverWIP, RemittanceAdvice, RequireProduct, Requisition, RFQ, RiskControlLibrary, Routing, SalesLead, SalesOrder, SequenceSchedule, Shipment, ShipmentSchedule, ShipmentUnit, SplitWIP, SupplierPartyMaster, UOMGroup, WIPStatus.
Infoq:在你看来,除了 JavaScript 客户端之外,我们何时可以用 JSON 方式表示 REST 服务的净荷?
请参考这篇文章,你可以使用任何协商好的传输类型,XML、XHTM 都可以。我使用JSON 的原因是它提供了一种有趣而不同的信息描述方式。这篇文章称,“使用MIME 类型和HTPP Accept 头是一种内容协商的机制,这可以让客户选择那种数据格式最有益于他们,这样可以最小化服务和使用数据之间的耦合”。
Infoq:依据书中“通常,流程要使用流程模型标准(诸如 XPDL 或 WSBPEL 等)进行建模”,你认为这些语言是建模语言还是执行语言?
尽管 WSBPEL 是流程执行语言,XPDL 侧重于流程的交换格式定义,他们都被用作为流程模型交换的工具。然而他们都没有定义 BPMN 所定义的可视化符号。BPMN2.0 团队已经意识到该缺口,我也非常希望在不久的将来我们会拥有一致的符号模型,交换模型和执行模型。
Infoq:当谈到服务路由和业务流程时,你提到用于路由的业务规则以及基于策略的外部路由。是否需要一个服务注册库来存放动态路由规则呢?你能对这些不同的方法做个比较吗?
在 WebSphere Fabric 上,我们的确将路由策略存在注册库中,这样就有了存放动态路由的注册库了。然而我们有必要区分路由决策发生点以及路由策略存储点。注册库中的服务端点和策略信息通常缓存在执行路由的 ESB 中,而缓存效率模式以及路由计算是在总线上快速进行的,而并不需要通过远程交互在注册库中进行。
高效的基于内容的路由首先需要一个映射,它将上下文及内容映射成一种约定的结构,从语义上看它可以通过类 SBVR 的人类可读性语言( http://www.omg.org/spec/SBVR/1.0/ )进行访问。这些内容及上下文的分析带来的性能影响要求在本地内存中对策略和规则进行解析处理。
在下文一个真实的策略示例中你能看到,策略的粗体和斜体元素很容易被业务人员理解,而表面之下,它还包含对服务请求内容(如例子中的 Product, Triple Play)以及上下文(如例子中的 Channel, Web)的明确的指示。
对于Business服务的ActivateConnection
操作
When
Product is Triple Play AND Channel is Web AND Elite Status is Gold AND
Role is Self Service OR Customer is Residential Then
Use the Activate Fiber To Home Process
Infoq:在书中,你提出了关于限制业务流程所拥有的数据的重要问题,对此你能否给出一个更加具体的解释呢?
早期的流程建模方法是区别流程流以及数据流的。Web 服务和 WS-BPEL 的引入促成了控制信息和其他净荷信息的合并。尽管该合并在理论上允许你使用任何信息参与流程决定,我的业务流程分析方面的经验表明这并非事实。我建议在进行流程建模的同时也要进行业务信息建模。然后,在信息模型中清晰地标识出控制元素并创建仅包含这些控制元素的具体服务。
然后,标识出那些与“信息服务”相关的服务(即仅为净荷信息实现了 CRUD 接口而不包括任何控制部分的服务)。除 CRUD 接口之外,还可以增加这类操作,它封装了信息的分析逻辑并返回分析结果,该结果可被流程用来执行某些智能判断而不需要在流程中承载相关的信息。在流程组件被触发之前,调用者先用 “信息服务”的接口将信息持久化,而触发流程时仅需要包含最少量的控制元素。如果与流程交互的目标系统需要的信息不只是控制信息,那么可以使用总线上的仲裁模块(该模块在流程之外)在中间补充该系统所需的其他信息。
所以,如果净荷的分析发生变更,因为变更被封装在流程之外,它就不会影响到流程的生命周期。
Infoq:你在书中描述了两种方法(机会性事件驱动的方法和决定性服务调用的方法)之间的区别,你说:“如果事件的发起者希望在该事件发生后触发一个具体的动作,那这是一个严格的面向服务架构(SOA)的交互方式……而如果消息的发起者并不期望事件消息的特定行为,而如果监听者检查了该事件消息并进一步应用某些规则并决定是否对此采取相应动作,那这就是一个典型的事件驱动架构(EDA)”。另外,你所描述的 EDA 非常类似于(文中较早描述的)基于业务规则 / 政策的路由,所以,在 SOA 和 EDA 之间真的存在着重大的架构区别吗?
事件的确可以触发服务。从那个角度上看,这就是 SOA 与 EDA 之间的紧密联系。
在 SOA 中,尽管在服务的请求者和提供者之间可能要进行某些规则解析从而选择合适的提供者,服务的请求者对提供者的调用是直接触发的。而在事件驱动的架构中,事件源往往不是服务的请求者,而监听事件的“观察者”却可能成为服务的请求者,有时还有规则的加入。总之,在 EDA 中观察者是服务请求者;而在 SOA 中事件是请求者而不需要观察者。
这是为什么我称之为“机会性的”,因为观察者决定他们是否处理事件并触发服务,而事件的最初源头却不是服务请求者。事件源也许期望发生某些特定动作,但是不能控制事件链上的观察者。
常见的 EDA 设计模式是来自 GOF 模式中的观察者模式,而 SOA 通常使用桥接模式。当然,你可以将二者的设计模式连接起来。
Infoq:SOA 的信条之一是服务都是无状态的前提。无状态意味着一堆人做一堆事儿。当你写到状态以及状态管理时,“状态”指得是什么?会话状态?执行状态或是其他?
我喜欢称之为“适配状态”。为了让应用程序暴露粒度合适的服务,你得需要适配,而且需要的是尽可能与目标应用粒度匹配的适配层。无状态服务被暴露成可重用服务,这就是适配的结果。服务中不暴露状态。
Infoq:当谈及服务生命周期管理时,你谈到使用 WebSphere 服务注册与存储库(WebSphere Service Registry and Repository),而不是 Rational 资产管理工具(Rational Asset Manager)。你认为注册与存储工具也有相同的能力吗?你见过二者一起使用的情况吗?
是的,我看到二者一起使用的场景。而且,我甚至会用变更配置管理工具“Tivoli Change and Configuration Management Database (CCMDB) ”来配合他们的使用。
在开发中,一个软件项目包括一些除了注册与存储域之外的其他领域的资产,可能是项目计划、文档及开发指导、图片、演示文稿、测试计划、用例和需求等,几乎所有与项目相关的东西。在服务注册与存储中只存放在设计时、编码过程中和运行时与服务相关的那些元素。在CCMDB 中你还可以找到软件组件的更多信息,如中间件版本,硬件级别与配置等。
感谢胡键对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。
评论