WCF系列:Binding模型 信道與信道棧(Channel and Channel Stack)

WCF採用基於消息交換的通信方式,而綁定則實現了所有的通信細節。綁定通過創建信道棧實現了消息的編碼與傳輸,以及對WS-*協議的實現。在這一節中,我們就來着重介紹WCF中的信道和信道棧。在正式開始對信道和信息棧的介紹之前,我們先來介紹兩個重要的類型:CommunicationObject和DefaultCommunicationTimeouts。

1. CommunicationObject與DefaultCommunicationTimeouts
WCF綁定模型涉及多種類型的組件,比如信道、信道監聽器、信道工廠等等。從功能上講,這些對象都是爲通信服務的,我們可以把它們稱爲通信對象(Communication Object)。對於這些通信對象來說,在通信不同的階段,它們往往具有不同的狀態;從整個通信的生命週期來看,在不同階段過渡的過程中,它們具有一些相似的狀態轉換方式。

WCF定義了一個特殊的接口,System.ServiceModel.ICommunicationObject,來管理通信對象的狀態和狀態的轉換。下面是ICommunicationObject的定義:
  1. public interface ICommunicationObject
  2. {
  3.     // Events
  4.     event EventHandler Closed;
  5.     event EventHandler Closing;
  6.     event EventHandler Faulted;
  7.     event EventHandler Opened;
  8.     event EventHandler Opening;

  9.     // Methods
  10.     void Open();
  11.     void Open(TimeSpan timeout);
  12.     IAsyncResult BeginOpen(AsyncCallback callback, object state);
  13.     IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state);
  14.     void EndOpen(IAsyncResult result);

  15.     void Close();
  16.     void Close(TimeSpan timeout);
  17.     IAsyncResult BeginClose(AsyncCallback callback, object state);
  18.     IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state);
  19.     void EndClose(IAsyncResult result);

  20.     void Abort();

  21.     // Properties
  22.     CommunicationState State { get; }
  23. }
複製代碼
ICommunicationObject的State屬性,表示通信對象當前所處的狀態。該屬性通過一個名爲System.ServiceModel.CommunicationState的枚舉類型表示,通信對象典型的六種狀態都定義在CommunicationState中:被創建(Created)、正被開啓(Opening)、已經被開啓(Opened)、正被關閉(Closing)、已經被關閉(Closed)已經出錯(Faulted)。
  1. public enum CommunicationState
  2. {
  3.     Created,
  4.     Opening,
  5.     Opened,
  6.     Closing,
  7.     Closed,
  8.     Faulted
  9. }
複製代碼
ICommunicationObject定義了以下三種類型的成員:

  • 事件:當正在進行狀態轉化,或者是狀態轉換成功,會觸發相應的事件。通過註冊相應的事件,可以在某個狀態轉換環節中注入你需要的處理操作。
  • 方法:定義了三種類型的操作:開啓(open)、關閉(close)、中止(abort)。關於“關閉”和“中止”在功能上具有相似之出,都是斷開連接、回收對象。不過它們具有不同之處,很多英文文章或書籍將“關閉(close)”成爲“graceful shutdown(優雅地關閉)”,而將“中止(abort)”描述爲“immediate shutdown(立即關閉)”。那我們關閉電腦來說,前面一種是通過操作系統進行關閉,後一種則是直接切斷電源。對於前一種方式,在關閉過程中,會進行一些IO操作。
  • 屬性:在上面已經提到,屬性State代表通信對象當前所處的狀態。

由於WCF處理的是跨應用程序域(Application Domain)、跨機器甚至是跨網絡的通信。所以WCF服務調用的大部分時間都在進行象網絡傳輸這樣的IO操作,對於這種IO綁定(IO bound)的操作,對於多線程異步的考慮肯定是可以不免的,所以ICommunicationObject中的開啓和關閉操作,既定義了一個的同步方法,也按照異步編程模型(APM:Asynchronous Programming Mode)定義了異步方法。

除了簡單定義ICommunicationObject接口之外,WCF還定義了一個實現了該接口的基類:System.ServiceModel.Channels.CommunicationObject。
  1. public abstract class CommunicationObject : ICommunicationObject

  2. {

  3. ...

  4. }
複製代碼
在WCF體系中,很多的基於通信的基類都繼承自CommunicationObject,比如信道的基類System.ServiceModel.Channels.ChannelBase;信道工廠和信道監聽器的基類System.ServiceModel.Channels.ChannelManagerBase;ServiceHost的基類System.ServiceModel.ServiceHostBase;信道分發器的基類System.ServiceModel.Dispatcher.ChannelDispatcherBase;等等。大體的繼承結構如圖3-8所示 的類圖所示。


[WCF中的Binding模型]之二: 信道與信道棧(Channel and Channel Stack)_9963
image_4.png(90.53 K)
11/14/2008 12:42:32 PM

圖3-8 CommunicationObject繼承關係

由於WCF往往需要跨域網絡進行服務的訪問,較之一般的方法調用,服務訪問的所花的時間往往較長,所以對超時的處理顯得異常重要。比如對於消息的發送,可能由於網絡的故障,該消息在一端時間內根本無法成功發送,客戶端程序不可能無限制地等待下去。一般的情況下,我們會設定一個操作執行的所允許的最大時限,一旦超時則取消操作,並進行相應的超時處理。

我們回顧一下ICommunicationObject的Open和BeginOpen方法,我們會發現它們各有兩個重載,其中一個具有的TimeSpan類型的timeout參數,另一個則沒有。在這裏的timeout參數實際上代表Open方法執行的超時時間,如果Open操作執行的時間過長,一旦超過了該事件,操作將被立即中止。
  1. public interface ICommunicationObject

  2. {

  3. void Open();

  4. void Open(TimeSpan timeout);

  5. IAsyncResult BeginOpen(AsyncCallback callback, object state);

  6. IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state);

  7. ... ...

  8. }
複製代碼
可能讀者會問,對於沒有timeout參數的操作,比如無參的Open方法,是否意味着沒有這樣的超時限制,操作將會一直執行下去直到操作正常結束呢?答案是否定的,實際上,對於沒有顯式指定超時時限的操作,採用的是默認的超時時限。WCF爲所有需要默認超時時限的通信對象定義了一個接口:System.ServiceModel.IDefaultCommunicationTimeouts。在IDefaultCommunicationTimeouts中定一個了四個Timeout屬性,分別定義了開啓、關閉、發送、接收四大操作的超時時限。
  1. public interface IDefaultCommunicationTimeouts

  2. {

  3.     // Properties

  4.     TimeSpan CloseTimeout { get; }

  5.     TimeSpan OpenTimeout { get; }

  6.     TimeSpan ReceiveTimeout { get; }

  7.     TimeSpan SendTimeout { get; }

  8. }
複製代碼
很多的基於通信的基類都實現了IDefaultCommunicationTimeouts接口,比如信道的基類System.ServiceModel.Channels.ChannelBase信道工廠和信道監聽器的基類System.ServiceModel.Channels.ChannelManagerBase;以及所有綁定對象的基類System.ServiceModel.Channels.Binding等等。

2. IChannel和ChannelBase
WCF中信道層中的每種類型的信道直接或者間接實現了接口System.ServiceModel.Channels.IChannel,IChannel的定義異常簡單,僅僅具有一個唯一範型方法成員:GetProperty<T>()。
  1. public interface IChannel : ICommunicationObject

  2. {

  3.     // Methods

  4.     T GetProperty<T>() where T : class;

  5. }
複製代碼
通過調用信道對象GetProperty<T>方法,獲得具有範型類型的屬性。這個方法比較重要,因爲它是探測信道是否具有某種能力的一種有效的方法。比如我們可以通過該方法,指定相應的範型類型,確定信道是否支持某種Channel Shape(關於channel shape將在接下來的部分中進行介紹),消息版本和安全模式等等。

除了IChannel接口之外,WCF還定義了一個實現了IChannel接口的基類:System.ServiceModel.Channels.ChannelBase。。除了實現了IChannel接口,ChannelBase還實現了另外兩個接口:ICommnucationObject和IDefaultCommunicationTimeouts,並直接繼承自CommnucationObject。
  1. public abstract class ChannelBase : CommunicationObject, IChannel, ICommunicationObject, IDefaultCommunicationTimeouts

  2. {

  3.     public virtual T GetProperty<T>() where T : class;

  4.     ... ...

  5.     TimeSpan IDefaultCommunicationTimeouts.CloseTimeout { get; }

  6.     TimeSpan IDefaultCommunicationTimeouts.OpenTimeout { get; }

  7.     TimeSpan IDefaultCommunicationTimeouts.ReceiveTimeout { get; }

  8.     TimeSpan IDefaultCommunicationTimeouts.SendTimeout { get; }

  9. }
複製代碼
3. 消息交換模式與Channel Shape
WCF完全採用基於消息的通信方式,對服務的消費最終通過一些列的消息交換實現。WCF應用在不同的場景中按照不同的模式進行消息交換。

3.1. 消息交換模式(MEP)
消息交換模式(Message Exchange Pattern:MEP)在SOA中是一個重要的概念。在W3C的文獻中對MEP的官方定義是這樣的:MEP定義了參與者進行消息交換的模板(原文是:a template that describes the message exchange between messaging participants.),這是一個很抽象的定義。實際上我們可以這樣來理解MEP:消息交換模式(MEP)代表一系列的模板,它們定義了消息的發送者和接收者相互進行消息傳輸的次序。比較典型的消息交換模式包含以下三種:數據報模式(Datagram)、請求/回覆模式(Request/Reply)以及雙工模式(Duplex)。

數據報模式(Datagram)

數據報模式是最簡單的消息交換模式,又稱爲發送/遺忘(Send/Forget)或者是單向模式(One-way)。數據報模式基於從一個源到一個或者多個目的地的單向消息傳輸。如圖3-9所示,在數據報模式下,消息的發送方將消息發送到接收方,並不希望收到對象的回覆。


[WCF中的Binding模型]之二: 信道與信道棧(Channel and Channel Stack)_9964
image_6.png(11.46 K)
11/14/2008 12:42:32 PM

圖3-9 數據報消息交換模式

數據報模式具有一些變形,比較典型的包括以下一些消息交換的方式:

  • 單目的地模式:一個消息的發送方將消息發送給單一的接收方
  • 多投模式:一個消息發送方將消息發送給一系列預定義的接收方
  • 廣播模式:和多投模式相似,只是接收方的範圍更加寬泛


數據報模式一般採用異步的消息發送方式,並不希望接收到對方的回覆消息,在個別情況下甚至不關心消息能否正常地被接收。

請求/回覆模式(Request/Reply)

在這三種典型的消息交換模式中,請求/回覆模式是使用得最多的一種模式。在這種模式下,消息發送方來將消息發送給接收方後會等待對方的回覆。請求/回覆模式的消息交換情況如下圖所示。請求/回覆模式一般採用同步的通信模式(儘管該模式也可以用於異步通信)。


[WCF中的Binding模型]之二: 信道與信道棧(Channel and Channel Stack)_9965
image_8.png(15.14 K)
11/14/2008 12:42:32 PM

圖3-10 請求-回覆消息交換模式

雙工模式(Duplex)

如果採用雙工的消息交換模式,在進行消息交換過程中,任何一方都可以向對方發送消息,如圖3-11所示。


[WCF中的Binding模型]之二: 信道與信道棧(Channel and Channel Stack)_9966
image_10.png(13.76 K)
11/14/2008 12:42:32 PM

圖3-11 雙工消息交換模式

雙工通信使服務端回調客戶端成爲可能:客戶端在調用服務的時候,指定一個回調對象,服務端操作執行過程中可以通過回調對象回調客戶端的操作。比較典型雙工通信是我們熟悉的訂閱/發佈模式。訂閱/發佈模式下的消息交換雙方的角色發生了變化,傳統的發送方和接收方變成了訂閱方和發佈方。訂閱方向發佈方發送訂閱消息定於某一主題進行訂閱,發佈方接收到訂閱消息後將訂閱方添加到訂閱列表之中。主題發佈的時候,發佈方提取當前主題的所有訂閱方,對它們進行消息廣播。

由於消息的交換依賴於網絡傳遞,所以消息交換模式與網絡協議的支持是一個不得不考慮的。對於雙工通信模式來說,它對於基於TCP協議的通信來說是完全沒有問題,因爲TCP協議本身就是全雙工的網絡通信協議。但是對於HTTP來說,它本身就是簡單的基於請求/回覆的網絡協議,是不支持雙工通信的。WCF通過WsDualHttpBinding實現了基於HTTP協議的雙工通信,實際上是採用了兩個HTTP通道實現的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章