100
人物
WCF 技術剖析之三十三:你是否了解WCF事務框架體係內部的工作機製?[下篇]
[續《上篇》]TransactionFlow選項通過TransactionFlowAttribute這個操作契約寫入綁定上下文,由事務綁定創建的事務信道獲取該選項並以此作為首否對事務實施傳播(發送或者接收)的依據。客戶端事務信道通過TransactionFormatter對當前事務按照指定的事務處理協議進行格式化,並嵌入出棧消息;通過TransactionFormatter則從入棧消息中提取相應的數據重建事務。這就是事務流轉實現的本質。整個WCF事務還有一個重要的步驟需要實現:如何將通過OperationBehaviorAttribute特性標記為TransactionRequired的操作的執行自動納入到流入的事務之中。接下來,我們就來著重討論這個問題。
一、 事務的自動登記(Enlistment)
被格式化的事務最終是作為一個消息報頭(MessageHeader)的形式被傳輸的。服務端事務信道接接收到包含有流入事務的消息後,按照指定的協議從相應的報頭中獲取將被格式化的事務獲取出來,並通過TransactionFormatter對事務進行重新創建。被重新創建的事務對象最終以消息屬性(MessageProperty)的形式重新放入入棧消息。
這樣一個包含有事務對象的消息屬性定義在一個類型為TransactionMessageProperty對象之中,TransactionMessageProperty定義如下。隻讀屬性Transaction獲取內嵌於消息屬性對象的事務,而靜態方法Set則將事務作為消息屬性植入指定的消息。該消息屬性在消息中的Key為TransactionMessageProperty,即類型的名稱。
1: public sealed class TransactionMessageProperty
2: {
3: //其他成員
4: public static void Set(Transaction transaction, Message message);
5: public Transaction Transaction { get; }
6: }
WCF運行時根據消息的Action報頭定位到相應的操作,如果該操作應用了OperationBehaviorAttribute特性並將TransactionRequired屬性設為True,會進行如下的操作:
- 如果入棧消息中包含事務消息屬性,則提取事務並基於該事務創建TransactionScope對象。TransactionScope對象的其他一些屬性,比如超時時限、隔離級別等采用通過服務行為指定的值。結合前麵對System.Transactions事務的介紹,該過程的本質就是創建流入事務的依賴事務,並將創建的依賴事務作為當前的環境事務;
- 如果入棧消息不存在事務屬性,則創建一個新的TransactionScope對象。也就是相當於創建一個可提交事務,並將其作為但前的環境事務。
上麵的過程是在操作方法被調用之前完成的,並且和操作方法處於相同的線程中。環境事務的存在確保操作方法的執行被納入到流入的事務或者是一個全新的事務之中。至於事務參與者之間的協調問題,已經不屬於WCF體係管轄的範圍了,DTC會接收餘下的工作。
如果我們將上麵的實現通過代碼的形式寫出來,相信讀者的理解會更加深刻。我們以上麵演示的轉帳操作的實現為例,下麵是響應的代碼。由於Transfer方法上通過OperationBehaviorAttribute特性將TransactionScopeRequired屬性設成True,WCF服務端運行時會自動為我們實現事務登記。
1: [OperationBehavior(TransactionScopeRequired = true)]
2: public void Transfer(string fromAccountId, string toAccountId, double amount)
3: {
4: //轉帳操作
5: }
現在我們將OperationBehaviorAttribute特性從Transfer方法中拿掉,通過自己的方式實現事務的自動登記。如果不考慮超時時限和隔離級別等問題,整個實現會如下麵的代碼所示:
1: public void Transfer(string accountFrom, string accountTo, double amount)
2: {
3: TransactionScope transactionScope = null;
4: if (OperationContext.Current.IncomingMessageProperties.ContainsKey("TransactionMessageProperty"))
5: {
6: TransactionMessageProperty transactionMessageProperty = (TransactionMessageProperty)OperationContext.Current.IncomingMessageProperties["TransactionMessageProperty"];
7: transactionScope = new TransactionScope(transactionMessageProperty.Transaction);
8: }
9: else
10: {
11: transactionScope = new TransactionScope();
12: }
13: try
14: {
15: //轉帳操作
16: transactionScope.Complete();
17: }
18: finally
19: {
20: transactionScope.Dispose();
21: }
22: }
二、OleTx提升(OleTx Upgrade)機製
在《一步步創建一個完整的分布式事務應用》的實例演示中我們談到,即使我們將綁定采用的事務處理協議設置成WS-AT,並且在DTC中對WS-AT進行了正確的設置,WCF運行時仍有可能采用OleTx協議進行事務處理,這就是將要介紹的OleTx提升機製。
OleTx是Windows平台下默認的分布式事務協議,它采用安全RPC(Secure RPC: SRPC)協議進行通信,並采用二進製編碼,具有最好的性能優勢。對於WCF事務來說,即使我們顯式地將WS-AT設置成綁定采用的事務協議,如果DTC發現當前的事務應用場景仍然能夠采用OleTx進行處理,會自動將WS-AT協議提升到OleTx協議,這就是OleTx提升機製。
我們將我們的視線再次移向上麵基於TransactionFormatter的例子,通過分析包含有格式化事務數據的三種基於不同事務協議的SOAP消息的結構,我們會發現基於OleTx的所有信息均包含在基於WS-AT的消息之中。實際上,OleTx需要的僅僅是事務的傳播令牌(Propagation Token)。也就是說,對於WS-AT協調上下文接收方的DTC是可以通過OleTx進行事務處理的。
在默認的情況下,OleTx提升機製自動生效。我們可以通過修改相應的注冊表項對OleTx提升進行開啟和關閉,該注冊表項就是我們上麵提到的HKLM\SOFTWARE\Microsoft\WSAT\3.0\OleTxUpgradeEnabled。接下來我們將介紹在不同的應用場景下將綁定的事務類型設置成WS-AT,分布式事務的實現真正采用的實現方式:
- 場景1:WCF客戶端和服務端不部屬於同一台主機,不論是OleTxUpgradeEnabled作何設置,客戶端和服務端均采用SRPC與DTC進行通信。實際上,無論對於何種場景,事務參與者與本地DTC之間通信的方式總是SRPC。
- 場景2: WCF客戶端和服務端部屬於不同的主機,在沒有設置OleTxUpgradeEnabled或者OleTxUpgradeEnabled=1的境況下,DTC之間采用OleTx進行事務處理,通信方式為SRPC。
- 場景3: WCF客戶端和服務端部屬於不同的主機,將OleTxUpgradeEnabled設置為0的境況下,DTC之間采用WS-AT進行事務處理;
- 場景4:WCF客戶端調用另一平台服務,DTC和服務所在主機的事務管理器(TM:Transaction Manager)采用WS-AT進行事務處理;其他平台客戶端調用WCF服務,DTC和TM之間也采用WS-AT進行事務處理。
上述的4個場景如下圖所示:
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-27 16:04:21