1. CommunicationObject與DefaultCommunicationTimeouts
WCF綁定模型涉及多種類型的組件,比如信道、信道監聽器、信道工廠等等。從功能上講,這些對象都是爲通信服務的,我們可以把它們稱爲通信對象(Communication Object)。對於這些通信對象來說,在通信不同的階段,它們往往具有不同的狀態;從整個通信的生命週期來看,在不同階段過渡的過程中,它們具有一些相似的狀態轉換方式。
WCF定義了一個特殊的接口,System.ServiceModel.ICommunicationObject,來管理通信對象的狀態和狀態的轉換。下面是ICommunicationObject的定義:
- public interface ICommunicationObject
- {
- // Events
- event EventHandler Closed;
- event EventHandler Closing;
- event EventHandler Faulted;
- event EventHandler Opened;
- event EventHandler Opening;
- // Methods
- void Open();
- void Open(TimeSpan timeout);
- IAsyncResult BeginOpen(AsyncCallback callback, object state);
- IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state);
- void EndOpen(IAsyncResult result);
- void Close();
- void Close(TimeSpan timeout);
- IAsyncResult BeginClose(AsyncCallback callback, object state);
- IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state);
- void EndClose(IAsyncResult result);
- void Abort();
- // Properties
- CommunicationState State { get; }
- }
- public enum CommunicationState
- {
- Created,
- Opening,
- Opened,
- Closing,
- Closed,
- Faulted
- }
- 事件:當正在進行狀態轉化,或者是狀態轉換成功,會觸發相應的事件。通過註冊相應的事件,可以在某個狀態轉換環節中注入你需要的處理操作。
- 方法:定義了三種類型的操作:開啓(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。
- public abstract class CommunicationObject : ICommunicationObject
- {
- ...
- }
圖3-8 CommunicationObject繼承關係
由於WCF往往需要跨域網絡進行服務的訪問,較之一般的方法調用,服務訪問的所花的時間往往較長,所以對超時的處理顯得異常重要。比如對於消息的發送,可能由於網絡的故障,該消息在一端時間內根本無法成功發送,客戶端程序不可能無限制地等待下去。一般的情況下,我們會設定一個操作執行的所允許的最大時限,一旦超時則取消操作,並進行相應的超時處理。
我們回顧一下ICommunicationObject的Open和BeginOpen方法,我們會發現它們各有兩個重載,其中一個具有的TimeSpan類型的timeout參數,另一個則沒有。在這裏的timeout參數實際上代表Open方法執行的超時時間,如果Open操作執行的時間過長,一旦超過了該事件,操作將被立即中止。
- public interface ICommunicationObject
- {
- void Open();
- void Open(TimeSpan timeout);
- IAsyncResult BeginOpen(AsyncCallback callback, object state);
- IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state);
- ... ...
- }
- public interface IDefaultCommunicationTimeouts
- {
- // Properties
- TimeSpan CloseTimeout { get; }
- TimeSpan OpenTimeout { get; }
- TimeSpan ReceiveTimeout { get; }
- TimeSpan SendTimeout { get; }
- }
2. IChannel和ChannelBase
WCF中信道層中的每種類型的信道直接或者間接實現了接口System.ServiceModel.Channels.IChannel,IChannel的定義異常簡單,僅僅具有一個唯一範型方法成員:GetProperty<T>()。
- public interface IChannel : ICommunicationObject
- {
- // Methods
- T GetProperty<T>() where T : class;
- }
除了IChannel接口之外,WCF還定義了一個實現了IChannel接口的基類:System.ServiceModel.Channels.ChannelBase。。除了實現了IChannel接口,ChannelBase還實現了另外兩個接口:ICommnucationObject和IDefaultCommunicationTimeouts,並直接繼承自CommnucationObject。
- public abstract class ChannelBase : CommunicationObject, IChannel, ICommunicationObject, IDefaultCommunicationTimeouts
- {
- public virtual T GetProperty<T>() where T : class;
- ... ...
- TimeSpan IDefaultCommunicationTimeouts.CloseTimeout { get; }
- TimeSpan IDefaultCommunicationTimeouts.OpenTimeout { get; }
- TimeSpan IDefaultCommunicationTimeouts.ReceiveTimeout { get; }
- TimeSpan IDefaultCommunicationTimeouts.SendTimeout { get; }
- }
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所示,在數據報模式下,消息的發送方將消息發送到接收方,並不希望收到對象的回覆。
圖3-9 數據報消息交換模式
數據報模式具有一些變形,比較典型的包括以下一些消息交換的方式:
- 單目的地模式:一個消息的發送方將消息發送給單一的接收方
- 多投模式:一個消息發送方將消息發送給一系列預定義的接收方
- 廣播模式:和多投模式相似,只是接收方的範圍更加寬泛
數據報模式一般採用異步的消息發送方式,並不希望接收到對方的回覆消息,在個別情況下甚至不關心消息能否正常地被接收。
請求/回覆模式(Request/Reply)
在這三種典型的消息交換模式中,請求/回覆模式是使用得最多的一種模式。在這種模式下,消息發送方來將消息發送給接收方後會等待對方的回覆。請求/回覆模式的消息交換情況如下圖所示。請求/回覆模式一般採用同步的通信模式(儘管該模式也可以用於異步通信)。
圖3-10 請求-回覆消息交換模式
雙工模式(Duplex)
如果採用雙工的消息交換模式,在進行消息交換過程中,任何一方都可以向對方發送消息,如圖3-11所示。
圖3-11 雙工消息交換模式
雙工通信使服務端回調客戶端成爲可能:客戶端在調用服務的時候,指定一個回調對象,服務端操作執行過程中可以通過回調對象回調客戶端的操作。比較典型雙工通信是我們熟悉的訂閱/發佈模式。訂閱/發佈模式下的消息交換雙方的角色發生了變化,傳統的發送方和接收方變成了訂閱方和發佈方。訂閱方向發佈方發送訂閱消息定於某一主題進行訂閱,發佈方接收到訂閱消息後將訂閱方添加到訂閱列表之中。主題發佈的時候,發佈方提取當前主題的所有訂閱方,對它們進行消息廣播。
由於消息的交換依賴於網絡傳遞,所以消息交換模式與網絡協議的支持是一個不得不考慮的。對於雙工通信模式來說,它對於基於TCP協議的通信來說是完全沒有問題,因爲TCP協議本身就是全雙工的網絡通信協議。但是對於HTTP來說,它本身就是簡單的基於請求/回覆的網絡協議,是不支持雙工通信的。WCF通過WsDualHttpBinding實現了基於HTTP協議的雙工通信,實際上是採用了兩個HTTP通道實現的。