biztalk 2006 事務補償模型[翻譯]

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#VBXLANG/s,會要求異常類都從System.Exception類派生,而且在biztalk環境中非System.Exception的異常是非常罕見的。如果你自己建的異常處理器捕獲到一個異常,你可以使用Compensate形狀調用補償塊。

Atomic的補償塊跟異常處理器有很大不同。它們更像跟這個scope關聯的嵌套sub-orchestrations,作爲補償處理代碼的容器,其中的代碼只有在跟其關聯的atomic scope成功提交後纔可能被調用,因此它不能被跟其關聯的scope中的上下文調用。它總是被外層的L-R scope調用,你可以把這樣的調用想像爲使用一個call 形狀調用一個子orchestration,只不過,在這裏是使用Compensate形狀。Compensate形狀典型的在外層L-R scope的異常處理器中使用,儘管在擴展模型中,它也可能出現在外層L-R scope的補償塊中。補償事務總是隻能作爲捕獲和處理異常直接或間接的結果,biztalk的補償有效的構成了內建異常處理模式。

實現類Sage的模型,補償塊被捕獲到異常的外層L-R事務直接調用,而不是任何嵌套的事務。假設外層L-R事務的‘Compensation’屬性設置爲defaultbiztalk將正如你預期那樣的執行補償動作,根據提交的逆序調用所有的內嵌的已經提交的atomic scope的補償塊。


圖四
:基本補償模型

這就是基本模型的全部邏輯,不過這對於biztalk的開發者來說並不總是顯而易見的。在Sage模型中,Sage自己負責執行嵌套的Atomic事務的補償動作,這也正是biztalk默認的補償機制。不過,開發者熟悉異常處理而經常會對補償模型不太瞭解,這可能是問什麼在許多biztalk項目中都沒有出現補償的原因。

6.       BizTalk中的前向恢復

Biztalk提供了非常有限的類Sage的前向恢復支持,有兩個前向恢復的機制:

l         Atomic scope的重試

Atomic事務有個‘Retry’屬性,如果設置爲trueatomic事務在特定的情況下,atomic會嘗試重新執行事務,只有在下面三種情況下會重試:

n         Biztalk server嘗試提交事務,但是提交失敗。

n         Biztalk server在事務的結束處持久化狀態失敗,這是第一種情況的特例,提交包括了狀態持久化

n         atomic事務代碼中拋出RetryTransactionException異常

atomic事務將進行21次的重試,在前兩種情況,biztalk使用2秒的間隔重試,這個值不會出現在可配置的設置中。如果是拋出一個RetryTransactionException,重試間隔就會被缺省的設置爲0,不過,在這種情況下,你可以使用DelayFor屬性配置你自己的間隔時間。21次重試後,atmoic事務還是不能被提交,或者orchestration的狀態不能被持久化,biztalk將掛起(可恢復)這個orchestration實例。

l         恢復掛起的orchestrations

一個掛起的orchestration實例可以通過手工在管理控制檯恢復也可以通過一些腳本來恢復執行。在這種情況下,biztalk會嘗試從最近的持久化點重新啓動掛起的orchestration,每個事務都在它提交後建立一個持久化點以保存當時的狀態,以保證在恢復的時候永遠不會存在需要部分逆向恢復的事務。

7.       擴展的缺省補償模型

如果你已經在biztalk中使用了補償特性,你一定會發現上面關於默認補償的描述並不完全就是biztalk所提供的全部功能。Biztalk在許多方面擴展了基本補償模型,以更好的適應商業過程管理的複雜性提供更大的通用性。

Sage的擴展版本一致,biztalk允許在外層L-R事務中嵌套L-R事務,任何外層的L-R事務都能包含L-R事務和atomic事務,嵌套的L-R事務還可以繼續嵌套別的事務,Atomic事務不能再嵌套任何事務。

這個方法爲設計和實現複雜商業過程的補償策略提供了很大的靈活性。每個嵌套L-R事務都能被用於控制它的直接子事務的補償,併爲上層的L-R事務提供一個補償目標。正如我們看到的,補償塊總是被異常處理器中的代碼調用,由於biztalk orchestration中結構化異常處理器的使用,這允許根據捕獲到的異常類型執行相應的商業過程子集的補償。

當一個外層的L-R事務捕獲到一個異常並執行缺省的補償,biztalk不區分嵌套的L-R事務或者atomic事務,外層L-R事務將按照逆序調用每個成功提交了的事務的補償事務。Atomic事務被提交完成並且orchestration的狀態被持久化後這個Atomic事務被認爲是成功完成。嵌套的L-R事務當人不是以ACID方式提交,當它內部所有的活動都正常,沒有向它拋出異常或者導致orchestration掛起的問題,這個L-R事務就被認爲是成功完成的。

如果嵌套的L-R事務沒有定製的補償塊,將執行缺省的補償邏輯,它的補償邏輯就是逆序調用內部已經成功完成的直接子事務的補償事務(即補償塊中的邏輯)。嵌套的L-R事務內部的事務對外層L-R事務不具可見性,外層L-R事務看嵌套的L-R事務是個黑盒子。

在使用嵌套L-R事務擴展缺省類Sage補償模型和用補償塊的事務都是atomic事務的情況下,我們可以想像這個擴展模型就是一個簡單的“補償樹”,葉子是atomic事務和它的補償塊,根和分支是L-R事務。


圖五:
補償樹

這個模型展現出一個精妙的特性。考慮一個簡單的場景,我們把一個L-R事務(L-RInner)嵌入到一個外層的L-R事務(L-Router),L-RInner包含一個atomic事務(ACID Tx1)。如果在L-RInner範圍內在ACID Tx1被提交之後的某一點有個異常被拋出,異常會被L-Router的異常處理器捕獲,如果L-Router調用它自己缺省的compensation handlerbiztalk將會根據提交的逆序依次調用L-Router的每一個已經完成的直接子事務的補償事務,可是,L-RInner事務沒有成功完成,它拋出一個異常,因此,我們可以預期它的補償塊不會被調用,ACID Tx1也因此不會被補償。

實際上,L-RInner事務也有缺省的異常處理器,就如我們看到的,它將調用L-RInner 範圍內的補償,然後再次拋出捕獲到的異常,因此,ACID Tx1將會得到補償,即使它的外層L-R事務沒有成功完成。L-RInner 將自動攔截這個異常,當然,你可以通過使用顯式的異常處理器來override缺省的異常處理器。注意每個L-R事務只對它的直接子事務的補償負責。


圖六:補償樹的基本流

Atomic scopes 不能嵌套事務,所以它在補償樹上它總是表現爲一個葉子,另外,它們不能有異常處理器,這點經常是開發者感到驚訝,但這是綜合考慮了異常處理器和補償塊後的邏輯結論。當然,你總能把非事務的scopes簽入到atomic事務中,爲了讓在atomic中捕獲異常。

8.       L-R 事務中使用補償塊

前面的章節我們看到嵌套的L-R事務如何跟異常處理器協同機制擴展類Sage的補償模型。這章我們將看到L-R事務裝備自己的補償塊進一步擴展這個模型,以釋放Sage定義的某些束縛。

當一個L-R事務配備了自己的補償塊,補償模型從“缺省”模型改變到“定製”模型,在設計器,可以通過直接改變事務的Compensate屬性到Custom,或者右鍵單擊L-R scope,選擇加入新的補償塊來做到。注意,跟異常處理器不同,補償塊只能有一個。

在定製模型,在確定的條件下你可以控制整個補償步驟,你可以用任何你希望的順序補償已經完成的子事務。爲做到這點,在補償塊中爲每個你希望補償的事務加入一個Compensate shape,當然,你也可以加入附加的邏輯,比如,你可以用Decision shape精確的決定基於當時的orchestration狀態使用哪個補償。

這個擴展模型的一個潛在問題是嵌套事務是否完成的不確定性。當一個L-R事務定製的補償塊被調用時,通常你不能很確切的知道哪個子事務是已經完成了的。這個問題實際上已經變得不是很大的問題了,事實上如果你嘗試調用一個未完成的子事務的補償塊,不會發生任何事,補償塊並不會被執行,這不被視爲一個異常,控制簡單的轉移到補償塊的下面部分。

有時,這並不足夠,如果你需要顯式的測試一個子事務是否已成功的完成了,可以使用XLANG/s 表達式的“succeeded ()”功能,這裏需要一個單一參數,就是你需要測試的事務的identifier,返回的是個boolean值,表示事務是否已經完成,你能在decision shape中使用這個功能。事實上,Compensate shape內部就包含了一個用succeeded ()測試事務是否成功的if語句,在成功狀態下調用XLANG/s ‘compensate <tx> ()’的語句,這就是爲什麼你嘗試用Compensate shape執行未完成事務的補償塊什麼都不會發生的原因。

這裏有個不是很重要的問題,如果你在Decision shape中使用succeeded()功能,然後在判斷成功分支中使用Compensate shape調用這個事務的補償塊,Compensate shape本身內部就有個if語句判斷這個事務是否完成,succeeded()將會被執行兩次,這時可以簡單的使用Expression shape,其中使用‘compensate <tx> ()’語句來調用相應的補償塊。

定製補償有很多結果,比如,你爲一個L-R的事務引入一個補償塊,而這個L-R事務也需要捕獲異常,作爲捕獲到異常後的一個結果調用補償。這種情況,在異常處理器中至少需要有一個Compensate shape,如果你補償當前的L-R事務(L-R中調用自身的補償塊,Compensate shape不會判斷本身事務是否完成,只有調用它的子事務的補償塊時纔會判斷子事務是否已經完成,並只會調用已經完成了的子事務的補償塊),定製的補償塊將被調用,而不是缺省補償塊。你需要在你的定製補償塊中添加Compensate shapes進行相關的補償調用。

下面的圖顯示這個模型,在這種情況,我們在補償塊中按照內部事務的順序調用補償,而不是缺省的逆序。


7:定製補償 (A)

從另一個角度看,上面展示的模型有不必要的複雜性。Biztalk允許我們直接在異常處理器中調用補償,所以,我們可以把compensation block中的內容放到異常處理器中來,compensation block也可以不再需要。


8:定製補償 (B)

如果你在當前L-R事務的補償塊中調用本事務的補償塊,biztalk將調用當前事務的缺省事務補償塊。這個功能很有用,如果你只是想在缺省補償邏輯的基礎上加些簡單邏輯。如果一個L-R事務使用了定製補償塊,沒有其他的方法調用到缺省的補償塊。

很奇怪,你可以在atomic的補償塊中調用它的缺省補償塊,在後臺,atomic事務會試着去調用嵌套事務的補償塊,但是,atomic事務是不會有任何嵌套事務,所以這個調用不會產生任何動作。

你只能調用當前事務和直接子事務的補償塊,這個規則在異常處理器和補償塊中都起作用。你不能直接調用子事務的嵌套事務的補償塊。這樣保持了這個模型的簡潔,保證補償總是被它的直接外層L-R事務管理。

這個模型的缺點是,你可以很容易的不止一次的調用同一個事務的補償塊。在運行時,biztalk服務器將保證每個事務最多被補償一次。在大多數情況下,任何嘗試超過一次補償一個事務都會在編譯階段被捕獲,但僅僅給出警告,orchestration仍然會被繼續編譯。在運行時,第二次或者併發的嘗試去補償一個已經補償過的事務,biztalk將會跟嘗試補償沒有完成的事務一樣,這個補償會被忽略。這一點沒有顯式的在XLANG/s表達式中反映出來。

9.       Orchestration水平的補償

一個orchestration能提供一個orchestration級別的事務,跟任何事務一樣,你可以把orchestrationcompensation model從“缺省”改變到“定製”,在這種情況,因爲沒有相應的orchestration的補償塊形狀,orchestration的補償塊被作爲orchestration設計器底部的一個tab顯示。

Orchestration水平的補償有時會令biztalk開發者感到困惑,像任何補償塊一樣,orchestration的缺省補償塊或定製補償塊僅能被外層的L-R事務的異常處理器調用。可是,明顯的外層L-R事務不會是這個orchestration的一部分,在這種情況,這個orchestration應該是作爲用Call shape調用這個orchestration的父orchestration的一部分。注意當使用Start shape直接調用orchestration的情況不適用。(應該還可以在異常處理器中調用自身的補償塊,測試Orchestration的默認異常處理器調用自身定製補償塊的情況

10.  事務中的數據處理

一個atomic事務在orchestration狀態管理方面支持ACID特性。它定義了orchestration中的子單元,它要麼全部完成要麼全部失敗,它導致了在兩個狀態之間的一致性轉換,它將把相關orchestration狀態跟過程中的其它部分隔離,它保證所有更改的狀態在事務被提交前持久化到磁盤。

另外,atomic事務可以通過自動登記分佈式事務(DTC)來擴展它的邊界,爲充分利用這一特性,在atomic範圍內你聲明和實例化一個從System.EnterpriseServices.ServicedComponent繼承的對象,BizTalk總是視ServicedComponent的類爲非序列化的,即使它們被申明爲serialisableServicedComponent基類自身就被標記爲serialisable),因此你只能在atomic事務內部聲明ServicedComponent類型的變量。

爲了支持ACID特性,atomic事務複製相應的orchestration狀態,在事務內部會工作在狀態數據的副本之上,比如,一個orchestration的變量,消息或者相關集在外層事務被聲明,然後在atomic事務中使用,如果這個atomic事務成功完成,那麼在atomic事務中被改變的狀態數據會更新的原始狀態數據,然後這些改變被提交。對於每個成功的事務(atomicL-R事務),biztalk保存完成時的orchestration的狀態。對於atomic事務,當然就是提交時的狀態。如果這個事務以後要被補償,這些狀態數據就是補償的依據。補償事務,它們自身是L-R事務。關於狀態管理它們不支持ACID特性,這導致一個問題,如果你想在orchestration代碼中使用非序列化的.net類型,你必須在atomic scope範圍內聲明這些類型的orchestration變量,這些變量不能在補償事務中使用。如果你試着引用這樣的變量,你將得到一個編譯時錯誤。Biztalk使用序列化來捕獲提交的atomic事務的狀態,然後將這些狀態提供給補償塊,所以,不能給補償塊提供非序列化的數據。

有一個更進一步的限制,補償事務不是atomic的,發生在跟它相關聯的事務被成功完成後。因此,它們不能登記到atomic事務,也不能跟外部的DTC事務交互,因此它們也不能跟在關聯的atomic事務中聲明的ServicedComponent 類型的對象交互。這實際上是XLANG/s規範的一部分,但是是通過biztalkServicedComponent 類爲非序列化的來強制實現的。補償事務不能引用非序列化類。

你可以在補償塊中任意嵌套事務,包括atomic事務,當一個補償塊拋出一個異常,正如你可能預期的,被傳送到這個補償塊被調用的那個上下文,這可能是另一個補償塊,也可能是一個異常處理器,但最終,所有的補償都開始於一個異常處理器。所有,一個異常將通過補償塊鏈傳送到導致補償開始的根異常處理器。如果這個根異常處理器是缺省異常處理器,異常會被簡單的再次拋出。


原文:BizTalk Server 2006: The Compensation Model

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章