在 Web 服务领域中的事务,第 1 部分(请参阅 参考资料 )一文中,我们介绍了为 Web 服务设计的分布式事务模型背后的技术概念,这些概念在 WS-Coordination 规范和 WS-Transaction 规范中定义。本文着重介绍适用于 Web 服务模型的业务事务的特定情形。
本文所讨论的两种主要类型是 原子事务(它是对特定服务操作的个别的事务调用)和通常由一个或多个原子事务组成的 业务事务。
图 1中的情形说明了使用 WS-Coordination 和 WS-Transaction 的标准事务服务(即数据库系统中常用的两阶段提交事务协议)的实现。图 1 显示了一个与数据库一起运转的简单应用程序,其中数据库操作发布为 Web 服务。IBM Web Services Toolkit(WSTK;请参阅
参考资料 )中包含了一个类似的情形,并展示了如何将
AddressBook 演示转换成支持 WS-Coordination 和 WS-Transaction 的。
图 1. 原子事务的情形
我们以事务的每个阶段分析这个示例情形,并详细讲述每个阶段中的步骤。这些阶段依次为: 激活(Activation)、 注册(Registration)和 完成/协调(Completion/Coordination) 。
第 1 步:应用程序使用 WS-Coordination 框架的激活服务创建一个事务活动。
CreateCoordinationContext 请求从应用程序被发送到激活服务,如
清单 1所示。
清单 1. 发送 CreateCoordinationContext 请求
<soapenv>
<soapbody>
<wscoor:CreateCoordinationContext>
<ActivationService>
<Address>
http://myActiviationService
</Address>
</ActiviationService>
<RequesterReference>
<Address>
http://myApplicationProgram
</Address>
</RequesterReference>
<CoordinationType>
http://xml-soap.org/2002/xx/AtomicTransaction
</CoordinationType>
</wscoor:CreateCoordinationContext>
</soapbody>
<soapenv>
|
协调服务返回用于唯一地标识事务的
CoordinationContext (还包含注册服务的地址),如
清单 2 所示。随后对 Web 服务的调用将使用这个
CoordinationContext ,
CoordinationContext 唯一地标识该请求代表哪一个活动。
清单 2. 协调服务返回一个上下文
<soapenv>
<soapbody>
<wscoor:CreateCoordinationContextResponse>
<RequesterReference>
<Address>
http://myApplicationProgram
</Address>
</RequesterReference>
<CoordinationContext>
<Identifier>
http://myCoordinationService/ts/activity1
</Identifier>
<CoordinationType>
http://xml-soap.org/2002/xx/AtomicTransaction
</CoordinationType>
<RegistrationService>
<Address>
http://myCoordinationService/tm/myRegistrationService
<Address>
</RegistrationService>
</CoordinationContext>
</wscoor:CreateCoordinationContextResponse>
</soapbody>
</soapenv>
|
第 2 步:应用程序使用
CoordinationContext 中指定的注册服务进行注册,如
清单 3所示。
- 应用程序将自己定义为负责驱动完成协议以完成活动的构件。
- 在协调服务中定义协调器角色(在调用中返回 CoordinatorRef ― 应用程序稍后用这个 CoordinatorRef 来调用完成协议)。
清单 3. 应用程序向注册服务发送注册请求
<soapenv>
<soapbody>
<wscoor:Register>
<RegistrationService>
<Address>http://myRegistrationService</Address>
</RegistrationService>
<RequesterReference>
<Address>http://myApplicationProgram</Address>
</RequesterReference>
<ProtocolIdentifier>
http://xml-soap.org/2002/xx/AtomicTransaction/Completion
</ProtocolIdentifier>
<ParticipantProtocolService>
<Address>http://myApplicationProgram</Address>
</ParticipantProtocolService>
</wscoor:Register>
</soapbody>
</soapenv>
|
注册服务返回协调服务的地址。
清单 4. 注册服务返回上述地址
<soapenv>
<soapbody>
<wscoor:RegisterResponse>
<RequesterReference>
<Address>
http://myApplicationProgram
</Address>
</RequesterReference>
<CoordinatorProtocolService>
<Address>
http://myCoordinator
</Address>
</CoordinatorProtocolService>
</wscoor:RegisterResponse>
</soapbody>
</soapenv>
|
第 3 步:应用程序执行 Web 服务上的一些操作
消息包含一个
CoordinationContext SOAP 头,资源(Resource)将用这个 SOAP 头来唯一地标识发出该请求的特定活动。
清单 4. 应用程序执行 Web 服务上的一个操作
URL:http//myhost/myBank
<soapenv>
<soapheader>
<wscoor:CoordinationContext
<wsme:Identifier>
http://myCoordinationService/ts/activity1
</wsme:Identifier>
<wsme:Expires>
2002-06-30T13:20:00.000-05:00
</wsme:Expires>
<wscoor:CoordinationType>
http://xml-soap.org/2002/06/AtomicTransaction
</wscoor:CoordinationType>
<wscoor:RegistrationService>
<Address>
http://myRegistrationService
</Address>
</wscoor:RegistrationService>
</soapheader>
<soapbody>
<debitAccount ... />
</soapbody>
</soapenv>
|
第 4 步:向注册服务注册一个资源以进行处理。
在第一次处理
CoordinationContext 时,资源要向 WS-Coordination 注册服务注册(使用前面第一次创建活动时给出的
RegistrationRef ),如
清单 5所示。
清单 5. 向注册服务注册资源
<soapenv>
<soapbody>
<wscoor:Register>
<RegistrationService>
<Address>http://myRegistrationService</Address>
</RegistrationService>
<RequesterReference>
<Address>http://myDatabaseWebService</Address>
</RequesterReference>
<ProtocolIdentifier>
http://xml-soap.org/2002/xx/AtomicTransaction/2PC
</ProtocolIdentifier>
<ParticipantProtocolService>
<Address>http://myResource</Address>
</ParticipantProtocolService>
</wscoor:Register>
</soapbody>
</soapenv>
|
第 5 步:注册服务接受
注册服务接受注册并返回协调器引用(
CoordinatorRef ),如
清单 6 所示,在万一碰到故障或恢复情况时,使用这个协调器引用来通知协调器。
目标也可以选择创建一个下级协调器(使用指定上级协调器的协调上下文的创建操作)。下级协调器向在接收到的协调上下文中所指定的协调器注册,资源向下级协调器注册。
清单 6. 注册服务发送协调器引用
<soapenv>
<soapbody>
<wscoor:RegisterResponse>
<RequesterReference>
<Address>
http://myDatabaseWebService
</Address>
</RequesterReference>
<CoordinatorProtocolService>
<Address>
http://myCoordinator
</Address>
</CoordinatorProtocolService>
</wscoor:RegisterResponse>
</soapbody>
</soapenv>
|
第 6 步:Web 服务执行操作并返回结果(请参阅 清单 7 )
清单 7. 服务执行操作
<soapenv>
<soapheader>
<wscoor:CoordinationContext/>
</soapheader>
<soapbody>
<debitAccountResult ... />
</soapbody>
</soapenv>
|
注:在响应中包含了
CoordinationContext 以允许在扩展元素中将信息返回 ― 某些事务实现会利用这种能力来返回特定于实现的信息。
根据需要,应用程序会向当前的 Web 服务或不同的 Web 服务发送额外的消息。
第 7 步:应用程序完成活动
应用程序完成活动并执行事务的
提交(Commit)(或
回滚(Rollback))请求(请参阅
清单 8)。从应用程序的角度看,假设一切都得到了满足,则应用程序就会在协调器上发出
Commit (AtomicTransaction/2PC 协议)消息,办法是使用从
CreateCoordinationContext 操作返回的
CoordinatorRef 。
清单 8. 应用程序执行 Commit
<soapenv>
<soapheader>
<CoordinatorProtocolService>
<Address>
http://myCoordinator
</Address>
</CoordinatorProtocolService>
</soapheader>
<wstx:Notification>
type=AtomicTransaction
portType=Completion
message=Commit
</wstx:Notification>
</soapbody>
</soapenv>
|
第 8 步:协调器执行协定协议
协调器执行协定协议(如 2PC 协议),协定协议首先通过
Prepare要求得知资源的状态,然后传递一个最终输出结果,这个输出结果会发送
Commit/
Rollback (2PC 协议)消息给每个已经注册的资源。在注册过程中,
ResourceRef 被发送,以正确定位需要被提交/放弃的资源实例。
清单 9. 发送 Prepare 消息
<soapenv>
<soapheader>
<ParticipantProtocolService>
<Address>
http://myResource
</Address>
</CoordinatorProtocolService>
</soapheader>
<wstx:Notification>
type=AtomicTransaction
portType=2PC
message=Prepare
</wstx:Notification>
</soapbody>
</soapenv>
|
第 9 步:资源发送 Prepared 通知 资源投票通过两阶段提交协议,然后将 Prepared 返回给协调器(coordinatorRef)。
清单 10. 资源发送 Prepared 通知
<soapenv>
<soapheader>
<CoordinatorProtocolService>
<Address>
http://myCoordinator
</Address>
</CoordinatorProtocolService>
</soapheader>
<wstx:Notification>
type=AtomicTransaction
portType=2PC
message=Prepared
</wstx:Notification>
</soapbody>
</soapenv>
|
第 10 步:协调器收集投票
协调器收集所有投票,确定事务可以被提交(请参阅
清单 11 )。
清单 11. 协调器发送 Commit 消息
<soapenv>
<soapheader>
<ParticipantProtocolService>
<Address>
http://myResource
</Address>
</CoordinatorProtocolService>
</soapheader>
<wstx:Notification>
type=AtomicTransaction
portType=2PC
message=Commit
</wstx:Notification>
</soapbody>
</soapenv>
|
第 11 步:资源接受 Commit
资源接受
Commit ,然后把 Committed 消息返回给协调器(
CoordinatorRef )。
清单 12. 资源发送 Committed 消息
<soapenv>
<soapheader>
<CoordinatorProtocolService>
<Address>
http://myCoordinator
</Address>
</CoordinatorProtocolService>
</soapheader>
<wstx:Notification>
type=AtomicTransaction
portType=2PC
message=Committed
</wstx:Notification>
</soapbody>
</soapenv>
|
本情形指明了对 Web 服务实现的几个基本要求:
- 在整个分布式环境中使用各方理解“一致”的激活服务定义(即包含标识符和协调器引用的上下文)。
- 能够建立和引用一个协调器(或多个协调器),即整个网络内都能理解的端点地址。
- (可选的 ― 未表明)通过减少网络流量提高效率,能够构造使用激活服务定义来控制分布式活动的某个部分的输出结果的子节点。
- (可选的 ― 未表明)能够通过将协议消息包含在常规应用程序消息流量中来优化流量。
- 上下文和端点之间的关联的确定关系(即,用来交换上下文和为目标 Web 服务建立执行环境的协定机制)。
业务事务情形(如 图 2 所示)说明了使用 WS-Transaction 的长期运行的事务(即业务活动协议)的实现。业务事务中的任务一般由多个原子事务组成。如果整个业务事务失败,则由原子事务执行的对资源的更新操作都必须被撤消。补偿是处理这种事情和实现业务事务协议的常用方法。下文讲解业务事务协议与原子事务协议在激活和注册时所需步骤的差别,并突出讲述在完成处理期间支持长期运行的业务事务所需的动作。
图 2. 业务事务情形
第 1 步:应用程序创建一个业务活动
应用程序使用 WS-Coordination 框架的激活服务创建一个业务活动。
CreateCoordinationContext 请求从应用程序被发送到激活服务,如
清单 12 所示。
清单 12. 应用程序发送 CreateCoordinationContext 请求
<soapenv>
<soapbody>
<wscoor:CreateCoordinationContext>
<ActivationService>
<Address>
http://myActiviationService
</Address>
</ActiviationService>
<RequesterReference>
<Address>
http://myApplicationProgram
</Address>
</RequesterReference>
<CoordinationType>
http://xml-soap.org/2002/xx/BusinessActivity
</CoordinationType>
</wscoor:CreateCoordinationContext>
</soapbody>
<soapenv>
|
第 2 步:协调服务返回 CoordinationContext 协调服务返回一个用来唯一地标识该业务的 CoordinationContext。在随后的调用中使用这个 CoordinationContext 来定义与随后的原子事务的关系。
清单 13. 协调服务返回一个 CoordinationContext
<soapenv>
<soapbody>
<wscoor:CreateCoordinationContextResponse>
<RequesterReference>
<Address>
http://myApplicationProgram
</Address>
</RequesterReference>
<CoordinationContext>
<Identifier>
http://myCoordinationService/ts/activity1
</Identifier>
<CoordinationType>
http://xml-soap.org/2002/xx/BusinessActivity
</CoordinationType>
<RegistrationService>
<Address>
http://myCoordinationService/tm/myRegistrationService
<Address>
</RegistrationService>
</CoordinationContext>
</wscoor:CreateCoordinationContextResponse>
</soapbody>
</soapenv>
|
第 3 步:应用程序创建一个活动
应用程序使用协调框架的激活服务来创建一个业务任务的活动,并使用创建(create)的扩展来指明
NestedCreate选项,
NestedCreate 选项指定了该业务任务与整个业务活动的关系(即这个任务是父活动的子任务)。这个创建指定完成第 1 步和第 2 步后得到的
CoordinationContext 。
CreateCoordinationContext 请求从应用程序被发送到激活服务,如
清单 14 所示。
清单 14. 应用程序发送 CreateCoordinationContext
<soapenv>
<soapbody>
<wscoor:CreateCoordinationContext>
<ActivationService>
<Address>
http://myActiviationService
</Address>
</ActiviationService>
<RequesterReference>
<Address>
http://myApplicationProgram
</Address>
</RequesterReference>
<CoordinationType>
http://xml-soap.org/2002/xx/BusinessActivity
</CoordinationType>
</wscoor:CreateCoordinationContext>
<CurrentContext>
<Identifier>
http://myCoordinationService/ts/activity1
</Identifier>
<CoordinationType>
http://xml-soap.org/2002/xx/BusinessActivity
</CoordinationType>
<RegistrationService>
<Address>
http://myCoordinationService/tm/myRegistrationService
<Address>
</RegistrationService>
</CurrentContext>
<myActivationService:NestedCreate/>
</soapbody>
<soapenv>
|
第 4 步:协调服务返回
CoordinationContext
协调服务返回一个用来唯一地标识该业务任务的
CoordinationContext 。在随后对该业务任务的 Web 服务的调用中将使用这个
CoordinationContext 。
清单 15. 协调服务返回 CoordinationContext
<soapenv>
<soapbody>
<wscoor:CreateCoordinationContextResponse>
<RequesterReference>
<Address>
http://myApplicationProgram
</Address>
</RequesterReference>
<CoordinationContext>
<Identifier>
http://myCoordinationService/ts/activity2
</Identifier>
<CoordinationType>
http://xml-soap.org/2002/xx/BusinessActivity
</CoordinationType>
<RegistrationService>
<Address>
http://myCoordinationService/tm/myRegistrationService
<Address>
</RegistrationService>
</CoordinationContext>
</wscoor:CreateCoordinationContextResponse>
</soapbody>
</soapenv>
|
第 5 步:应用程序执行 Web 服务上的一些操作
消息中包含一个业务事务的“
CoordinationContext ”SOAP 头,这个 SOAP 头将被资源使用。
清单 16. 带有 CoordinationContext 的 SOAP 头
URL:http//myhost/myBank
<soapenv>
<soapheader>
<wscoor:CoordinationContext
<sequence>
<CoordinationContext-Parent(Activity1)/>
<CoordinationContext-Child (Activity2/>
</sequence>
</soapheader>
<soapbody>
<debitAccount ... />
</soapbody>
</soapenv>
|
在活动的作用域内创建的任务形成一个分层结构。当 Web 服务被调用时,在操作中将包含描述关系的上下文信息。本示例显示在 SOAP 消息中包含
CoordinationContext 序列。
在业务任务的作用域内,原子事务的执行情况如前面讲述原子事务的部分所述。
第 6 步:业务任务向业务活动注册 在处理完对 Commit(来自原子事务部分,第 11 步)的状态响应之后,业务任务接下来就向业务活动注册。注册使得在碰到整个业务活动失败的情况时能够调用补偿操作。
清单 17. 业务活动失败时的补偿注册消息
<soapenv>
<soapbody>
<wscoor:Register>
<RegistrationService>
<Address>http://myRegistrationService</Address>
</RegistrationService>
<RequesterReference>
<Address>http://myBusinessTask</Address>
</RequesterReference>
<ProtocolIdentifier>
http://xml-soap.org/2002/xx/BusinessActivity/2PC
</ProtocolIdentifier>
<ParticipantProtocolService>
<Address>http://myResource</Address>
</ParticipantProtocolService>
</wscoor:Register>
</soapbody>
</soapenv>
|
第 7 步:注册服务发送一条响应
注册服务在注册响应中返回
bpCoordinatorRef 。
清单 18. 注册服务发送 bpCoordinatorRef 引用
<soapenv>
<soapbody>
<wscoor:RegisterResponse>
<RequesterReference>
<Address>
http://myBusinessTask
</Address>
</RequesterReference>
<CoordinatorProtocolService>
<Address>
http://myCoordinator
</Address>
</CoordinatorProtocolService>
</wscoor:RegisterResponse>
</soapbody>
</soapenv>
|
第 8 步:业务活动检查哪些任务已经完成
接下来,业务活动发出
Complete 以确定输出结果,从而确定哪些业务任务已经成功。
清单 19. 业务活动发出一条 Complete 消息
<soapenv>
<soapheader>
<ParticipantProtocolService>
<Address>
http://myResource
</Address>
</ParticipantProtocolService>
</soapheader>
<wstx:Notification>
type=BusinessActivity
portType=BusinessAgreementwithComplete
message=Complete
</wstx:Notification>
</soapbody>
</soapenv>
|
第 9 步:业务任务响应说它已经 完成(Completed)。
清单 20. 业务活动发送 Completed 消息
<soapenv>
<soapheader>
<CoordinatorProtocolService>
<Address>
http://myCoordinator
</Address>
</CoordinatorProtocolService>
</soapheader>
<wstx:Notification>
type=BusinessActivity
portType=BusinessAgreementwithComplete
message=Completed
</wstx:Notification>
</soapbody>
</soapenv>
|
第 10 步:(可选的)应用程序决定放弃事务
我们假设在这个例子中应用程序决定应该放弃整个业务活动,于是告诉协调器放弃该业务事务,我们从
bpCoordinator 处讲起。
清单 21. 应用程序放弃事务
<soapenv>
<soapheader>
<ParticipantProtocolService>
<Address>
http://myResource
</Address>
</CoordinatorProtocolService>
</soapheader>
<wstx:Notification>
type=BusinessActivity
portType=BusinessAgreementwithComplete
message=Compensate
</wstx:Notification>
</soapbody>
</soapenv>
|
第 11 步:(可选的)业务任务执行
补偿操作
业务任务执行一些恢复或故障处理以撤消原子事务的效果,从而完成补偿,然后接受
Compensate请求并将
Compensated 返回给协调器(
coordinatorRef )。
清单 22. 业务任务发送 Compensation 消息
<soapenv>
<soapheader>
<CoordinatorProtocolService>
<Address>
http://myCoordinator
</Address>
</CoordinatorProtocolService>
</soapheader>
<wstx:Notification>
type=BusinessActivity
portType=BusinessAgreementwithComplete
message=Compensated
</wstx:Notification>
</soapbody>
</soapenv>
|
事务是进行可靠的应用程序处理最基本的概念之一。Web 服务除需要传统的分布式和数据库事务模型所提供的行为之外,还需要有灵活的、可扩展的机制来对请求和输出结果进行控制。此外,对 Web 服务环境还有要支持协作(Collaboration)、持续时间很长的任务和跨企业的应用程序等特定要求。
WS-Coordination 规范提供了一个协调框架,这个框架提供了活动的创建、注册和协调方面的服务。这个通用框架提供了指定一个请求(或一系列请求)的操作上下文、控制活动的持续时间以及定义要得到某个输出结果需要哪些参与方的功能。
此外,WS-Transaction 提供了许多协调模式,这些模式在行业中通常用来容纳不同的应用程序:
- 原子事务:web 服务上的操作或者全部发生,或者根本不发生。
- 业务事务:web 服务上的操作表现为松散的工作单元,工作单元的结果在整个活动完成之前就可以被共享。补偿的语义是每个参与方会撤消它在对话期间内已经执行完的操作。
这些样式或行为机制绝不是到此就完事了。然而,它们允许参与到 Web 服务中的站点对站点现有的实现进行补充,以支持更复杂的处理和补偿模型。这些站点可以构建在它们的内部事务和业务逻辑环境的基础上。此外,协调服务框架将会考虑到传统事务模型以外的额外操作模式。
我们目前对 web 服务的唯一要求是能够让两个端点就输出结果达成协定。在使用自己的内部事务和工作流模型的企业内,可以使用多方“事务”处理来管理操作和与多个参与方的对话。
- 您可以参阅本文在 developerWorks 全球站点上的
英文原文.
- 请单击文章顶部或底部的
讨论参加关于本文的
讨论论坛。
- 请参阅这个共两部分的文章的第 1 部分
Web 服务领域中的事务,第 1 部分。
-
Web Services Toolkit可以在 alphaWorks 上获得。
-
使业务流程和事务自动化介绍了 Web 服务中工作流和事务的概念。
- 请阅读
Web Services Coordination规范文档。
- 请参阅
Web Services Transaction规范文档。
- The
Business Process Execution Language for Web Services规范定义了跨多个服务的工作流的更高级别的抽象。
- 这篇文章从技术上详细阐释了
在 Web 服务世界中的业务流程。
您可以通过 tjfreund@us.ibm.com与 Tom 联系。
您可以通过 tony_storey@us.ibm.com与 Tony 联系。