處理事務是構建許多業務邏輯的一個重要方面。但在面向服務的世界中使用事務卻很麻煩。分佈式事務假設參與各方之間存在高級別的信任,因此一般不適合跨服務邊界的事務。但仍然存在一些情況,將事務和服務綁定起來可以起到很好的作用,因此 Indigo 包含了對這一重要的應用程序設計特性的支持。
.NET Framework 2.0 中的事務
Indigo 中的事務支持構建在 .NET Framework 2.0 提供的機制上。這一即將發佈的版本中包含 System.Transactions,這是一種新的命名空間,完全專注於控制事務性行爲。開發人員將最常將 System.Transactions 與某個“執行上下文”配合使用,這是 .NET Framework 2.0 中的一種新結構。執行上下文允許指定適用於包含在一個定義範圍內的所有代碼的通用信息,如事務。以下是應用程序如何使用該方法將一組操作組合成一個事務的示例:
using System.Transactions; using (TransactionScope ts = new TransactionScope(Required)) { // 執行操作,例如更新不同的 DBMS ts.Complete(); } |
位於 using 塊內的所有操作將成爲一個事務的一部分,因爲它們共享其所定義的事務執行上下文。本例中的最後一行,調用 TransactionScope 的 Complete 方法,將導致退出該塊時請求提交該事務。此方法還提供了內置的錯誤處理,出現異常時會終止事務。
如本例那樣,爲新 TransactionScope 指定 Required,意味着此代碼將總是作爲事務的一部分運行:若其調用方的事務存在,則加入之;若不存在,則創建一個新的。如同在企業服務中一樣,還可以指定其他選項,包括 RequiresNew、Supported 和 NotSupported。
與企業服務及其前任 MTS 和 COM+ 不同,Systems.Transactions 完全專注於控制事務性行爲。例如,事務與對象的內部狀態之間不需要存在連接。企業服務要求一個對象在其結束事務時被停用,但 Systems.Transactions 則沒有這種需要。由於 Indigo 建立在 Systems.Transaction 上,因此 Indigo 應用程序也是獨立管理事務和對象狀態的。
Indigo 中的事務
Indigo 應用程序可以顯式使用 System.Transactions,也可以隱式使用依賴於 System.Transactions 的屬性來控制事務。一種選擇是,對位於標記有 ServiceContract 屬性的類中的方法,使用前面所述的 TransactionScope 將其工作包裝到一個事務中。例如,該方法可以包含一個 using 語句,建立一個事務範圍,然後在該事務內更新兩個獨立的數據庫。
服務的方法還可以使用屬性來控制事務性行爲。除了顯式使用 System.Transactions 外,服務還可以使用前面所述的 OperationBehavior 屬性。下面是一個示例:
using System.ServiceModel; [ServiceContract] class XactOperations { [OperationContract] public int Add(int value1, int value2) { return value1 + value2; } [OperationContract] [OperationBehavior(RequireTransaction=true, AutoCompleteTransaction=true)] int Update(int value1, int value2) { // 將 value1 和 value2 插入到 // 兩個不同的數據庫中 } } |
本例中的第一個方法 Add 沒有使用事務,因此其簡單操作將和以前一樣發生。但是第二個方法 Update 前置有 OperationBehavior 屬性,同時 RequireTransaction 屬性被設置爲 true。因此,該方法中完成的所有工作將發生在一個事務內,就像其位於前面所示的 using 塊事務範圍內一樣。同時由於還指定了 AutoCompleteTransaction 屬性,因此如果不出現異常,事務將自動提交。
如果調用此方法的客戶端不是運行在事務內,則 Update 方法將在其自己的事務內運行,沒有其他選擇。但這裏假定客戶端在調用 Update 時已經是某個現有事務的一部分。Update 方法所完成的工作是否會加入客戶端的事務,或其是否仍運行在自己獨立的事務中?答案取決於此服務能否接受由客戶端傳遞的“事務上下文”,這是通過 OperationContract 屬性的 TransactionFlowAllowed 屬性控制的一個選項。如果服務中的一個方法未附加 TransactionFlowAllowed 屬性,如上例所示,該方法內所完成的工作將永遠不會加入現有事務中。而如果此屬性存在,則方法將能夠加入其客戶端的事務中。
值得強調的還有,基於 Indigo 的應用程序可以參與包含運行於非 Indigo 平臺上的應用程序的事務。例如,一個 Indigo 應用程序可以啓動一個事務,更新本地 SQL Server 數據庫中的記錄,然後調用在一個 J2EE 應用程序服務器上實現的 Web 服務,更新另一個數據庫中的記錄。如果該服務是事務型的,且其運行的平臺支持 WS-AtomicTransaction 規範,則兩個數據庫的更新可以是同一事務的一部分。與安全性和可靠消息傳輸相似,Indigo 事務工作在 Web 服務導致的異質環境中。
隊列
使用綁定(如 WsHttpBinding),Indigo 應用程序可以與基於 Indigo 或任何其他實現了 WS-ReliableMessaging 的 Web 服務平臺上的另一個應用程序進行可靠通信。但儘管此規範定義的技術確保了 SOAP 消息的可靠端對端傳送,它卻不能實現消息隊列。使用隊列,應用程序只需將消息發送到隊列,而不是直接發送到另一個應用程序。當接收應用程序準備好時,它就可以從隊列讀取消息並進行處理。啓用這種交互很有用,例如,當消息的發送方和接收方可能不是同時運行的時候。
因此,Indigo 提供了對消息隊列的支持。這種支持建立在 MSMQ 之上,這意味着與 Indigo 的大多數其他特性(如可靠消息傳輸、安全性和事務等)不同,Indigo 隊列並不支持跨供應商邊界直接進行互操作(儘管可以使用 MSMQ-MQSeries 橋)。
要使用 Indigo 隊列,開發人員需要創建一個標準的 Indigo 服務類,照常使用 ServiceContract 進行標記。但位於此類的服務合同中的操作具有一些限制。特別是,它們必須全部標記爲單向,即不返回任何響應。這並不奇怪,因爲調用排隊的操作是將消息發送到一個隊列中,而不是其最終接收方,因此等待立即響應沒有任何意義。與其他任何服務類一樣,隊列 Indigo 應用程序也需要公開終結點。這些終結點使用了一些綁定,例如:NetMsmqBinding,允許與其他隊列 Indigo 應用程序進行通信;或 MsmqIntegrationBinding,允許一個隊列 Indigo 應用程序與不使用 Indigo 的標準 MSMQ 應用程序進行互操作。Indigo 隊列還支持隊列環境的其他傳統特性,如“死信”隊列和有毒消息的處理等。
隊列對絕大多數分佈式應用程序都是正確之選。Indigo 對這種通信方式的支持是開發人員無需瞭解完全獨立的隊列技術即可構建隊列應用程序。
六、共存和移植Indigo 代表在可靠、安全和事務型服務時代創建分佈式應用程序的一種新型方法。然而,需要理解的一個關鍵在於,安裝 Indigo 不會破壞任何現有的應用程序。運行於 ASMX、.NET Remoting 以及 Indigo 包含其功能的其他技術上的當前代碼,均可以繼續運行,因而不需要移植到 Indigo。但對於那些擁有對當前 Microsoft 技術的投資的機構,仍然存在一個明顯的問題:採用 Indigo 之前的技術編寫的現有代碼會發生什麼情況?
對於因 Indigo 的出現而前途深受影響的每一項當前技術,開發人員需要理解以下兩件事:基於此技術的應用程序是否將與基於 Indigo 的應用程序進行互操作,將應用程序從此技術移植到 Indigo 環境需要完成的工作量有多大?以下是對每項技術如何解決這些問題的簡短描述:
• |
ASP.NET Web 服務 (ASMX):採用 ASMX 建立的 Web 服務會與 Indigo 應用程序進行互操作。由於 ASP.NET Web 服務和 Indigo 兩者均支持標準 SOAP,因此這不應該有什麼奇怪之處。將現有 ASP.NET Web 服務代碼移植到 Indigo 需要進行一些機械性工作,但仍然簡單直接。兩種技術的基本結構十分相似,因此大體上只有屬性和配置文件需要改變。但更高級的特性(如 SOAP 擴展等)將無法直接移植到 Indigo。相反,需要使用 Indigo 提供的擴展選項對它們進行重寫。 |
• |
.NET Remoting:基於 .NET Remoting 的應用程序不會與基於 Indigo 的應用程序進行互操作,它們的傳輸協議不兼容。將現有 .NET Remoting 代碼移植到 Indigo 需要進行一些工作,但仍然是可能實現的。但是如果一個人建立了自定義的 .NET Remoting 擴展(如通道和接收),將會發現該代碼無法映射到新環境。Indigo 中存在相似的擴展,但實現的接口與 .NET Remoting 中實現的接口不匹配。 |
• |
企業服務:爲了使現有的企業服務應用程序能夠與 Indigo 客戶端(或其他基於 Web 服務的軟件)進行互操作,開發人員可以精確指定該應用程序中的哪些接口應當公開。使用 Indigo 提供的一個工具,可以自動爲那些接口創建服務合同,並通過 Indigo 公開。對於那些不基於 .NET Framework 的企業服務應用程序的現有客戶端(以及其他純粹基於 COM 的客戶端),提供了一個 Indigo 名字對象,以允許直接訪問 Web 服務。將現有的企業服務應用程序移植爲直接在 Indigo 上運行所需的工作與移植 ASMX 應用程序所需的工作類似。儘管不是全部,但大部分工作都是對屬性和命名空間的直接機械的修改。 |
• |
Web 服務增強 (WSE):WSE 是 Microsoft 爲實現需要 WS-* 規範所提供的部分或全部功能的 Web 服務應用程序而採用的一種戰術性解決方案。基於 WSE 1.0 和 WSE 2.0 的應用程序不會與基於 Indigo 的應用程序進行互操作。但基於將在 Indigo 發佈之前交付的 WSE 3.0 的應用程序將與 Indigo 應用程序進行互操作。對於可移植性,情況與已經介紹的技術類似:將現有代碼從 WSE 移植到 Indigo 需要進行一定的工作,但對於使用最後 WSE 版本編寫的應用程序這一工作將大大減小。 |
• |
MSMQ:由於 Indigo 的隊列功能基於 MSMQ,因此基於 Indigo 的隊列應用程序可以與直接基於 MSMQ 的隊列應用程序進行互操作。將應用程序從初始 .NET Framework 提供的 System.Messaging 命名空間進行移植需要一些工作,因爲這種早期接口與 Indigo 所提供的接口不同。一旦 Indigo 交付,開發人員就應使用它而不是 System.Messaging 來創建大多數基於 MSMQ 的隊列應用程序。 |
在 Indigo 面世之前,對不需要隊列的分佈式 .NET 應用程序而言,最佳技術選擇大概就是 ASMX。它使用簡單,同時提供了移植到 Indigo 的最平滑的途徑。企業服務對需要其提供的特性(如分佈式事務)的應用程序也很重要,但 MSMQ 仍然是隊列應用程序的正確選擇。而 .NET Remoting 則應主要用於同一進程中的兩個應用程序域之間的通信。對其他大部分情況下的直接應用程序對應用程序通信,ASMX 是一種較好的選擇。
引入新軟件總是會對已經存在的東西有影響。通過提供構建面向服務應用程序的通用基礎,Indigo 爲開發人員提供了一種更簡單、更統一的平臺。儘管這種改變會引起一些痛苦,但 Indigo 創建者們的目標是使這種轉換儘可能平滑和簡單。
七、結論Indigo 代表了在開發人員創建軟件的方式方面的一項重大進步。隨着面向服務的應用程序越來越普遍,Indigo 將成爲 Windows 軟件開發人員的主流技術。其他 Microsoft 產品也將轉而利用 Indigo 所帶來的優點。例如 BizTalk Server,將在 BizTalk Server 2006 發佈後的某個時候加入對 Indigo 作爲一種通信選項的支持。由於 Indigo 爲面向服務的軟件提供了一種標準基礎,因此它將成爲大部分 Windows 通信的基礎。
這一技術的影響勢必不會小。任何人要在 Windows 上構建分佈式應用程序,特別是那些必須與其他平臺上的應用程序進行互操作的應用程序,都應當給予密切關注。Indigo 將極大地改變他們的世界。