Indigo 的其他特性
服務和客戶端的基礎知識對每個 Indigo 應用程式都很重要。但這些應用程式中大部分還將用到此技術的其他方面。本節探討 Indigo 為基於它建立的應用程式提供的一些其他特性。
控制本機行為
Indigo 的許多特性(如合同、綁定及其他)均跟服務與其客戶端之間的通信有關。但也有部分服務行為本質上是本機行為。例如,一個服務實例的生存期是如何控制的,對該實例的並發訪問是如何管理的?為了讓開發人員控制此類行為,Indigo 定義了兩個基本內容,其中每個都擁有大量內容。內容之一為 ServiceBehavior,可用於同樣標記有 ServiceContract 內容的類。另一個內容為 OperationBehavior,可用於服務類中同樣標記有 OperationContract 內容的方法。
ServiceBehavior 內容具有各種內容,共同影響服務的行為。例如,有一個內容名為 ConcurrencyMode,可用於控制對服務的並發訪問。如果設置為 Single,Indigo 在任何時候都只處理對該服務的一個客戶端請求,即服務是單線程的。如果設置為 Multiple,Indigo 在任何時候都可以處理對該服務的多個客戶端請求,每個請求執行於一個不同的線程上。與此類似,ServiceBehavior 的 InstanceMode 內容可用於控制如何創建和銷毀服務的實例。如果 InstanceMode 設置為 PerCall,將為處理每個客戶端請求創建該服務的一個新實例,然後當該請求完成時將其銷毀。而如果設置為 PrivateSession,則將使用服務的同一實例處理來自某個客戶端的所有請求。
例如,假設其創建者決定 Calculator 類應當是多線程的,並且將使用同一實例處理來自某個客戶端的每個呼叫。類的定義將如下所示:
using System.ServiceModel;
[ServiceContract]
[ServiceBehavior(
ConcurrencyMode=Multiple,
InstanceMode=PrivateSession)]
class Calculator { ... }
與此類似,OperationBehavior 內容上的內容允許控制實現該操作的方法的模擬行為、其事務要求(將在後面講述)以及其他內容。
消息傳輸選項
本文中所示的簡單示例採用了同步遠端過程呼叫 (PRC) 方法來實現客戶端/服務交互。Indigo 支持這種選擇,但它不是唯一的選擇。SOAP 是一種面向消息的協議,這意味著它可以支持各種編程模型。實際上,Indigo 支持多種可能,包括以下選擇:
‧
傳統 RPC,使用帶有類型化參數的阻塞呼叫;
‧
異步 RPC,使用帶有類型化參數的非阻塞呼叫;
‧
傳統消息傳輸,使用帶有一個消息參數的非阻塞呼叫;
‧
基於消息的 RPC,使用帶有一個消息參數的阻塞呼叫。
儘管絕大多數分佈式應用程式需要,但 SOAP 規範未對可靠性進行任何規定。確保可靠性的一種通用方法就是只在點對點情況下使用 SOAP,依靠 TCP 來保證請求和響應的傳送。在有些情況下,這樣做就已經足夠,使用 BasicProfileHttpBinding 時就是這樣。
但仍有大量的情況,這樣做還不夠。例如,如果通過多個 SOAP 中間方訪問服務會怎麼樣?由 TCP 提供的可靠性保證在這種情況下是無法確保端對端可靠性的。為了解決這個問題,Indigo 採用了 WS-ReliableMessaging 規範。通過選擇一個使用 WS-ReliableMessaging 的綁定(如 WsHttpBinding),服務及其客戶端可以在通過多重 SOAP 中間方的情況下也能保證可靠的端對端通信。
安全性
在網路上公開服務,即使是在內部網路上,一般也會需要某種程度的安全性。服務如何確定客戶端的身份?如何防止發送到服務的消息和從服務接收的消息被惡意更改和竊取?如何使對服務的訪問僅限於那些被授權使用它的客戶端?如果沒有解決這些問題的解決方案,公開大量服務就會非常危險。而構建安全的應用程式則會使事情複雜化。理想的情況,應當是採用簡單直接的方式應對通用的安全情況,同時對有需要的應用程式採取更精細的控制。
為達到這一目的,Indigo 提供了身份驗證、消息完整性、消息保密和授權等核心安全功能。Indigo 實現這些功能中前三個功能的方法主要依靠綁定,開發人員的選擇有:
‧
選擇一種支持安全性的標準綁定。例如,只需要基於傳輸的安全性的應用程式可以採用 BasicProfileHttpsBinding 之類的綁定。這種方法對於那些不需經過任何中間方(如 HTTP 代理或其他 SOAP 節點)而直接從客戶端到達服務的請求已經足夠。需要確保經過多重 SOAP 中間方的消息的端對端安全性的應用程式,則可以採用支持 WS-Security 的綁定,如 WsHttpBinding。
‧
選擇一種支持安全性的標準綁定,然後通過改變一個或多個預定值對其進行自定義。例如,如果需要,可以更改一些綁定(如 WsHttpBinding)所採用的身份驗證機制。
‧
創建一個準確提供開發人員需要的安全特性的自定義綁定。這種方法不適合害怕繁瑣者,但確實是一些高階情況的正確方法。
‧
選擇一種不支持安全性的標準綁定,如 BasicProfileHttpBinding。雖然採用不支持安全性的綁定通常是件危險的事,但在有些情況下這仍然是最佳選擇。
Indigo 服務還可以控制授權哪些客戶端使用該服務。大體而言,Indigo 只支持 .NET Framework 中已有的授權機制。例如,服務可以使用標準 PrincipalPermission 內容定義允許哪些客戶端訪問它。
讓開發人員構建安全的應用程式而又避免使他們面對極大的複雜性,已被證明極具挑戰性。通過為大多數通用情況提供簡單直接的方法,同時為更為複雜的情況提供精細的控制,Indigo 正在以一種可行且有效的方式實現這一目標。
事務
處理事務是構建許多業務邏輯的一個重要方面。但在面向服務的世界中使用事務卻很麻煩。分佈式事務假設參與各方之間存在高階別的信任,因此一般不適合跨服務邊界的事務。但仍然存在一些情況,將事務和服務綁定起來可以起到很好的作用,因此 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 將極大地改變他們的世界。
關於作者
David Chappell 是位於美國加利福尼亞州舊金山市的 Chappell & Associates (
http