现在的位置: 首页 > 综合 > 正文

biztalk 2006 事务补偿模型[翻译]

2011年07月06日 ⁄ 综合 ⁄ 共 5701字 ⁄ 字号 评论关闭

1.       简介

Biztalk 2006的补偿模型(Compensation Model)为解决多种多样的商业过程应用场景提供了一种通用机制,被应用在某些条件下需要回滚跟同一个商业活动相关的已经完成的一部分工作单元的情况。在这些情况下,补偿模型通常需要重新访问已经完成的工作单元,检查这些单元在各个阶段的系统状态,以采用合适的动作补偿已经完成的动作,至少,也可以维护一个审查日志或提供相关通知。

一个课本上的此类场景是,在订单/发货过程,一个客户取消了已经被部分处理但是还没有发货的订单。取消操作何时发生具有不确定性,货物可能已经被从仓库提出,可能已经被分派,也可能已经在路途上,发票可能已经开具并发送等等。订单/发送过程中必须有强壮的取消订单的机制,无论取消操作发生在过程中的哪个环节。

Biztalk 2006的补偿就是设计用于这种情况的机制,它提供了向后跟踪已经完成的单独工作单元,同时自动忽略没有完成的工作单元的灵活手段,它允许补偿逻辑访问被认为已完成的工作单元的过程状态。与异常处理和事务管理协同工作,它允许流程设计者定义当补偿动作被执行时将被调用的商业过程的路径。它不能解决所有的问题和应付所有的场景,无论如何,它被认为是实现失败处理和还原逻辑的必需手段。

2.       长时间运行的事务(Long Running Transactions

Biztalk的补偿不可避免的跟长时间运行事务的概念有关系。长时间运行事务(L-R事务)是具有更高一层水平事务(面向商业)的工作单元,但它不是标准的ACIDatomic, consistent, isolated and durable)的事务。因为通常(虽然并不总是)这样的工作单元将耗费很长的时间,这里的很长可能意味着几秒钟到几天、几个月,甚至几年。ACID事务之所以不适合这种情况是因为,ACID事务在事务期间锁定访问的数据,并要求并发的事务串行化,而长L-R事务的运行时间很长,不可能在很长的时间内一直锁着数据。L-R事务通常用于需要人工交互的过程或者需要跨组织边界进行交互的过程。一个L-R事务内的子活动可能具有很大程度的不确定性 ,例如,一个商业过程会受许多不受控制的、难于预期的外部因素的影响。 L-R事务的不确定性不适合传统的ACID事务模型,需要一种不像ACID模型那样严格的事务模型。

通常根据简化ACID相关属性来定义L-R事务,比如,微软定义L-R事务为“过程具有一致性和耐久性,但不具原子性和隔离性”。 biztalk的环境下,这样的描述大致是正确的,但是有些过分简单。它容易让人认为L-R事务是一种有缺陷的ACID事务, 这样看待L-R事务是不正确的。 ACID事务假定具有确定的存在,并使用一组定义明确的约束进行事务管理。L-R事务没有这些假定,因此有更广泛的适应性。关系型数据库申请ACID事务只使用到保存在数据库表中的数据,一个orchestration,必须使用贯穿整个商业过程中使用到的各种各样的数据,这些数据可能是内部数据,也可能是外部数据,外部数据可能是各种各样毫不相干的系统管理的数据,它们可能支持,也可能不支持ACID事务。

L-R事务可以被简单的定义为一个不遵循ACID模型的模仿现实世界的商业事务的机制。一个商业事务的定义 (基于1999年美国的Uniform Electronic Transactions Act) 是“一个或一组有两个或多个合作伙伴或参与者参加的涉及商业或者政府事务的活动”。 一个L-R事务跟一个ACID事务不以同样的方式进行约束,虽然它会展现出某些跟ACID事务相同的特性,它可以被分解为许多更小的内部事务,这些小事务也可能是ACID事务。

3.       Sagas(传奇)

术语“saga”在biztalk社区中不是经常被提到,但是它和L-R事务这个概念有很深的关系,并有一个古老的历史。Sagas是由Hector Garcia-Molina Kenneth Salem定义的,他们的论文发表在20年前,Sagas被描述为在关系型数据库中处理“长寿”事务的机制。这个概念是这样的,在一些情况下,一个长寿的ACID事务可以被分解为一系列更小的、单独的内部事务,这些内部事务跟其它Sage的内部事务对资源进行访问是串行的(如下图所示,两个Sage中的ACID事务不会同时发生),每个内部事务保持它的ACID特性,成为外层Sage的一个成员。Sage自身不处理ACID特性,但是会呈现出一个整体性的长寿事务。



图一
并发的Sage

 

Sage最与众不同的特点是捕获和处理失败的方法。在每个内部事务(ACID事务)水平,事务的失败使用通常的方法进行回滚,可是,如果在Sage的内部事务序列中前面内部事务已经被提交,要回滚这些事务就为时已晚了。因此,如果,在任何Sage中,第二个或者后续的事务失败,Sage将在这个中间状态被总体上被抛弃,此时,有的工作已完成,有的工作还未完成。

为了处理这种情况,Sage使用补偿块(compensation handler)的概念,每个内部事务都被提供一个属于它自己的补偿块,如果发生失败,失败的那个内部事务被以常规方法回滚,然后Sage执行每一个先前已经完成了的那些内部事务的补偿块,它按照内部事务被提交的逆序调用内部事务的补偿块。因此,如果在Sage A中事务4失败了,Sage调用补偿块的顺序将是按照事务321的顺序调用。


图二
 Sagas – 逆向恢复(Backwards Recovery)

这个方法被叫做“逆向恢复(backwards recovery)”,当然,术语“恢复(recovery)”被用于很广泛的领域。我们不能回滚已经提交了的事务,所以每个补偿块必须用一些动作完美的取消或者逆向恢复跟它相关的那个内部事务的动作做产生的效果。更正式的,理想的情况是,保证每个内部事务(T)和它的补偿事务(CT)可以相互交换,如果是fT,CT),即先执行内部事务T,然后执行它的补偿事务CT,所呈现出的系统状态的变化,跟先执行CT后执行T之后效果一样。如果不能保证这一点, Sage不是一个合适的关系数据库事务机制。

在包含了多个并发Sage的数据库系统中,每个Sage可以看到被另外的Sage做的部分改变,在Sage级别没有隔离性,Sage也不具有原子性。因此,可交换性不是总能达到的,Sage在适用性上有所限制。Sage可以安全的被用于下列一些场景:不需要事务隔离的场景,每个Sage的每个内部事务操作被约束的数据的场景,执行有效的跟其它Sage隔离的约束操作的场景。

除了逆向恢复,Sage模型还引入了正向恢复(forward recovery)的机制。在Sage流程内部定义一些保存点(save points),这些保存点把当前的Sage状态持久化保存到磁盘。Sage中的内部事务,它们遵循ACID模型的规则,自己内部已经能保证一致性和耐久性。保存点能保证Sage自身的上下文数据被持久化。

当一个内部事务失败时,Sage能从保存点再重新开始。如果在失败点和保存点之间有一个或者多个内部事务已经被提交,Sage必须首先使用部分的逆向恢复,执行补偿块补偿已经提交的内部事务,然后回到保存点重新开始Sage


图三
 Sagas – 前向恢复(Forwards Recovery

这个方法的一个明显的问题是重试之后Sage可能还是不能完成,因此,它很容易陷入一个死循环。解决这个问题的方法之一是,联合补偿块和异常处理器,比如,一个系统可能察觉到这样的循环,然后在合适的重试次数过后,不再循环重试,调用异常处理器,异常处理中进行这种不会恢复的场景处理。另一个方法是,Sage中每个内部事务前都设置一个保存点,这样一旦哪个内部失败就不用先执行任何逆向恢复了,只要重试它自身的失败就可以了。

4.       Saga模型和商业过程管理(Business Process Management

BizTalk Server,跟其它遵循 BPEL4WS规范的系统一样,为使用自动化商业过程的上下文改造和扩展了Sage模型。有一点需要强调,上下文真的跟关系数据有很大的不同,在关系型数据库中,我们通常只有有限的几种需要管理的数据种类,包括:

l         存放在数据表中的关系数据

l         在存储过程中的应用级别的数据,比如声明的变量和光标。

l         在内部事务水平和Sage水平在数据库中管理的底层上下文数据。

当然,这个列表不是完整的列表。目前,存储过程可以很好的跟外部系统交互,发送和接收信息等等。无论如何,关系数据库系统提供一个约束的环境,Sage可能影响到的大多数数据是被数据库系统管理的。复杂的过程工作流通常不在数据库中管理, Sage的流程可以跟多个其它Sage结合以支持更复杂的流程。

biztalk,事情更加复杂,考虑biztalkorchestration引擎必须管理的数据:

l         orchestration中为每个scope定义的内部上下文数据,包括整个orchestration scope

l         在特定scope级别定义的定制数据,包括:不可改变的messageorchestration变量和相关集,端口和角色链接。这些可能在运行时通过call orchestration形状传递到子orchestration

l         orchestration中建立的.net对象。

另外,它还必须提供一个跟广阔范围的外部数据进行交互的安全和可用的环境,包括:

l         .net对象交互的数据,它们可能在内存中,或者被持久化到磁盘,或者是通过支持或不支持事务的外部资源管理器管理,或者是跟非biztalk进程共享的数据。

l         更特别的是,通过System.EnterpriseServices.ServicedComponent派生的类可以具有DTC类似的行为。

l         服务(包括web services),应用等等,我们可以经由message box同步或者异步向它们接收或者发送消息。

 

除了这些,考虑任何一个orchestration可能展现出一个复杂的处理流程,在这个复杂流程中的参与方可能是另一个orchestration,也可能是许多外部系统。跟关系型数据库系统比较,它的环境更具挑战性。考虑一个完整的复杂的商业过程,包括所有参与的系统(biztalk是其中之一),不同的数据存储和消息流在整个商业活动中穿越。Biztalkorchestration是被设计用来控制这种复杂的流程的关键角色。

早前,我们讨论过,在Sage模型中,一个事务应该可以和它的补偿事务相互交换,这对事务主要是处理有良好数据结构关系数据库系统来说是比较有意义的,在商业过程的场景,我们在某种程度上对这个交换性会放松一些要求。 Orchestrations模型的现实商业过程,经常的参与者包括人类、外部系统和组织等等,它并不总是需要严格的确保事务和补偿事务的交换性。实际上,我们使用补偿模型承担广泛的补偿任务而不是“纯的”补偿机制。 比如, 在许多情况下,补偿模型足够用来简单的警告最终用户已经发生了异常,并告知他们在失败点在哪,哪些子任务已经执行完成。在我们的商业过程管理的状态上,可能并不需要做真的补偿性行为。

5.       BizTalk 基本补偿模型

Biztalk的基本补偿模型是有Sage模型的逆向恢复组成的,这个模型扩展了许多方法。我们先研究基本模型,然后下去看扩展。这个模型集中于使用L-R事务和atomic事务类型的scope。一个L-R 事务类型的scope可以看作是个Sage,跟Sage一样,它里面可以嵌套Atomic类型的scopeatomic scope遵循ACID事务模型)。每个atomic事务可以有一个补偿块(Compensation Block),在补偿块里,开发人员可以实现相关补偿的代码。BiztalkL-R事务有个缺省的补偿处理器(compensation handling),内建逆向恢复的逻辑。当某个嵌套的atomic事务抛出一个异常,外层的L-R事务可以选择调用缺省补偿块进行逆向恢复。

exception 处理器的调用不同,缺省补偿块不会被自动调用,它总是被一个L-R事务的异常处理器中的上下文调用。这里有两点比较容易让人感到迷惑。

首先,补偿块看上去很像异常处理器,所以,开发者会很自然的想这个补偿块是被atomic事务调用的。事实并非如此,当一个atomic事务抛出一个异常后,会被这个atomic scope直接外层的L-R事务的scope的异常处理器捕获,Atomic scopes不能有它自己的异常处理器。补偿块只能在直接外层的L-R事务的异常处理器捕获到异常后调用。

其次,每个L-R事务默认有个缺省的“General Exception”的异常处理器。它的行为就是捕获所有的异常,它在orchestration设计器中是不可见的,是在XLANG/s底层实现的。它等同于一个捕获‘General Exception’的异常处理器,里面包含一个Compensate形状和一个Throw形状,Compensate形状调用相关的这个L-R事务的compensation处理器,Throw形状再次抛出捕获到的异常。

你可以通过显式的新建一个捕获“General Exceptions”的异常处理器来override掉默认的异常处理器。这个方法可以用来抑制补偿,更可取的方法是建一个捕获“.NET exception”类型的异常处理器,默认异常处理器只有在有未被新建的异常处理器捕获的异常时才会被调用。“General Exception”的异常将捕获所有的.NET exceptions,包括不是从System.Exception继承的异常,如此宽松的类型以致不能给捕获到的异常对象提供任何可访问的方法和属性。大多数的.net语言,包括C#VB

【上篇】
【下篇】

抱歉!评论已关闭.