當前位置:開發者網絡 >> 技術教程 >> .NET教程 >> 安全和優化 >> 內容
精彩推薦
分類最新教程
分類熱點教程
    
可靠的 XML Web Service (1)
作者:未知
日期:2003-07-12
人氣:
投稿:Andy.m(轉貼)
來源:未知
字體:
收藏:加入瀏覽器收藏
以下正文:
可靠的 XML Web Service
Eric Schmidt
Microsoft Corporation,XML Core Services 組,項目經理
2001 年 12 月 11 日

下載此專欄的示例代碼。

注意:要下載與本文相關的代碼,您需要:
Visual Studio .NET Release Candidate(英文)
SQL Server 2000(英文)
在 PDC 上,我談論了有關可靠的 XML Web Service(Web 服務)的話題,這個話題源於過去一年來的多次交流。在有關建立 XML Web Service 的眾多常見問題中,可靠性問題是開發人員實現分散式 Web 服務所面臨的五個最重要的問題之一。如果分開來講,這個問題並不是太難,因此,本月我準備談一談建立可靠的 XML Web Service 這一棘手的問題。

概述
Global XML Web Services Architecture(GXA [英文])最突出的一面就是可以使用可合成處理協議擴展該體系結構。這些協議主要通過 SOAP 標頭實現,可以提供包括安全性、加密、路由和可靠性的廣泛服務。當您開始構建基於 GXA 的應用程序時,您將發現 GXA 實質上是一種消息處理體系結構,它通過基於標準的編碼技術 (SOAP) 在系統和服務之間提供協同工作能力。到目前為止,大部分實現工作都集中在 SOAP 1.1 和 WSDL 兼容服務上,因此 Web 服務實現方案可以與多種語言和操作系統協同工作。

這是一個了不起的概念。任何兩個系統之間都能夠進行交流,只要它們能夠分析 XML 並理解 SOAP 規範的規則。但是,簡單的消息交換並不能滿足複雜的業務應用程序的需要。真正的應用程序(不管其內部域體系結構如何)均需要標準化的服務,例如處於 Web 服務消息處理層上的安全性、授權和可靠性。在 Global XML Web Services Architecture(具體地說就是 SOAP、SOAP 模塊和基礎結構協議)的創建和實現背後有一個巨大的動力。隨著今年十月份四項新規範(WS-Routing、WS-Referral、WS-Licensing 和 WS-Security)的發佈,我們已經開始著手下一代 XML Web Service 實現工作。儘管發佈了這麼多的新規範,但仍有兩個領域尚無公共規範,即事務處理和可靠的消息處理,這主要是因為這些基礎結構協議依賴於底層 SOAP 模塊。

本專欄主要從 GXA 環境的角度討論可靠性和可靠的消息處理的含義。而且我還要花一些時間探討通過在 .NET 框架中擴展現有 Web 服務類來開發可靠性協議需要做些什麼。本專欄有兩個主要目的:

讓讀者瞭解可靠性概念,為以後各種規範的實施做好準備。請注意,本文不是規範,而只是一篇文章,旨在引發讀者思考下面要討論的問題。
說明 .NET 框架中 Web 服務和 SOAP 類強大的、基於標準的功能。
XML Web Service 的可靠性
我們把問題分開來講。我們前面講過,GXA 服務實現方案屬於消息處理服務,它們需要在分散式環境中發送和接收基於標準的編碼消息。在 Web 服務實現方案中發送 SOAP 消息的主要傳輸協議是 HTTP,它易於實現和管理,但本身不可靠。我們無需深入探討 HTTP 不可靠的具體原因,但只要知道 HTTP 沒有基於標準的服務來保證終點或服務器能夠接收到請求就足夠了。儘管內置的網絡層設備可以在發生一般災難性故障(例如未找到資源)時產生錯誤,但是卻沒有機制可以確保客戶端能夠以可靠的方式接收請求或響應。

通常是通過簡單的重新發送操作處理 HTTP 故障,但在業務處理環境中這既不利於提高效率也沒有效果。它導致不必要的通信量,並增加了重複交易的風險。

目前市場上有多種能夠更有效解決此問題的消息處理技術,包括傳輸協議(如 HTTPR)、企業基礎結構(如 MSMQ 和 MQ Series)以及業務處理協議(如 ebXML)。儘管每種技術針對特定的實現方案各有優點,但都不能以可在所有傳輸協議上跨域應用的可擴展方式解決可靠性問題;而且,在消息交換和處理方面的功能層次上也不盡相同。

面對所有這些問題,我決定總結一個需求列表,看一看在 Web 服務環境中實現可靠性原型需要做哪些工作。

以下是我自己創建的可靠性層的主要需求列表:

基於標準並應用於消息協議層
確認發送
有序發送
對稱對話
加快異步處理
基於標準
該協議必須由現有的基於標準的技術組成。而且,該協議還應該對 SOAP 1.1 規範進行擴展,然後應用到消息編碼層而不是傳輸層。這樣,消息才能夠在所有可用的機制(從 HTTP 到某些專用套接字實現方案)上進行傳輸。

確認發送
為了有章可循,該協議必須採用某種發送確認機制,也就是說,使用該協議發送的消息應當從處理器接收一個且只有一個關於該消息狀態的確認信息。

有序發送
有序發送引入了對話概念,即客戶端和服務器可以交換消息和確認(確認也是可唯一標識的對話的一部分)。收到消息後,將檢查消息以進行排序,確保處理器收到一組有序的消息。

對稱對話
建立在對話機制之上的協議,還必須確保消息和確認的對稱性。必須確保每條消息只被處理一次,並且只生成一個確認。

加快異步處理
這是需求列表中最重要的一點,所以留在最後說明。HTTP 是基於同步請求響應模型的,適用於處理任務量小或運行時間短的簡單應用程序。Web 服務實現方案有一個不太高明的小秘密,即用戶不需要從處理的角度瞭解服務是如何在後端實現的。也就是說,Web 服務實現方案處理一個請求可能只需要三秒鐘,也可能會花上三個小時。這導致消息處理體系結構效率低下,且無法擴縮。我們需要的是一個能夠加快異步消息處理體系結構的處理模型。但是要注意,異步模型實現方案要比緊耦合的請求響應實現方案複雜得多,因為它需要更多的基礎結構。

我來解釋一下。在使用標準 HTTP 的同步消息處理模型中,客戶端在向服務器發送請求後、從服務器接收到響應之前一直保持停滯狀態。在這段時間內,可能會發生許多災難性事件:

連接可能會因外部原因而斷開,從而丟失請求或響應。
服務器可能會因脫機或過載而超時。
服務器進程可能取決於下行服務,而這種服務的響應時間無法控制。
同步模型


圖 1:同步模型

不管問題是與網絡有關還是與應用程序有關,要確保可靠性都需要實現某種附加協議驅動的基礎結構。在本次討論中,我想著重講述消息是如何在傳輸層上進行處理的。傳輸層是獨立於應用程序的關鍵部分,使用它可以實現可靠性層,並將消息的最終處理過程分離出來。更具體一點來說,每一條消息(不管針對哪種應用程序)都需要從網絡層上讀取,並分配至適當的應用程序資源。我們可以在這裡添加一個發送可靠性確認和執行持續存儲的附加協議,這樣應用程序資源就可以選擇處理該消息的時間和方式。而且,這個新協議可以幫助我們分離或加快異步處理模型。下面將解釋如何完成此過程。

在下面的異步模型中,某一請求被發送至 SOAP 服務器。服務器從網絡層上讀取該消息流,並立即向客戶端返回 HTTP 202 響應。此進程僅就向服務器發送消息的時間而言是同步的,這樣可以減少與連接有關的問題。到達服務器後,消息將被傳送到可靠性層,在這裡進行檢查以驗證消息是否過期、重複和有序。然後,消息被持續存儲(在關係數據庫中),並向客戶端發送有關其狀態的確認。最後,消息將被分配至正確的應用程序功能。

異步模型


圖 2:異步模型

在 HTTP 環境中,您可以控制向客戶端發送響應的時間。通過控制向客戶端發送響應的時間,您可以將下行處理影響通信可靠性的風險降到最低。在 SOAP 中,這是通過單向消息傳遞實現的。它指示底層 SOAP 處理器立刻向客戶端發送 HTTP 202 響應,通知客戶端已收到消息,並已成功地將消息分配給正確的資源進行處理。之後,處理器向客戶端發送有關該消息狀態的響應。本文稍後將對這種模型的優點進行詳細介紹。

建立可靠性層
明確了上述要求之後,我們來討論如何使用 .NET 框架為 Web 服務實現方案建立可靠性協議。根據上述要求,我建立了一個小型 API,以便提供可用的實現方案。

協議:ericRP
第一個問題是定義如何分解可靠性協議 (ericRP)。以下是該協議的關鍵之處:

該協議是用於教學的原型。
該協議主要是通過擴展 SOAP 消息處理層在 SOAP 處理層上執行的。
SOAP 標頭用於對處理層所需信息進行編碼。
該協議要求實現方案具有某種方式的持續存儲,以便記錄消息。本實現方案使用的是 Microsoft SQL Server 2000。
注意:不管採取哪種方式在 SOAP 環境中實現可靠性層,除了 SOAP 分析器之外,都還需要其他基礎結構。
該協議支持對話概念,也就是說可以對多條消息進行排序,從而保證有序的發送。
該協議的全部實現方案都由 ericRP 名稱空間限定。
ericRP 基於兩方對話方案,即兩個服務可以通過 XML Web Services 體系結構(HTTP、SOAP 和 WSDL)進行對話。
客戶端負責消息的所有更正。(本文後面有詳細論述)
服務器只負責基於特定標準發送確認。
服務器不記錄收到的過期消息。
服務器不記錄收到的無序消息。
服務器不記錄收到的重複消息。
處理 API
在這個原型中,我建立了六個主要的類和一個小型數據庫。我將類稱為處理 API。Web 服務客戶端和服務器將使用這些類監控和更正使用 ericRP 可靠性協議的消息。所有的類都屬於 ericRP 名稱空間:

Client.ConversationManager:由客戶端使用,創建 Web 服務消息關聯和消息監控的對話環境。
Client.RPClientTrace:由 Web 服務客戶端使用,這些客戶端的方法對出站消息執行 ericRP 可靠性協議。
Server.ConversationManager:由 Web 服務服務器使用,記錄並處理入站消息。
Server.RPServerTrace:由 Web 服務服務器使用,這些服務器的方法對入站消息執行 ericRP 可靠性協議。
ReliabilityInfo:具有雙重作用。它可以由 Client.ConversationManager 使用,為記錄提供可靠性信息;也可以由 Web 服務客戶端代理使用,為出站消息創建必要的 SOAP 標頭信息。
Acknowledgment:由 Server.ConversationManager 使用,向客戶端發送確認。
ericRP 的工作原理
在查看代碼之前,我想先從用戶的角度說明該協議的工作原理。例如,我有一個簡單的 Web 服務代理類,通過它可以向 Web 服務發送訂單消息。打算使用 API 的客戶端需要執行以下操作:

首先,創建 Client.ConversationManager 類的實例並開始一個新對話。例如:

private void begin()
{
rpClient = new ericRP.Client.ConversationManager();

rpClient.MessageSent += _
   new ericRP.Client.ConversationManager.MessageSentEventHandler(process);

rpClient.ConversationStarted += new _
   ericRP.Client.ConversationManager.ConversationStartedHandler(constarted);
   
rpClient.BeginConversation();
}

rpClient 變量在類級別內有效,稍後會用到。我還設置了一些事件處理程序。

下一步,使用訂單代理並配合 ReliabilityInfo 類,發送一條可靠的信息。先創建 PurchaseOrderProxy 的實例,就像通常為 Web 服務客戶端所做的操作一樣。再創建 ReliabiltiyInfo 類的實例,將 ConversationManager 傳送給構造函數,然後設置可靠性屬性。需要特別注意的屬性是 MaxRetry、ExpireDate 和 AckURL。MaxRetry 和 ExpireDate 用於限制消息的活動,防止它無限制地發送;Web 服務將在向客戶端發送接收確認時使用 AckURL。設置完這些屬性後,即可設置代理的 ReliableHeader 屬性並調用所需的方法。

private void sendMessage()
{
ClientProxies.PurchaseOrderProxy po = new ClientProxies.PurchaseOrderProxy();
         
   ericRP.ReliabilityInfo rInfo = new ericRP.ReliabilityInfo(rpClient);
   rInfo.Status = ReliabilityInfo.MessageStatus.New;
   rInfo.SendDate = System.DateTime.Now;
   rInfo.ExpireDate = System.DateTime.Now.AddHours(4);
   rInfo.MaxRetry = 5;
   rInfo.AckURL = "http://localhost:8082/ericRPAck/POAck.asmx";
         
   po.ReliableHeader = rInfo;
   po.SubmitMessage("非常希望他們得到此訂單!");
}

這是為了說明該功能而編寫的一段客戶端測試程序的屏幕快照。注意,我們一共發送了五條消息。第三條消息在到達目的地之前已過期,按照 ericRP 協議,這條消息將被丟棄,服務器不對其進行處理。第四條消息是無序消息,因為服務器並沒有收到有效的第三條消息。在重新發送第三條消息之前,任何後續消息都是無序的。如果重新查詢 Client.ConversationManager,您將發現第五條消息也是無序的。



圖 3:客戶端測試程序

相關文章: