我要投搞

标签云

收藏小站

爱尚经典语录、名言、句子、散文、日志、唯美图片

当前位置:百万心水论坛 > 段提交协议 >

Web 服务事务处理协议的比较

归档日期:06-16       文本归类:段提交协议      文章编辑:爱尚语录

  developerWorks 中国 正在向 IBM Developer 过渡。 我们将为您呈现一个全新的界面和更新的主题领域,并一如既往地提供您希望获得的精彩内容。

  为了获得相互一致的结果,大多数工作流和企业到企业(business-to-business,B2B)协作应用程序都需要事务处理支持。事务处理支持保证输出结果在组成业务活动的应用程序中的所有任务间都能保持一致,这些任务包括了相应的业务活动。一个任务的执行结果一般在整个应用程序或活动结束前都能保持有效。例如,航班预订系统能在一段特定时间内为一个乘客保留某航班的一个座位,但如果该乘客没有在这段时间内确认这个座位,那么该座位应该重新收回,以便下一位乘客能够预订它。

  因此如果在这样的应用环境中使用传统的事务处理架构是非常困难的,甚至是不可能实现的。此外,现在大多数协作业务流程管理系统支持复杂的、长时间运行的程序, 然而为了能从流程运行失败后恢复或者选择流程中另外一种可以接受的执行路径,撤销那些已经完成的任务也是非常必要的。

  Web 服务专门用于促进系统互操作性。从事务管理的角度来看,这提出了一些非常有趣的问题,尤其是还存在这样的一个事实, Web 服务故意没有描述服务实现后面到底发生了什么:Web 服务仅仅关心各团体间结构化数据的传输,再就是一些元数据级信息,用它们来保护数据的传输(例如,通过对传输的消息进行加密或数字签名)。然而您会发现传统的支持业务活动的事务处理架构是在服务实现之后的。

  不过,Web 服务通过一个简单的设计方案,为解决一个非常重要的事务处理方面的问题(即互操作性)提供了可能。从有事务处理开始自今,已经有了各种各样的事务处理协议标准(如 X/Open 和 OTS,请参见参考资料),还要特定厂商的各种协议,以及许多相应协议的实现。然而,在这些不同的协议间进行协同工作已经证明问题多多,而且限制了事务处理实现的成功。Web 服务提供了一种方案来解决这些问题。

  这样是不是有点自相矛盾:Web 服务提供了面向服务的、松散耦合以及可能异步的方法来在不同团体间传输消息(请参见参考资料中的 WS-Security 和 BTP 资料),而基础服务又是使用传统的事务处理设计架构。此外,当从这些服务或资源中组合业务活动时,后端系统的事务处理与 ACID 特性构造在一起的事实可能导致一些问题,因为它给了那些团体一些机会来锁住相应的资源及阻止事务处理继续进行。因此,如果事务处理要在 Web 服务架构中的得到支持的话,显然这些问题需要重新解决。

  虽然我们会在后面更详细地分析这两个规范的不同之处,但是现在可以将它们之间的关键区别简单地分为以下两个方面:

  BTP 不是专门用于 Web 服务的事务处理协议,它的目的是它也能用于其他的环境中。因而,BTP 定义了事务性的 XML 协议,并且必须在规范中指定所有的服务依赖性。而 WS-C 和 WS-Tx 是专门用于 Web 服务应用环境,因此它是基于 Web 服务架构来定义的。

  WS-Tx 的实现原理是基于传统的事务处理架构的,这样,业务逻辑的功能性方面和在应用程序中使用事务处理的非功能性方面就存在很大的差别。BTP 基本上是从头开始制订的,需要在事务处理架构中加入业务级的决策。

  注意,在本文中,我们比较的是 BTP 1.0 委员会规范(ommittee specification)与 WS-C/Tx 规范的初级版本(preliminary version)。在后来的规范中,它们已经得到了一些行业反馈,并根据反馈在授权后做了一些修改。后面的规范已经征求了行业的反馈意见,如果得到授权的话,可能会做一些附加的修改。

  In 在本文中,我们将对这两个事务处理规范给出一个客观的分析,并且比较和对照它们采用的方法。因为已经有大量的文字来描述 OASIS BTP(请参见参考资料中的一些示例),我们不打算花太多的时间来描述这个协议,而将主要把精力放在 WS-C 及 WS-Tx 上,因为现在关于它们的资料非常的少。

  分布式系统引起了在原来集中式系统中不常见的可靠性问题的出现。分布式系统包括了大量通过网络连接起来的计算机,这种系统会遭受它的任何一个组件的单独失败,包括单独的应用程序及一些执行时间不确定的行为活动。分散允许系统的任何部分失败,而其他还保持运行,这有可能导致执行应用程序时出现异常行为。

  考虑这样的一个分布式系统,它的一个单独的计算机提供了选择一种有用的服务,这些服务可以被应用程序所使用。这是很自然的,一个使用了一组这样的服竦挠τ贸绦蛐枰庑┓竦亩饕恢拢踔猎诖砦蟪鱿质币彩钦庋R桓龇浅<虻サ囊恢滦孕枨缶褪?失败原子性(failure atomicity):应用程序要么正常结束并产生期望的结果,要么整个失败,而根本不产生任何的结果。如果出现失败,系统的状态怎样恢复到一些预订义的状态是一个典型的实现选择。传统的事务处理系统通过原子事务(atomic transactions)支持了这种失败原子性(failure atomicity)的特性。

  一个事务处理能以两种方式结束:提交(committed)或异常终止(aborted)(也叫取消(cancelled))。当一个事务处理被提交后,期间做的所有修改都将变成永久性的(保存到稳定的存储系统中,例如硬盘)。当一个事务处理异常终止时,在此事务处理期间所做的全部修改都将被撤销。让已经存在的事务处理系统协同工作是 Web 服务事务处理的一个非常重要的部分,因为这些系统已经是这些企业级应用程序的骨干了,并且将继续成为 Web 服务应用程序中的骨干。企业到企业的活动一般直接或间接地包括后端事务处理系统,而是否能把这些环境结合在一起对成功地使用 Web 服务事务处理来说是非常关键的。

  传统的事务处理系统一般称为 ACID 事务。ACID 事务具有以下特性:

  :事务处理成功完成(提交),而如果失败(异常终止)的话,则它的所有影响全都消失。

  :执行事务时产生的中间状态,对其他事务是不可见的。其他的事务即使事实上是同时执行的,但是它们看起来也像是逐次执行的。一般来说,要达到这个目的,可以锁住资源,使事务持久化,这样另一个事务就不能以相冲突的方式获得它们。

  传统事务处理系统利用两阶段协议来实现参与者之间的原子性,如所示。在第一个(准备)阶段,单个参与者必须使事务处理范围中出现的任何状态改变持久化,以便这些改变在事务处理结果确定之后就可以回滚或提交。假定在第一阶段中没有出现失败,则在第二(提交)阶段,参与者就可以“重写”在第一阶段中进行过持久化处理的状态。

  为了保持一致,两阶段协议必须是模块化协议:在返回了第一阶段的响应之后,每个已返回提交响应的参与者必须保持封锁状态,直到它接收到同伴的阶段2消息为止。在它接收此消息之前,其他的参与者都不能使用此参与者所用的资源,因为这样做可能会产生非 ACID 行为。如果在第二阶段消息传递之前同伴失败,则这些资源保持封锁,直到它恢复为止。

  虽然大多数典型的事务处理系统是 ACID 协议的实现,但是 ACID 事务的各种特性可以放宽到提供通称为扩展事务(extended transactions)的事务(请参阅参考资料中的 OMG Additional Structuring Mechanisms);例如,扩展事务处理模型可以将原子性放宽到允许部分参与者提交或异常终止,也可以将隔离性放宽到允许协作用户观察部分结果。“典型的” ACID 协议可以看作是此协议范围中结构良好的两阶段协议。正如您在本文后面将看到的,其他的协议(如 BTP 内聚功能和 WS-Tx 业务活动)都属于此范围,它与每个功能都有不同程度的关联。

  组合长期运行的 ACID 事务中的某些活动可以减少应用程序中并行操作的数量,也可以在失败的情况下要求重新进行操作。例如,有某些应用程序的类知道不必等到事务处理结束,就可以及早释放事务处理中获得的资源;另一方面,在事务处理取消的情况下,可能需要某些活动来讲系统存储为一致性的状态(可能执行补偿或反作用)。一般来说,这样的补偿和错误处理活动(它可能执行向前或向后恢复)是应用程序特有的,可能完全是没有必要的,或许由应用程序处理更有效。因此,扩展事务处理模型更适合长期交互。

  举例来说,我们考虑一个相对简单的安排旅行和布置会议的场景。特别是,与会者将需要飞往举行会议的城市,需要预订旅馆的房间,或许还需要租赁会议期间使用的汽车。

  在设置航班、旅馆和汽车租赁服务时,您需要保证在把旅行所需的预订组合成一个整体时可以保留合理的选择。同时,考虑到与会者的需要,服务提供者也需要有同样的自主性,并且对他们的资源保持(航班、房间和汽车租赁预订)控制。

  预订所需的各个要素是相互关联的,但是它们不必预先确定。显然,如果会议不是在本地举行的,在没有飞机的情况下,预订旅馆和租赁汽车就没有意义。但是在其他情况下,预订航班和旅馆可能有意义。不过,如果您预订的旅馆和作为会场的旅馆是同一个旅馆,则有可能不需要进行汽车租赁。

  此外,为了保持选择的自由,您可能会在预订大量航班的同时,寻找其他一些直飞选择或便利的旅馆。订户将要求提供多个报价以确定成本最低的承订者。因此,在一个典型的(ACID)事务中管理整个旅行安排是不合理的。让我们来想象一下,如果在个典型的(ACID)事务中管理整个旅行安排,则会出现这样的情况,或者需要做全部的工作,或者不需要做任何工作,不满足旅行代理的特定要求。例如,在访问多个航班预订服务时,可能需要有部分结果(放宽的原子性),而对于传统的 ACID 事务,它是不可能的。

  这一部分要解决的基本问题是,为了支持企业到企业交互,事务处理模型必须具有什么特性?要回答这个问题,您可能首先需要理解所谓业务事务(business transaction)指的是什么。

  业务关系(business relationship)是任何由两个或多个合作伙伴维持的分布式状态,它受到这些合作伙伴先前订立的契约的约束。因此,业务事务(business transaction)可以看作是合作伙伴之间业务关系的状态的一致改变。业务事务中的一方保存它自己的应用程序的状态,这种状态与它和事务中其他各方的业务关系相对应。在业务事务处理的过程中,这种状态可以改变。

  在 Web 服务领域,关于业务事务的信息是用 XML 文档进行传递的。然而,这些文档如何由相关各方(如电子邮件或 HTTP)可能是一个环境函数、业务关系类型、或其他业务或逻辑因素。

  活动(activity)是一项(分布式)工作,它可以是事务性的,也可以不是事务性的。在其存在的过程中,一个活动可以有事务处理时期和非事务处理时期。每个包含其他活动的实体都可以是一个活动的一部分,不过,一个活动不需要包含其他的活动。可以创建,接着运行,然后完成一个活动。已完成的活动的结局就是它的结果,可以用于确定接着发生的其他活动的控制流。

  任务(task)是一项短期活动,它可能比较符合更传统的事务语义。每个任务都可以运行在不同的分布式系统或域中,而一个任务内部组合可能有许多不同的机器/域伙子任务。如何实现任务来完成必要的工作对于应用程序并不重要。

  传统的事务处理系统中可用的结构化机制有事务的顺序组合和并行组合。如果应用功能表示为一个顶层事务,那么这些机制就是足够的。但是对于 Web 服务,情况常常不是这样的。顶层事务最适合被看作是短寿命实体(任务),对系统进行稳定的状态改变;它们不能很好地适合结构化长寿命应用功能(如运行几分钟,几个小时、几天 … )。使用传统系统实现的活动可能通过长时间占有锁,将系统中的并行操作减少到不能接受的程度;此外,如果这样的事务回滚,则已完成的许多有价值的工作可能被取消。

  活动可以与构成整个应用程序的许多独立任务一样是结构化的。这种结构允许一个活动仅在长期运行的事务性活动中所需的持续时间内获取和使用资源。图3对此进行了展示,其中,活动(用虚线椭圆显示)已经分成许多不同的并列任务。假定该应用程序活动涉及预订出租车(t1),预订餐馆的餐桌(t2),预订剧场的座位(t3),然后预订旅馆的房间(t4),等等。如果所有这些操作是作为一个事务进行操作的,那么在活动 t1 中获取的资源在顶层事务终止之前将不会释放。如果随后的活动 t2、t3 等等不需要这些资源的话,则它们对于其他客户端将是毫无用处的。

  另外,和传统的 ACID 事务不同,任务失败并不一定就影响整个操作。这种长期运行的应用程序通常这样来构造:可能需要某种形式的(特定应用程序的)补偿来尝试返回系统的状态以保持(特定应用程序的)一致性。例如,假定 t4 异常终止(图4)。进一步,假定活动可以继续进行,但是为了达到这一目的,现在必须撤销在 t4 开始之前(由 t1、t2 或者 t3)所做的状态更改。因此,新的任务会开始;tc1 是一个补偿任务,它将尝试撤销 t2 和 t3 所作的状态更改,一旦 tc1 完成,t2 和 t3 将继续该应用程序。tc5 和 tc6 是新任务,将在补偿行为之后继续进行;例如,如果没有预订剧院的可能,那么一张电影院的电影票可能会是与先前订购的餐馆和旅馆一起的可选事件。显然,其他形式的事务组合也是可能的。

  其实有多种方式可以满足上面列出的一些或者所有应用程序的需求。然而,相信“一概而论(one-size fits all)”的方式就足够了是不现实的,换句话说,一种扩展事务的方式不太可能适用于所有的应用程序(甚至是其中的主要部分)。但是在最后的实例中,一种事务性工作流系统,使用了脚本工具来表达操作的组合,包括补偿(一个工作流),这也许是最合适的方法;

  但是在最后一个示例中,一种事务工作流系统用脚本工具来表达带有补偿的活动的组合(一个工作流),这也许是最合适的方法;对于前三个示例,一个相对没那么精巧的解决方案也是很受欢迎的。

  随着 Web 服务已经发展成为了在企业间的层次集成流程和应用程序的一种方法,传统的事务语义和协议已经证明是不适合的,其原因已经在前面得到了阐述。基于 Web 服务的事务和传统事务的不同之处在于,它们以较长的周期运行,它们需要提交到有待协商的事务,并且隔离级别应该放宽。

  由于业务关系包含了通过某些关系相联系的各方的价值级别,所以它们之间达成某种级别的多数人意见(consensus)是非常重要的。在特定的业务事务中,并不是所有的的参与者都必须看到同样的的结果;一个特定的业务事务将拥有多个不同的多数人意见组(consensus groups),而每个组中的参与者都观察到相同的结果。另外,某些多数人意见组可能允许降低特定事务的原子性,允许部分参与者接收不同的结果。这种在一个组中的参与者列表的灵活性是扩展事务和传统事务的重要区别。

  此外,在需要的情况下,一个参与者退出多数人意见组也应该是可能的。为什么一个参与者不再愿意参与多数人意见组的决定的原因多种;例如,这个参与者所执行的工作可以全部安全地完成,而不用考虑多数人意见组的最终结果,或者在多数人意见组取消工作的事件中,某个单独的任务(一个不同的服务或领域)必须执行反操作。

  现在来看一下在图5中所描述的情形,其中有一个事务协调器和三个参与者。假定这些参与者中的每一个都处在不同于协调器或其他参与者的机器上。连接协调器和参与者的每一条线都代表从协调器到参与者的调用,反之亦然。

  对于协调器来说,参与者的实现是什么并不重要——尽管一个参与者可能与数据库交互来提交事务,而另一个参与者可能恰好愿意负责把协调器的消息发送到许多数据库中,但是本质上承担的都是协调器本身的责任。

  这种使用代理协调器(或者是从属协调器/子协调器)的技术被称为插入(interposition)。每个导入事务上下文的域(机器)都可能创建一个从属协调器,使导入的协调器加入进来,就像是一个参与者一样。由于种种原因(包括性能优化和安全性),插入是很重要的。每个从属协调器可以代表一个单独的域,负责它自己的安全性、协议桥等等。

  多数人意见组获得了参与者之间的一致的结果,但是仅为图片的部分。通常在企业到企业关系中,有这些组的层次结构(工作范围),在它们之间存在着父和子的关系。一般来说,在父参与者成功完成的情况下,由子参与者执行的工作是临时的;例如,父的范围可以为已完成的子范围执行反操作。

  要认识到父-子(活动-任务)范围并不等同于插入,这是非常重要的。在一种插入层次结构中,子节点只是在得知其上级节点完成时才可以完成。在一种嵌套范围关系中(比如嵌套事务),子范围将可以独立于它的父范围而完成,然后对父范围产生补偿需求。

  除了理解结果之外,一个业务事务的参与者可能需要支持事务处理过程中的临时或者暂定的状态更改。这些参与者也支持通过确认(最终有效)或者取消(反作用)来完成一个业务事务。一般来说,它表示确认还是取消业务事务中已完成的工作需要由参与者来确定。

  例如,一个应用程序可以选择执行更改来作为临时操作,并且使它们对其他业务事务可见。而与此同时,它可以存储必要的信息来撤销这些更改。如果确认,将可以简单地放弃这些撤销操作;如果取消,它可以应用这些撤销操作。例如,一个应用程序可以采用这种基于补偿的方法,也可以采用传统的回滚(roll back)方法。

  最后,对于任何 Web 服务事务处理协议来说,具有与现有事务处理系统的互操作性也是很重要的。这种系统已经构成了企业级应用程序的骨干,并且将继续成为 Web 服务应用程序的骨干。

  在下面几个部分,我们将讨论 BTP 和 WS-Tx 是否能够和如何解决这些问题。然而,在我们这样做之前,理解 WS-Tx 和 BTP 如何区分事务服务和事务控制的参与者是很重要的,如图6所示。

  :这种服务允许应用程序在业务事务的范围内进行工作。在应用程序指示事务服务提交或终止事务之前,工作的结果不是最终的。这样的对象的一个例子就是 Web 服务,它允许用户把物品放到购物篮中,如图7所示;只有当用户决定提交购买时,应用程序才提交事务,对购物蓝中物品的购买才会发生。从应用程序中分离出根据组成工作的任务/服务来编排结果的责任,并将这个责任移交给事务服务来控制。

  :这是指一种实体,它控制事务对象执行的工作的结果。例如,如果在线购物服务使用数据库来存储关于购物篮中的物品的信息,那么它一般将通过驱动程序来访问这种信息。SQL 语句将通过驱动程序发送到数据库进行处理,但是这些语句将是暂定的,当且仅当提交事务之后才会这么做。为此,驱动程序/数据库将事务和参与者关联起来,并且把结果通知给数据库。注意,在这种插入的情况下,参与者实际上是前面所述的协调器。

  下面总结一下前面几个部分讨论的内容,在 Web 服务中使用事务的需求意味着,任意 Web 服务的事务模型都应该支持以下功能:

  采用结构化的、定义良好的方式放宽 ACID 特性;严格的 ACID 特性,特别是原子性不适合所有的应用程序。所需的许多长时间的活动不是原子的“要么全有要么全无”(参见多数人意见组)。同样,在整个活动终止之前,任务的结果常常被公开(隔离性的放宽)。

  多数人意见组的灵活结果。例如,Open-flat,其中,事务的参与者将公开给业务逻辑,允许它定义工作单元和事务任务的关系;开放-嵌套(Open-nested),其中,在活动中有任务形成多数人意见组的父-子关系。

  参与多数人意见组的灵活性;如果一个任务决定它不影响结果处理,那么它就可以在结果处理之前离开活动(退出多数人意见组),也就是说,它它不会公开结果或引起副作用。

  活动和任务应该被定义为单个范围(多数人意见组),在它们之间有定义清晰的关系,这样,服务也可以清楚地划分责任。范围也允许由服务或者长期运行的操作执行的工作,被应用程序或者服务清除的划分。另外,范围的终止寄存在应用程序的域,并且它从

  驱动。这是范围和插入之间的另外一个重大区别,一个参与者(例如,映射为一个范围)可以自动离开一个操作(采用

  方式),并且,不会给予应用程序需要的控制来正确的管理范围。范围也允许应用程序或服务清楚地划分由服务或者长期运行的活动执行的工作。另外,范围的终止寄存在应用程序的域,并且它是

  BTP 是第一次跨行业的尝试,目的是为了制订一个用于 B2B 事务的 XML 标准。BTP 被设计成能支持在时间、空间和管理上都完全不同的应用程序,这样的应用程序因而也需要超出经典的 ACID 事务范围的事务处理支持。BTP 是一个协议,用于在松散耦合的软件服务之间编排业务流程,以获得来自参与的业务各方的一致结果。

  在 BTP 中,前面讲到的多数人意见组的概念可以通过定义的两种事务协议(原子和内聚)来得到。这两种事务类型都要求一个两阶段提交协议(two-phase completion protocol)来确保在参与者(的一部分)之间的原子性(您很快会明白我们的意思是什么)。在第一个阶段(准备(prepare)中,一个的参与者必须将在事务范围内发生的状态更改持久化,这样的话,一旦以后达成了多数人意见,这些更改就可以被撤销(取消)或进行持久化(确认)。

  尽管 BTP 使用两阶段协议,在 BTP 中并没有意味着ACID。这个完成协议只关注达成多数人意见。如何提供准备、确认和取消阶段的 参与者实现被交给后端决定。处理数据的一致性和隔离性的问题也由后端选择,而不利用 BTP 或通过 BTP 来假定;实际上,从使用 BTP 的参与者推断它作出的后端选择是不可能的;例如,没有策略框架(Policy Framework)(如在 Web 服务中)(参见参考资料),其中行为是用断言语句描述的(允许解释和使用工具)。

  因为迄今为止传统的 ACID 事务还不适合于所有类型的 Web 服务交互,所以这也相当不错的。然而,每件事情都留给后端实现选择负责,并且在协议中没有什么(隐式或显式地)用户决定可以作出什么决定。因此,判断分布式系统最终的正确是不可能的。举例来说,如果您想将 BTP 用于 ACID 事务,那么服务当然可以使用传统的 XA 资源管理器(如由 BTP 参与者封装的)。但不幸的是,在 BTP 中没有什么方式可以用于那些服务去通知外部用户,告知这是它们已经做的,这样,就可以在 BTP “ACID” 事务范围中安全地使用它们。

  因为传统的两阶段算法不会对执行第一个阶段和第二个阶段之间的时间加以限制,所以 BTP 采用了这种方法,通过它来允许在阶段之间插入业务逻辑决定。这意味着,在什么 BTP 称为open-top 完成协议方面需要用户显式地驱动两个阶段。应用程序完全控制了事务什么时候准备,并且不管使用什么样的业务逻辑,应用程序以后都可以确定确认或取消哪一个事务。准备成为了服务业务逻辑的一个完整部分。

  BTP 的Open top 完成是行业通常称为的 Open-flat。术语 Open-top 暗示有范围层次,但是实际上,BTP 并不支持范围嵌套,只支持插入(正如我们前面所看到的),这是不一样的。

  这是和传统的事务系统的重要差别,在传统的事务系统中,只允许一个应用程序告诉事务是提交(确认)或者是回滚(取消);事务协调器然后在返回控制(以及结果)给应用程序之前,执行整个两阶段协议。能够控制两个阶段,这意味着,参与者和它的操作所代表的服务必须紧密协作。告知协调器准备的行为一般由参与者反映为业务层次的决策,比如,保留一个航班的报价。在一个传统的事务系统中,在执行提交协议之前,必须发生保留行为,并且通知参与者准备实质上是试图使保留持久化(如将保留转为预订)。

  : 原子是一个典型的方式,其中,“事务性”工作是在有范围的 Web 服务上执行的。原子的结果是保证是原子性的,这样所有进入的

  )它。尽管初看起来,BTP 原子好像等同于原子事务:实际上不是。在后面的部分中我们将再次探讨这个问题,但是在这里提供一些简短的情况也是值得的。BTP 不把与现有事务系统的互操作性作为一个重要的因素。原子(隔离性、持久性等等)的语义没有像我们从原子性事务中所看到的一样精确地定义。

  ,允许基于高层业务规则来选择确认或取消工作。原子是内聚中的典型参与者,与原子不同的是,内聚可能提供不同的结果给它的参与者,这样,再它的参与者中,一些参与者可以选择确认,而其他的可以选择取消。在本质上,内聚的两阶段协议是参数化的,允许用户精确指定需要准备哪些参与者(原子或独立参与者),而需要取消哪些参与者。支撑内聚的策略是:它们更好地对长期运行的业务活动进行了建模,其中,服务进入了代表特定工作单元的原子。而业务活动继续时,它将遇到一种情况,运行它去取消或者准备这些单元,同时带有一个警告,提示在内聚到达它的最终决定之前有多少小时或者多少天,并且指定它的

  :为了使它成功地终止业务活动,它需要确认的参与者集。一旦确定了确认集,内聚将退化为一个原子:确认集的所有成员将看到同样的结果。如前所述,这正是一种对 Web 服务事务所需的多数人意见组的弱化。

  粗略一看,感觉这两种事务模型是截然不同的。然而,在效果上内聚是原子的功能父集:如果你有一个内聚协调器,那么您可以使用同样的实现来提供对原子的支持(但反之不然)。

  对于传统的两阶段协议,在事务(原子或内聚)中注册参与者没有指定的次序,理解这一点是很重要的。因此,一个协调器的实现可以自由地按照任何它希望的次序和参与者通信,而在 BTP 中不能执行任何需求和次序,所以应该被应用程序或者服务所避免。

  注意:在原子和内聚中的参与者是等同的,因此可以进入原子或内聚事务。传递给服务的上下文信息包含足够多信息使 BTP 中的参与者能够决定它们是否进入原子或内聚事务。

  在 BTP 中插入协调器是可能的。尽管在规范中没有禁止,但是在事务层次中这两种事务类型的混合将难以管理,简单的来说是因为原子和内聚的差别。实际上,尽管原子的插入是相当易于理解的(毕竟,它与传统的事务系统的插入类似),但是内聚事务协调器的插入并不是那么易于理解和管理,简单的原因是业务级的决定终止内聚的方式方面的作用非常重要。因此,举例来说,一个根内聚协调器告诉一个子内聚协调器去确认,是不是就意味着,所有与子协调器一起进入参与者都必须确认?这个答案依赖于根协调器确认了哪些其他的参与者,但是不幸的是,在标准的协议中,这种信息对于子协调器是不可用的。

  你在前面看到了,为何插入是 Web 服务事务的一个重要需求。然而,我们也讨论了,这种父-子关系(范围)的概念是重要的,特别是从不同的服务和领域构造规模的应用程序时更是如此。不幸的是,BTP 不支持嵌套的范围(嵌套的原子或内聚事务)。

  正如我们前面所讨论的,业务事务中的参与者需要在事务处理的过程中支持临时的或者是暂时的状态改变。这样,各方也必须通过确认(最终操作(final effect))或取消(反操作(counter-effect))来支持业务事务的完成。一般来说,这意味着,确认或取消在业务事务中所做的工作将由参与者来决定。正因如此,BTP 没有定义如何实现准备、取消或确认。这是重要的,因为 BTP 在传统事务的持久性和隔离性方面彻底放宽了,而这意味着,与传统事务不同的是,用户同时干预或查看部分结果是可能的。这种策略是在 BTP 的范围之外执行的,但是不幸的是,协议并没有提供标准化的机制来帮助开发人员和用户。

  能够控制终止协议的两个阶段之间的时间对 BTP 来说极其重要的。因为 BTP 中,没有包含关于参与者的准备、确认或取消操作的语义,所以它们一般变成为 BTP 中的业务逻辑的一部分。在 BTP 中,当告知一个参与者准备时,这意味着参与者可以执行一些业务逻辑。回到我们的航班保留示例:使用 open-top 完成协议,您可以访问每个航班预订中心(在它自己的原子中),并且询问报价;如果您希望在您决定最佳的选择之前保留报价,那么您必须准备相应的原子;而这个准备将需要理解您已经执行的工作(获得报价)的语义,然后将其翻译为暂定保留相应的座位。

  尽管业务级语义不需要和单个参与者操作相关联,但是显式控制阶段之间的时间通常被看作是 BTP Open-top 方法的主要优点。例如,应用程序有时间在可选的任务(在最终终止事务之前准备的)之间选择。然而,你将在后面看到,两阶段提交协议的开放,允许应用程序时间是“注入的(injected)”,这在 Web 服务环境中并未真正起到好的作用。

  BTP 采取一种有趣的方法来用于那些松散耦合的领域和长期运行的交互,这种方法就是,把限定符(Qualifiers)引入到协议中。可以把限定符看作是对与它相关联的协议方面的警告。实质上,限定符是一种在协议中提供附加扩展信息的方式。

  尽管 BTP 规范提供了一些标准的限定符类型(比如超时,一个参与者愿意在准备状态保留多长时间),还可能扩展它们来提供更适合应用程序或参与者的新的实现。显然,对非标准的限定符的任何使用或者依赖都将降低应用程序可移植性。

  不幸的是,尽管概念基础限定符是合理可靠的,但是它们的 BTP 实现是有缺陷的。造成这种结果的主要原因是:在某些情况下,限定符中包含的信息不是被能最好使用它的实体所用。例如,在 BTP 中有一个标准的限定符是在准备阶段使用,并且它允许参与者指定它将(或者能够)在在准备状态(和它可能将转变到的状态)中保留多长的时间。这个信息将传递给协调器,但事实上,是应用程序需要它。

  根据基本 BTP 协议,还有几种最优化是值得考虑的,特别从 Open-top 完成协议来看:

  :在传统的两阶段提交协议,除了在准备阶段指示成功或失败之外,一个参与者也可以返回一个

  响应;这表明,它不控制在事务处理过程中修改的任何工作,并且因此不需要告知事务处理结果。这使得两阶段提交协议可以快速完成,因为不需要第二轮的消息。在 BTP 中,与这相对应的是,参与者可以从加入的事务(原子或内聚)中退出。在任意时间,如果参与者已经准备好了,并且参与者在这一点表明不再对事物的结果感兴趣,这时候就会退出。退出可以发生在参与这已经准备的时刻之前的任何时候,而参与者可以用它来表示,它不再对事务处理的结果感兴趣。

  参与者自主决定(Autonomous participant decisions)

  :在一个传统的两阶段提交协议中,参与者进入一个事务,并且在它确认或取消之前,等待终止协议。在前面你已经看到,为了取得多数人意见,阻塞协议是必需的。现代事务处理系统为两阶段提交增加了

  ,允许准备的参与者做出关于它们将是提交还是回滚的单方面决定。显然,如果参与者所作的选择与其他参与者的不同,非原子性行为就出现了。BTP 也有等同的启发式(heuristics)概念,也允许参与者作出单方面选择。然而,与其他事务处理实现不同的是,该协议允许参与者提前告知协调器,决定将是什么和它将何时执行。参与者可以准备并且给协调器提出一些警告(前面提到的限定符(Qualifiers)),关于它将在此状态保留多长时间和它将转变到哪个状态(例如,“将在准备状态保留10天,然后将取消座位预订”)。然后,协调器可以利用这种信息来优化消息交换。尽管这看起来是一个好主意,但如前面所述,这种信息的理想端点是应用程序,而不是事务;不幸的是,BTP 没有为应用程序提供一种以获得这种消息的方式。

  :一般来说当服务调用发生时,参与者就加入到了一个 BTP 事务中。当服务请求完成时,就可以把响应发回到请求的发起者(initiator)。在一些情况中,将上述的许多消息组合成一个“单次(one-shot)”消息是可能的。例如,服务调用可能会导致状态改变发生,这意味着调用完成之后,参与者可以立即准备。BTP 允许把加入的请求和准备语句合并到服务响应中,而不必等待显式的协调器消息。然后,接收者负责确保此附加额外的信息已经发送到协调器(一个简单的操作是不够的)。

  :如果原子或内聚协调器在被告知确认时只有一个参与者,那么它可以告诉该参与者去确认,而不需要先前的准备。

  Web 服务的 BTP 方法也与您所期望的不同。一开始,技术委员会决定 BTP 应该用在 Web 服务之外。正因如此,BTP 不是 Web 服务专有的;它没有利用 Web 服务架构,没有包含 WSDL 或者携带者(carrier)协议绑定。这意味着,BTP 没有把需求放在特定的机制上,而是选择在事务处理协议中定义一个完整的服务栈。

  不幸的是,将 BTP 映射为一个特定的部署环境(如 Web 服务)可能意味着栈的某些方面是不必要的;也存在着这样的可能性,“本地”功能甚至将干扰事务协议。例如,前面所讨论的“单次(end-point)”优化意味着,允许把多个相关的 BTP 协议消息发回到在一个携带者消息的某个端点。现在的大部分 Web 服务基础架构已经透明地支持这种类型的优化(在发送者和接收者双方,来自于BTP 基础架构单次(one-shot)需求支持)。

  有趣的是,所有的 BTP 命令都是 XML 消息集,它是引导协议所需的。相关的各方如何交换消息集可能与环境(如电子邮件或 HTTP)、业务关系的类型、或其他业务或逻辑因素有关。该规范确实定义了 SOAP-over-HTTP 绑定,但不是强制性的。它不过是消息内容和消息顺序的标准化。

  让我们来看一看旅行代理场景,并且了解可以如何利用内聚,如图8所示。在本例中,旅行代理开始一个事务,并且预订一个到伦敦的航班。一种航班选择是 ALU 中的直飞,另一种航班选择有两程和两个不同的航空公司 ZA 和 Xantas。最终,旅行代理必须决定选择其中的一个航班——是直飞的 ALU 航班还是组合的 Xantas/ZA 航班。通过获得 ALU 航班或组合的 Xantas/ZA 航班的承诺,该旅行社可以决定选取哪一个,并且知道他们将总是得到他们决定的航班。

  如果您看一下某个调用(参见图9),您就可以了解到如何作出、管理和协调对终止的承诺。首先,旅行代理为它需要执行的工作创建一个业务事务(上下文(context))。然后,旅行代理还通过传递事务信息(上下文(context))来请求 和 ZA.com提供服务。

  )都同意参与这个事务(进入(Enroll))。在本例中,Xantas 还对事务(

  如图10所示,根据返回的价格,旅行代理决定继续并且预订由 Xantas 和 ZA 提供的两程航班(确认(Confirm) B,C)。因为 ALU 从来没有对业务事务(准备的(Prepared))作出承诺,换句话说,就是没有保留座位;所以没有必要取消 ALU 航班。

  图11表明,因为选择的航班涉及两方,Xantas 和 ZA,所以事务协调器将要求各方都对整个业务事务(准备的(Prepare))做出承诺。因为 Xantas 已经作了承诺,所以协调器只需从 ZA 得到一个承诺(准备(Prepare))。

  现在, composer 已经从和 得到了肯定的承诺,由旅行代理请求业务事务的请求部分。因此,composer 继续,并且确认由 ZA.com 和 Xantas.com 提供的座位保留,如图12所示。

  如果 ALU 已经作了承诺(准备的(Prepared)),那么 composer 就需要显式地取消 ALU 保留的座位(作为业务事务的一部分),同时确认 XA、Xantas 航班。composer 最后确认业务事务成功结束,并且结果返回到旅行代理(事务已确认(Transaction Confirmed)),如图13所示。

  正如您在本例中所看到的,在 BTP 中,因为业务逻辑是在事务协议中编码的,所以它实质上意味着,一个用户必须紧密地连接(甚至就是)协调器。业务信息,比如在一段特定的时间内参与者保持准备的(prepared)(如占用旅馆房间)的能力,将从参与者传递到协调器中,但在协议中没有任何事情允许该信息实际所属的应用程序/客户端过滤它。

  为了使用内聚, Web 服务需要公开关于参与者的后端实现选择。正如您所看到的,为了参数化两阶段提交协议,内聚的的终止器(terminator)很明显需要能够表示“准备 A 和 B 而取消 C 和 D”,其中参与者 A、B、C 和 D 已经通过服务(比如航班预订系统)加入了内聚(cohesion )。显然,这是编程人员很不习惯的地方,并且它违背了 Web 服务的正统。

  这一部分将分析 Web 服务协调和 Web 服务事务处理规范所使用的整个模型。这对理解 WS-C/WS-Tx 和 BTP 之间的区别是很重要的。

  协调是分布式系统的不同方面的需求,比如工作流、原子事务,高速缓存和复制、安全性、拍卖和 B2B 活动。例如,在编排中,可能需要协调多个 Web 服务以确保组成某个业务事务的一系列操作的正确结果。

  尽管有许多不同类型的应用程序需要协调,但它们一般都使用清单(Manifests) 作为不同类型的协调协议。例如,就事务来说,BTP、对象管理组(Object Management Group)、对象事务处理服务(Object Transaction Service)、Microsoft DTC 都是一些针对特定的问题域和那些不能应用于其他系统的应用程序(因为它们基于不同的架构)。即便这些协调协议是属于特定领域的,但是提供一个“统一的”协议而不降低效率和可伸缩性,也是不可能的。

  与 BTP 把协调绑到事务上不同,Web 服务事务处理协议利用了单独的协议,只针对结果决定/处理:Web 服务协调(Web Services Coordination)。支撑 WS-Coordination 的基础理念是:在 Web 服务环境中普遍需要协调基础架构。WS-Coordination 规范定义了一种框架,允许不同的协调协议插入到客户端、服务和参与者之间的协调工作中,如图 14所示。

  注意,单独显示 Control 信息只是为了说明客户端/协调器和服务/参与者之间的特定交互。这些消息仍然是 Web 服务消息,因此使用 SOAP 进行 传输。

  WS-C 和 WS-Tx 两者都只是用于 Web 服务,因而利用了现有的和正在制订的标准,比如 WSDL、WS-Addressing、Web Services Security 和 WS-Policyare(请参见参考资料)。这使 WS-C 和 WS-Tx 集中在 Web 服务环境,并且简化了规范,还可以把它们作为一个组件放在 Web 服务架构中。Web 服务架构的性能优化方面的任何进步都可以自动为这些规范所利用。

  为了跨大量分布式服务/任务进行协调,某些信息必须在用到应用程序的站点/域之间进行传输。这通常称为上下文(context),一般包含如下信息:

  可以通过传递上下文信息来提供分布式执行环境之的上下文流。这可以以对对客户端和应用程序服务透明的方式发生。如前所述,上下文是作为应用程序中的标准消息交换的一部分进行传递的(比如,作为 SOAP header 的附加部分)。

  WS-Tx 和 BTP 之间的重要区别在于:前者通过利用 WS-C 协议来区分事务性需求和协调,而后者把协调绑到事务上。为了更好地理解 WS-Tx 多于其他方法的灵活性的类型,下面几部分将分析 WS-C。

  协调是某个代理(协调器(coordinator))发送信息到许多参与者中以保证所有参与者得到特定的消息的行为。协调器也可以是一个参与者,它创建子协调器或者对等协调器(它们相互协作以进一步发送结果)的树。与 BTP 不同,插入(interposition)是 WS-C(和  WS-T)模型的完整部分。

  上下文信息在发给参与者的消息内隐式地进行传输(对应用程序透明)。对于正在执行的协调器类型,该信息是特定的,例如,它可以确定协调器、活动的其他参与者,失败情况下的恢复信息,等等。此外,也需要把其他的特定应用程序的信息(例如,额外的 SOAP header 信息)发送到这些参与者或适用它们的服务。

  WS-Coordination 定义了一种通用的协调框架,它支持任意的协调协议。WS-Coordination 在协调器级和上下文级都是可扩展的。例如,在需要的情况下,一个执行三阶段提交协议的协调器可以很方便地插入到 WS-C 实现中,并且还可以增强基本 WS-C 上下文。框架对于传递一个上下文类型的范围是很有用的,这些类型包括安全性、工作流或复制(replication)。

  WS-Coordination 规范通过活动来通信,它是分布式的工作单元,包括一方或多方(可以是服务、组件、甚至是对象)。在这个级别上,活动被最低限度地指定,因而可以简单地创建,再运行,然后完成活动。

  头三点直接与 WS-Coordination 有关,而第四点是在 WS-T 中定义的,通常客户端程序把这种应用程序作为一个整体进行控制。这四个 WS-Coordination 角色和它们之间的相互关系,如图16所示。

  WS-Coordination 框架展示了激活服务(Activation Service),激活服务支持为特定协议和它们相关联的上下文创建协调器。调用一个激活服务的过程显示为异步发生,所以,这个规范定义了激活服务本身的接口和调用服务的接口:激活服务可以回调来传递激活的结果,也即标识协议类型和协调器位置的上下文。

  通过在 WSDL 1.2 中指定“多样性(variety)”,WSDL 允许各种各样的交互。正因如此,WS-C 和 WS-Tx 支持交互模型而不是异步方式。

  这个异步方式降低了端点之间的紧耦合(这在其他环境中是经常看到的)。这种方式的优点是改进了容错性(fault-tolerance)、模块性(modularity)和部署考虑事项。例如,尽管一个客户端发送一个完成消息给协调器,这对发送给其他实体的响应也是有意义的。

  例如,尽管客户端可以发送一个完整的消息到协调器中,但是把响应发送到一些其他的实体中可能更有意义。

  一旦通过激活服务实例化了协调器并创建了相应的上下文,注册服务(Registration Service)也就创建和公开了。注册服务允许参与者进行注册,以接¥收与特定协调器相关的接收协议。与激活服务一样,注册服务假定以不通信,所以为注册服务和注册请求者指定了 WSD。

  一个上下文对于协调来说是关键的,因为它包含了服务参与到服务的必需的信息。它提供了线索,来绑定所有的应用程序的 Web 服务到一起,成为一个协调应用程序整体。因为 WS-Coordination 是一个通用的协调框架,上下文必须修改来满足插入到框架的特定协调协议的需求。WS-Coordination 上下文的格式是专门设计,可以为第三方扩展,它的内容如下:

  对于协调来说,上下文是至关重要的,因为它包含了服务参与到协议所需的信息。它提供了一条线索,可以用来把所有组成应用程序的 Web 服务绑在一起,使之成为一个协调的应用程序整体。由于 WS-Coordination 是一个通用的协调框架,所以必须修改上下文,以满足插入到框架中的特定协调协议的需要。WS-Coordination 的格式专门设计成第三方可扩展,而它的内容如下:

  这些内容示于图17中,Schema 声明了以下几个部分:一个上下文,包含一个 URI,它惟一地标识了需要的协调类型(xs:anyURI);一个端点,协调的参与者可以在其中注册(wsu:PortReferenceType);一个可扩展元素,设计成能携带特定协调协议上下文有效载荷(xs:any),它可以携带任意的 XML 有效载荷。

  前面我们讨论了 OASIS 业务事务处理协议(Business Transactions Protocol)如何协调原子或内聚事务中的参与者以取得多数人意见。定义在 BTP 规范中的协议是 Open-top、两阶段完成协议。然而,在 BTP 中并没有把事务和协调分离开来,并且所有这些协议都假设为两阶段的。假设要更改协调协议的类型(比如,更改为三阶段协议),那么就需要对规范做非常大的改动,并且会影响到协调和事务的所有方面。

  WS-Transaction 规范集成到了 WS-C,并且提议了两种通用的行业完成模式(即专门的协调协议),其中每一个都支持一种特定类型的企业到企业交互的语义学:

  :它的意思是映射到现有的事务处理标准,这些标准有原子性(格式良好和两阶段)、隔离性(没有脏读及重复读)以及持久性(没有数据丢失)的定义良好的行为,换就话说就是传统的 ACID 语义。在考虑 Web 服务时要重点记住的是,它们把互操作性看得与 Web 一样重要。过去要使一个传统的事务处理系统与另外一个交流是非常神圣的(即很难很难实现),也是很少能实现的。而在这一点上,Web 服务提供了对互操作性无可比拟的支持。传统的事务处理系统已经构成了企业级应用程序的骨干,并且将继续成为 Web 服务应用程序的骨干。企业到企业活动一般会直接或间接地包括后端的事务处理系统,而且是否能把这些环境连接在一起对成功使用 Web 服务事务处理(请参见参考资料,查阅 Vasters 的有趣讨论和关于互操作性的资料)是非常关键的。最后,如果仅需要用在内部环境,而在这个环境里用户需要合并大量内部应用程序的操作,那么AT 将是非常有用的。例如,合并可能需要把新旧业务的应用程序组合到一起。

  :它提供了灵活的事务处理特性,主要是为需要长时间的交互设计的,在这些交互中完全控制住资源是不可能的,也是不现实的。在这个模型里,服务需要做一些工作(如预订某个航班的座位),而且如果它们能以一种那些工作以后能被取消的方式做这些,那么服务就可以通知 BA。使用这种方式时,如果 BA 后来决定要取消那些工作,它就可以通知服务。服务如何完成它们的工作以及提供补偿机制(compensation mechanism)都不是 WS-Tx 协议涉及的范围:这是服务提供者的实现决策。

  BA 模式来源于 BPEL4WS 规范(请参见参考资料,查阅 BPEL4WS 规范)中的一个专门的行业需求,注意到这一点是非常重要的。虽然 ATs 与 BAs 对规范针对的当前用况(use case)可能是足够的,但是能接受以后需要的其他协议也是必要的。因为 WS-Tx 利用了 WS-C,新的协议在需要时能添加到规范中。 这样 WS-Tx 规范在需要新协议时能变得更大。

  这是到现在为止 WS-Tx 与 BTP 之间的另外一个重要的区别:尽管 WS-Tx 允许存在以后或许需要支持“one-size doesn’t fit all”和其他协议的可能性,但 BTP 规范本质上还是封闭的,而且受到了它的两阶段协议的限制。通过显式地将 WS-C 和 WS-T 中的协调和事务处理分开来添加新的事务处理协议应该是相当简单的,并且不会影响到已有的协议。但不幸的是,要在 BTP 做相同的这件事可能会导致产生一个全新的协议,因为现在的所有协议都依赖于两阶段完成协调。

  WS-Transaction 不同于传统事务处理协议的一个重要方面,就是不需要同步的请求/响应模型。在这个模型中,如图18所示,WS-Transaction 位于 WS-Coordination 协议之上,而 WS-Coordination 的通信模式在缺省情况下是异步的,不过它可以支持其他的交互模式。

  WS-Transaction 利用了 WS-Coordination 以两种方式提供的上下文管理架构。其一,它扩展了 WS-Coordination 上下文来创建一个事务处理上下文。其二,它通过其他的一些服务增加了激活(activation)和注册服务,这些服务包括:

  以及两个协议消息集(分别对应于 WS-Transaction 支持的事务处理模型)。

  原子事务处理(AT)协议就是一个多数人意见组,在这个组的参与者中执行一种严格的原子性。说原子事务违反了 Web 服务之间的“信任分裂(trust chasm)”是错误的(请参见相关主题,查阅 ObjectWatch 资料),因为这忽略了使用 AT 的主要原因:互操作性和短时间交互。传统的事务处理系统在 Web 服务中还是可以占有一席之地的,而这正好是原子事务处理所关心的。

  要开始一个原子事务处理,客户端应用程序可以定位一个支持 WS-Transaction 的协调器。一旦定位到,客户端就会发送一个 CreateCoordinationContext 消息给活化服务,指定 作为它的协调类型,然后返回一个适当的 WS-Transaction 上下文。事务处理上下文把它的 CoordinationType 元素的命名空间设置为 WS-Transaction AT,而且它也包括了一个对原子事务处理协调器端点(WS-Coordination 注册服务)的引用,通过这个端点,参与者可以加入进来。

  从协调器那里得到事务处理上下文后,客户端应用程序就继续与 Web 服务进行交互,以便完成它的业务级工作。对于业务服务中的每个调用,客户端都会传送上下文,这样事务处理就可以隐式地确定每个调用的范围。

  一旦所有必要的应用程序级工作都完成了,客户端就会终止这个事务。为了达到这个目的,客户端应用程序为 Completion 或 CompletionWithAck 协议注册它自己的参与者。一旦注册好,参与者就能指导协调器试着提交或回滚这个事务。

  如前所述和图1所示,事务处理终止通常使用两阶段提交协议(2-Phase Commit,2PC)。由于使用 BTP,所以没有 WS-Tx 协议表示的 2PC 参与者调用的排序。如果事务仅涉及到一个参与者,那么 WS-Transaction 就支持一阶段提交最优化,与传统事务处理系统(和 BTP,正如您在前面所看到的)中的一阶段提交最优化类似。既然只有一个参与者,那么它的决定默认就是多少人意见了,所以协调器不需要通过两个阶段来驱动事务。在优化情况下,参与者只是简单地被告知要提交决定,而且事务协调器也不需要记录关于决定的信息,因为事务处理的输出结果仅仅需要传送给这一个参与者。

  图19显示了一个 WS-Transaction 原子事务的状态转换和协调器与参与者之间的消息交换。协调器生成的消息以实线表示,而参与者生成的消息以虚线表示。

  一旦协调器完成了事务协调,最初开始终止事务的 Completion 或 CompletionWithAck 协议就可以完成,并且通知客户端应用程序事务是提交还是回滚(roll back)。注意,CompletionWithAck 协议要求,在协调器接收到从参与者发送回来的通知确认之前,它必须记住结果。

  除了 2PC 协议之外,WS-Tx 还提供了另外两个协议:PhaseZero 和 OutcomeNotification。访问持久性存储器(不管它的实现)常常是性能瓶颈(performance bottleneck),因而,把对象的状态(如整个数据库)存储在高速缓存中并对事务持久性的高速缓存状态进行操作来代替不断地往返数据库,可以大大提高性能。

  在传统的事务处理系统中,这是通过同步参与者(synchronization participant)来完成的。当一个事务将要(about)提交时参与者会被同步通知。它们也会被通知事务是否已经完成以及在什么状态下完成。使用同步本质上就是把两阶段提交协议变成四阶段协议:

  当一个原子事务正在终止时,如果有任何参与者注册在它的上面,那么与它关联的协调器首先执行 PhaseZero 协议。所有 PhaseZero 参与者都会被告知事务将要完成,而且它们可以响应 PhaseZeroCompleted 或错误消息。该阶段的任何失败都将引起事务回滚。

  另外,一些服务可能已经注册了有完成事务的兴趣,在 2PC 完成之后,将通过 OutcomeNotificato 协议通知它们。在事务终止之后,所有注册的 OutcomeNotification 参与者都将被调用,并且被告知事务完成的状态(协调器会发送提交的(Committed)或异常终止的(Aborted)的消息)。由于事务已经终止,所以此阶段任何参与者的失败都会被忽略 ——OutcomeNotification 实质上是礼节性的通知,而与事务的处理结果没有关系。

  存在完全不同的同步和两阶段提交协议,这个事实对于 AT 的重要性并不亚于传统事务处理系统。如果能够依赖特定类型的参与者的调用次序,那么性能将大大得到优化,比如支持高速缓存。

  正如您前面所看到的,BTP 仅有一种类型的参与者可以加入原子或内聚事务,而且它们都不支持任何一种相对排序(relative ordering)。因此,要在 vanilla BTP 的范围内提供一个等同于同步协议的协议是不可能的。

  最后,当完成了 AT 的各个阶段之后,您现在就可以看到各个错综复杂的协议,它们构成了整个 AT,如所示。

  在 AT 模型和 BTP 原子模型之间要另外一个基本的区别,而且它经常会被比较:终结协议(termination protocol)不是Open-top 协议,因此明确地定义了参与者与服务之间的区别。终结协议没有把业务级的决定混合到提交协议(commit protocol)中,例如,参与者接收一个准备请求可能就意味着超载(overloading)。

  如果这项工作是在一个事务(我们假设它是一个原子事务)的范围内执行的,那么应用程序与事务之间的交互应该会很少——事务协调器仅仅需要访问参与者,而且它们应该不需要与它们的操作所代表的服务进行强交互(strong interaction)。

  在一个航班预订服务场景中,业务级(即服务)方法(如座位预订)已经进行了必要的工作(如暂时保留座位)。Open-top 协议的隐式准备操作是很简单的,不需要有业务语义学。Open-top 方法的一个假定优势(即允许在两阶段之间有一定的决定时间)是不必要的。当应用程序决定终止业务事务时,它希望这个立即发生(或不发生),而需要具备的全部条件就是要保证所有参与者之间意见一致。

  为了保证一致的结果和正确的执行,大多数企业到企业应用程序都需要事务支持。这些应用程序经常涉及到长时间运行的计算、松散耦合的系统以及不能共享数据、位置或管理的组件,因此要把原子事务整合到这样的架构中是非常困难的。例如,一个在线书店可能在指定的一段时间内为一个人保留一些书,但如果这个人没有在这些时间内买这些书,这些书将需要“放回抽屉”,供其他人购买。此外,让任何人都有一个无限的库存供应(supply of stock)是不可能,为此有些在线书店可能允许用户保留一些书,但事实上书店也允许其他人抢先占有这些预订,也就是说,同一本书可能同时被多个人“预订保留”。然后用户可能随后发现他预订的书已经没有了,或者他们如果想得到这些书,可能需要重新排队。

  业务活动(BA)就是专门为这种需要长时间的交互而设计的,在这里独占式地锁住这些资源是不可能的,或者是不实际的。在这个模型里,服务需要用来执行这些工作,这些服务有能力取消任何执行了的工作,它们会把执行信息通知给 BA,以便当 BA 决定取消这些任务时,BA 能指导服务执行取消操作。

  虽然整个的 ACID 语义学不是由 BA 维护的,但是一致性还是通过补偿来维护的。不过,编写正确的补偿动作(并因此而实现整个系统的一致性)的任务交给了在 BA 控制下的服务的开发人员。这样的补偿可能会使用向后错误恢复(backward error recovery),但是一般将采用向前恢复(forward recovery)。

  WS-Transaction 的业务活动(Business Activity)简单地为基于 Web 服务的应用程序定义了一个协议,使得现有的业务处理和工作流系统能封装它们自己的机制,并且跨各种实现和业务边界(business boundaries)进行互操作。

  WS-Tx 的重心是使用范围(scope)的概念,以及定义活动到任务(activity-to-task)的关系。一个业务可以部分加入到范围中,在这里一个范围就是使用了一组 Web 服务的一个业务任务或工作单元。这样的范围可以任何层次地嵌套,并形成父的或子的关系。一个父范围可以为一个专门的业务活动选择一个子任务到整个的结果协议中,所以很明显,非原子的结果是不可能有的。一个业务活动(BA)定义了一个多数人意见组(consensus group),它允许基于业务级的决定原子性松散。使用与传统内嵌事务相似的方式,如果子任务遇到了错误,那么父任务可以捕捉该错误,并且有可能能够加以补偿,然后继续进行处理。

  如您前面所看到的,虽然 BTP 支持插入(interposition),但它还是不支持范围嵌套。 这是 WS-Tx 的业务活动(BA)与 BTP 之间的一个非常重要的区别。嵌套范围是非常重要的,其原因有很多,包括如下两点:

  :如果子范围失败了(例如,一个正在使用的服务失败了),这不需要包含它的父范围也失败,从而也不需要取消全部至此进行的工作。

  :当一个新范围开始时,如果已经有一个范围与调用关联了,那么这个新范围会嵌套到这个已经关联的范围里。因此,那些知道服务需要范围的程序员会在服务中使用这些范围。如果调用的方法没有父范围,表示这个服务的范围是顶级的,它们将嵌套在客户端范围内。

  当一个子任务完成时,它可以离开这个业务活动,或者发一个信号给父范围,说它完成的任务可以在以后进行补偿。之后的情形是,可以被父范围调用的补偿任务最后需要取消子任务执行的所有操作。

  不像原子事务协议模型,仅仅当被要求时,参与者才通知协调器它们现在的状态,BA 允许业务活动的一个任务能直接指定结果给父范围,而可以不需要等待一个请求后才这样做。 当任务失败时,这个特征是非常有用的,因为它允许业务活动异常处理器去通知更新目标并使处理继续往前进行,而不是一味地等待,直到事务结束才允许失败(一个设计良好的业务活动(BA)应该具备前瞻性),如果它将需要执行的话。

  所有的状态转换都可靠地记录下来了,包括应用程序状态和协调元数据(发送和接收消息的记录)。

  所有请求信息都被确认了,以便问题能尽早被发现。这就避免了执行不必要的任务并能在矫正时更早地发现错误,这些都是非常简单的,而且资源耗费也很少。

  因为使用原子事务,一个响应被定义为一个分离的操作,而不是作为请求的输出。消息输入输出实现一般都会出现超时,而这些超时对一些业务活动来说是太短了。如果超时后响应没有收到,它会被重发。这个动作一直重复,直到响应被收到为止。请求接收者丢弃了所有的请求,但且接收另外一个完全相同的请求。

  因为使用原子事务,业务活动模型有多个协议:BusinessAgreement 和 BusinessAgreementWithComplete。然而,它不像 AT 协议那样从协调器向下到参与者驱动,这个协议更多是从参与者向上驱动。

  在 BusinessAgreement 协议下,一个子活动最先在活动状态下创建。如果它完成了创建要做的任务,而且没有其他更多的参与者需要在 BA 范围中(例如当活动在永久性数据上操作时),那么子活动能单方面发送一个已退出消息(exited message)给父活动。这相当于从业务事务退出的参与者,在 BTP 中也是支持的。然而,如果子任务完成了,并且想在 BA 中继续,那么它必须能补偿它已经完成的任务。如果它发送一个已完成消息(completed message)给父活动,并且等待从父活动接收 BA 的最后结果。这个结果可以是一个结束消息(close message),意味着 BA 已经成功地完成了,也可以是补偿消息(compensate message),表示父活动需要子活动恢复它做过的工作。

  除了在业务活动中子活动不能决定结束它的参与者之外(即使它可以进行补偿),BusinessAgreementWithComplete 协议与 BusinessAgreement 协议是完全一样的。但是,在子活动收到了所有要求它执行任务的请求时,子任务可以依赖于父活动来通知它。父活动通过发送一个完成消息到子任务来达到这个目的。然后,子任务就可以与 BusinessAgreement 协议中一样的事情。

  因为使用 AT 模型,另外一个在 BA 模型与 BTP 内聚模型之间经常比较的基本区别是,它没有把业务级语义学与事务协议混合在一起。使用 BA 方法的理由是它非常类似于传统工作流系统中所做的以及当今编写的大多数 Web 服务:补偿工作被简单地看作是另外一个活动,并没有什么特殊之处。需要补偿的工作补救已经在服务中提供了(如取消预订座位),而且很显然,预订座位以某种方式完成了这项工作(但是在应用程序确认座位预订之前,这很可能是暂时的)。

  大多数工作流系统没有把补偿活动(compensate activities)与向前继续活动(forward progress activities)区分开来:一个活动就是一个活动,它都要完成一些任务。如果那个任务碰巧是对以前任务的补偿,那它就是补偿活动了。另外,您会发现大多数服务已经有写在它们的定义中的补偿操作,像“取消座位预订”或“取消假期”,它们不需要被其他一些事务/协调引擎来驱动,这些引擎发送“准备(prepare)”或“提交(commit)”或“回滚(roll back)”给参与者,然后它(参与者)不得不指出怎样与服务交谈以完成相同的目标。

  WS-Tx 协议有几种最优化方法是值得考虑的,特别是根据 BTP 的协议:

  :正如您前面看到的,在传统的两阶段(two-phase)提交协议中,参与者也能返回一个

  响应,表示它没有控制任何在事务过程中更新的任务,这样它就不需要接收到结果的通知。原子事务协议支持这种优化。

  灵活的多数人意见组(Flexible consensus groups)

  :正如您前面所看到的,原子事务处理协议与 ACID 语义学一起提供了严格的、原子的多数人意见组。业务活动(BA)协议定义了允许减弱原子性的多数人意见组。另外,因为那些能在 BA 协议中形成的活动范围关系,把任务描绘进不同的多数人意见范围变得更容易了。

  :在业务活动(BA)中与只读同等的是参与者能从活动中放弃(退出)。这有点类似于 BTP 的参与者放弃最优化。放弃可以在活动正在完成的那一刻之前的任何时间发生,参与者使用它来表明它不再对 BA 的结果感兴趣。

  参与者自我决定(Autonomous participant decisions)

  :因为原子事务协议是基于传统事务协议的,它允许参与者对它们自己的最终结果做自我决定。如果这些决定是在事务开始结束之前做的,那么这种决定可能导致非原子(non-atomic)的结果,而且这个以后必须解决。

  :不同于 BTP,WS-C 和 WS-Tx 协议主要基于 Web 服务架构中的实现来提供协议最优化(例如单次)的实现。这个不应该看成是 BTP 的不足,而更应该是一个把 WS-C 和 WS-Tx 放进一个单一的部署领域中的特性。这种类型的最优化最好能被其他架构层处理。

  :原子事务处理(Atomic Transaction)协议支持一阶段提交优化。

  : 该协议需要的其他限定由 WS-Policy 进行处理,其中策略(Policy)是告知操作特征的标准化机制。

  正如我们已经提到的,Web 服务协调(Web Services Coordination,WS-C)和 Web 服务事务处理(Web Services Transactions,WS-Tx)是完全属于 Web 服务架构的。正因如此,它们设计成在需要时能使用其他 Web 服务规范,像安全性、可靠消息传递等等。when and if required. 然而,与 BTP 不同的是,这样的一些需求被清楚地描述在单独的规范中。

  前面,我们通过 BTP 内聚对旅行代理场景进行了建模,而在这一部分中,我们将展示可以如何通过业务活动一样轻松地完成相同的工作。为了简单起见,我们仅仅考虑获得几个航班报价的情形,并且最后只接受最便宜的报价。

  这个示例讨论了这样一种事务的需求,它需要一种机制来选择和管理那些包括在整个应用程序结果中的任务。图21实际上重新进行了应用程序配置:每一个航班预订服务都会公开预订、确认和取消一个特定航班上的座位的操作。

  注意,虽然没有在本例中展示,但整个业务活动可以由大量的任务组成。每一个任务可以在整个应用程序范围内模型化成另外一个业务活动。另外,任务可以使用原子事务来实现。WS-Tx 允许应用程序指定各种范围(关系),而不必在整个业务流程中构建逻辑来跟踪这些关系。

  同前面一样,应用程序调用每个服务来获得航班上座位的报价。 和 ZA.com 确认旅行代理的航班预订请求(或者是应用程序级的响应)。ALU 和 BA 暂时预订座位,而 Xantas 实际保留一个座位。在请求的同时,事务服务管理参与应用程序的任务(换就话说,参与者加入(Enroll),表示预订任务正在积极处理,而 Xantas 却表示它已经完成了预订请求,如图22所示)。

  根据返回的价格(Prices),旅游代理决定继续并预订由 Xantas 和 ZA 提供的双程航班,如所示。因为 ALU 从来没有保留座位,所以不需要取消 ALU 航班。旅行代理指示 ALU 去取消临时预订(如果应用程序是用范围(Scope)进行构造的,旅行代理可以选择允许 ALU 暂时预订超时)。

  因为选中的航班有两个:Xantas 和 ZA,然后事务旅行代理请求 ZA 保留一个座位。ZA 确认保留。然后参与者(participant)告诉协调器任务已经完成(图24)。

  现在,应用程序已经选择了座位保留,这将被包括在整个预订中。您将注意到最后一组选中的参与者必须以原子方式终止。在本例中,ZA 和 Xantas 需要提交事务,并且作为原子组来完成。我们或许能在整个业务应用程序的范围内以原子事务的形式展示这种情况,但相反我们选择举一个更简单的场景,在这个场景中,旅行代理直接执行出结果。

  协调器(Coordinator)现在已经收到来自和 的确认,而且旅行代理已经完成了业务事务的请求部分。这样协调器就能继续并确认 Xantas.com 和 ZA.com 提供的座位预订(通过关闭(close)所示)。

  ALU 保留了一个座位,那么旅行代理需要指示 ALU 去取消这个预订。然后事务服务将从参与事务的任务中除去 ALU(参与者发送退出消息给协调器)。然后,旅行代理为剩下的任务确认保留,如图26所示。

  虽然给人的第一感觉是似乎这两个规范间有共性(例如,它们都支持两阶段(two-phase)完成协议)。但到此您也已经看到了它们之间是有非常大的区别的。在这一部分,我们将重新分析之前已经讨论过的一些问题,当然也有一些问题我们还没有讨论过的。

  您可能已经料想到一个花费了一年时间开发的规范应该是什么样的,从正面来说,BTP 规范是结构良好和完整的。但不幸的是,虽然协议是相当简单的,但是规范却几乎长达200页!因此,要说服客户或分析员(有时也包括实现人员)接受它并不是一件容易的事情。

  对于 Web 服务事务处理的用户来说,这又意味着什么呢?首先,让业务逻辑从一个事务处理服务内部直接影响事务处理流程似乎是一个好的主意,但在实际应用中,它并不是真正有效。它混淆了两个方面的区别,第一个方面是您期望从事务处理协议中得到的(保证一致性、隔离等等),它实质上是业务“事务”的非功能性方面,第二个方面是功能性方面(预订我的航班,预订一辆出租车,等等)。

  在 BTP 中,业务逻辑是在事务处理协议中进行编码的,这事实上意味着用户必须紧密地连接到协调器中(甚至有可能本身就是协调器)。业务信息,例如参与者在一段特定的时间内保持准备(比如继续占用宾馆房间)的状态的能力,是从参与者传输到协调器的,但是在 BTP 协议中,没有任何部分允许此信息实际所在的应用程序/客户端来过滤它。

  为了使用内聚,公开后端关于参与者的实现选择对于 Web 服务也是很必要的。为了参数化两阶段完成协议,内聚的终止器(terminator)显然需要能够表示“准备 A 和 B 而取消 C 和 D”,其中参与者 A、B、C 和 D 已经通过服务(比如航班预订系统)加入了内聚(cohesion )。在传统事务处理系统中,用户没有看到参与者(想象一下,如果您必须明确地告诉所有您的 XA 资源管理去准备和提交会怎样?)。自然而然,这是程序员感到不方便的事情,并且它与 Web 服务的正统观念是相违背的。

  此外,因为 BTP 需要使用Open-top方法的事务控。

本文链接:http://maps-enzymes.com/duantijiaoxieyi/580.html