WCF服務端運行時架構體系詳解[中篇]

作者: Artech  來源: 博客園  發布時間: 2011-12-27 10:37  閱讀: 3087 次  推薦: 0   原文鏈接   [收藏]  
摘要:在這篇文章中,我們對信道分發器本身作一個深入的了解,首先來看看它具有哪些可供擴展的組件,以及我們可以針對信道分發器對WCF實現哪些可能的擴展。

目錄:
ErrorHandler & ServiceThrottle
ChannelInitializer
IncludeExceptionDetailInFaults
ManualAddressing
MaxPendingReceives
ReceiveSynchronously
IsTransactedReceive & MaxTransactedBatchSize
TransactionIsolationLevel & TransactionTimeout

  信道分發器對應的類型為ChannelDispatcher,下面的代碼片斷給出了ChannelDispatcher部分屬性成員的定義。而這些屬性代表了包含在信道分發器中那些可供擴展的組件。信道分發器是基于信道監聽器創建的,后者用于請求消息的監聽和消息接收信道棧的創建。信道監聽器對應于只讀屬性Listener。

public class ChannelDispatcher : ChannelDispatcherBase
{

//其他成員
public SynchronizedCollection<IChannelInitializer> ChannelInitializers { get; }
public Collection<IErrorHandler> ErrorHandlers { get; }
public ServiceThrottle ServiceThrottle { get; set; }

publicoverride IChannelListener Listener { get; }
}

  ErrorHandler & ServiceThrottle

  而屬性ErrorHandlers代表的是一組ErrorHandler對象的集合。而ErrorHandler用于異常的處理的錯誤消息的提供。而類型為ServiceThrottle的同名屬性用于進行流量控制,相關的內容你也可以參考《WCF中并發(Concurrency)與限流(Throttling)》。

  ChannelInitializer

  至于屬性ChannelInitializers,則代表的是一組實現了接口System.ServiceModel.Dispatcher.IChannelInitializer的被稱為信道初始化器的對象。顧名思義,所謂信道初始化器,就是當服務信道被創建之后用于對其進行初始化操作。接口IChannelInitializer的定義如下,它只具有一個唯一的Initialize方法。

public interface IChannelInitializer
{

void Initialize(IClientChannel channel);
}

  從擴展性角度來講,你可以將自定義的ErrorHandler和ServiceThrottle應用到信道分發器中分別實現對異常的處理和流量的控制。你也可以自定義信道初始化器改變創建的信道狀態。上述的關于信道分發器的結構可以簡單地通過下圖表示。

clip_image002信道分發器結構

  為了實現自定義的異常處理和流量擴展等功能,你可以將自定義的相關組件應用到信道分發器中。另一方面,信道分發器本身具有一些用于控制器運行行為的屬性。你也可以根據需要改變這些屬性是信道分發器按照你希望的行為進行運作。下面的代碼片斷列出了信道分發器主要的可供修改的屬性。其中通過屬性MessageVersion表示的消息的版本(SOAP版本和WS-Addressing版本)決定于綁定的同名屬性。

public class ChannelDispatcher : ChannelDispatcherBase
{

//其他成員
public bool IncludeExceptionDetailInFaults { get; set; }
public bool ManualAddressing { get; set; }
public MessageVersion MessageVersion { get; set; }
public int MaxPendingReceives { get; set; }
public bool ReceiveSynchronously { get; set; }
public bool IsTransactedReceive { get; set; }
public int MaxTransactedBatchSize { get; set; }
public IsolationLevel TransactionIsolationLevel { get; set; }
public TimeSpan TransactionTimeout { get; set; }
}

  IncludeExceptionDetailInFaults

  IncludeExceptionDetailInFaults:表示服務端拋出的異常的詳細信息是否需要通過錯誤消息回傳給客戶端。基于安全的需要,該屬性的默認值為False。通常只有在調試的時候我們才需要讓客戶端得到服務端原始的錯誤信息,所以這個開關由服務行為ServiceDebugBehavior來控制。如下面的代碼所示,ServiceDebugBehavior具有一個同名的屬性。你也可以直接通過在服務類型上應用ServiceBehaviorAttribute特性通過命名屬性控制這個開關。關于該屬性背后的原理,你可以參考我的文章《ServiceDebugBehavior服務行為是如何實現異常的傳播的?

public class ServiceDebugBehavior : IServiceBehavior
{

//其他成員
public bool IncludeExceptionDetailInFaults { get; set; }
}

public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
{

//其他成員
public bool IncludeExceptionDetailInFaults { get; set; }
}

  ManualAddressing

  而屬性ManualAddressing則涉及到尋址(Addressing)的概念。對于一個支持WS-Addressing的SOAP消息來說,在其報頭列表中包括一系列WS-Addressing報頭(比如To、ReplyTo、RelatesTo等)以提供消息路由需要的尋址信息。在默認的情況下,這些尋址報頭最終是通過位于信道棧最底層的傳輸信道(Transport Channel)來添加的。但是在某些情況下,我們希望手工地位消息添加相應的尋址報頭,并希望該消息按照這些手工添加的尋址信息進行路由。我們將這種機制成為手工尋址(Manual Addressing)。

  如果啟用手工尋址,當消息最終通過傳輸信道向傳輸層發送的時候,傳輸信道會認為相應的尋址報頭已經被成功添加,所以不會進行尋址報頭的重復添加。ChannelDispatcher的ManualAddressing屬性表示是否啟用了手工尋址,其默認值決定于綁定的傳輸綁定元素的同名屬性。按照尋址的需要,你可以在運行時動態變該屬性值強制啟用或者禁用手工尋址。

public abstract class TransportBindingElement : BindingElement
{

//其他成員
public bool ManualAddressing { get; set; }
}

  MaxPendingReceives

  MaxPendingReceives表示允許的最大掛起(未處理)的消息數,默認值為1。該值可以通過終結點行為DispatcherSynchronizationBehavior來修改。如下所示,DispatcherSynchronizationBehavior具有一個同名的屬性。

public class DispatcherSynchronizationBehavior : IEndpointBehavior
{
 
//其他成員
public int MaxPendingReceives { get; set; }
}

  ReceiveSynchronously

  對于服務端信道層對請求消息的接收,到底采用同步還是異步的方式更加有效往往取決于具體采用的通信方式。在默認的情況下,對于同步/異步消息接收方式的選擇取決于終結點的綁定。對于所有的系統預定義綁定類型,它們都實現了一個特殊的接口IBindingRuntimePreferences。如下面的代碼片斷所示,IBindingRuntimePreferences接口具有一個唯一的只讀屬性:ReceiveSynchronously。該屬性就表示具體的綁定是否應該采用同步的消息接收方式。而在默認的情況下,綁定的ReceiveSynchronously屬性值被作為對應的信道分發器的同名屬性值。

public interface IBindingRuntimePreferences
{

bool ReceiveSynchronously { get; }
}

  對于幾個我們常用的系統預定義綁定(BasicHttpBinding、WSHttpBinding、WSHttp2007Binding、WSDualHttpBinding、NetTcpBinding、NetNamedPipeBinding和NetMsmqBinding),除了NetMsmqBinding的ReceiveSynchronously屬性可以是True外,其他綁定的該屬性總是返回False。也就是說,除了NetMsmqBinding,其他的綁定總是以異步的方式進行消息的接收,這樣可以及時地處理同時抵達的消息請求,并極大的改善服務的吞吐量。而對于NetMsmqBinding來說,它的ReceiveSynchronously屬性和ExactlyOnce具有相同的值。

  雖然在默認的情況下,綁定的ReceiveSynchronously屬性決定了信道分發器的同名屬性。但是你也可以通過擴展來改變該屬性值。實際上,WCF為我們定義了一個類型為System.ServiceModel.Description.SynchronousReceiveBehavior的終結點行為來對信道分發器的ReceiveSynchronously屬性值進行設定。當終結點應用了該行為之后,對應的信道分發器被自動設置為True,意味著采用同步的方式接收請求消息。

  IsTransactedReceive & MaxTransactedBatchSize

  接下來,我們來關于信道分發器與事務相關的幾個屬性。首先是基于事務的消息接收。為了判斷某個綁定是否支持事務性消息接收,WCF定義了名稱為System.ServiceModel.Channels.ITransactedBindingElement的接口。從下面給出的定義可以看出,ITransactedBindingElement具有唯一的只讀屬性TransactedReceiveEnabled,表明是否需要將消息的接收工作納入到事務中進行。

public interface ITransactedBindingElement
{

bool TransactedReceiveEnabled { get; }
}

  從接口的名稱我們就可以看出來,ITransactedBindingElement是為綁定元素定義的接口。對于一個具體的綁定來說,只要它的綁定元素列表中具有任何一個綁定元素實現了ITransactedBindingElement接口,并且TransactedReceiveEnabled屬性返回True,就意味著這是一個基于事務性消息接收的綁定。而綁定的是否支持事務性消息接收在默認的情況下反應在信道分發器的IsTransactedReceive屬性上,而另一個屬性MaxTransactedBatchSize則表示允許納入同一個事務進行的最大消息接收操作數。對于WCF預定義的所有綁定元素,只有基于MSMQ的兩個綁定元素MsmqTransportBindingElementMsmqIntegrationBindingElement實現了ITransactedBindingElement接口。

  對于最初決定于綁定的這兩個基于事務性消息接收的屬性,我們也可以通過擴展對其進行動態修改以強制或者避免進行事務性消息接收。而對于MaxTransactedBatchSize屬性的設定,WCF同樣為我們定義了相應的終結點屬性:System.ServiceModel.Description.TransactedBatchingBehavior。信道分發器的MaxTransactedBatchSize對應于TransactedBatchingBehavior的MaxBatchSize屬性。

public class TransactedBatchingBehavior : IEndpointBehavior
{

//其他成員
public int MaxBatchSize { get; set; }
}

  TransactionIsolationLevel & TransactionTimeout

  如果你閱讀看了我的文章《WCF事務編程([上篇][中篇][下篇])》你應該對信道分發器的另外兩個基于事務的屬性TransactionIsolationLevel和TransactionTimeout不會感到陌生。它們代表在事務的隔離級別和超時時限。這兩個屬性對應于我們熟悉的ServiceBehaviorAttribute特性的同名屬性。

[AttributeUsage(AttributeTargets.Class)]
public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
{

//其他成員
public IsolationLevel TransactionIsolationLevel { get; set; }
public string TransactionTimeout { get; set; }
}

0
0
 
標簽:WCF
 
 

文章列表

arrow
arrow
    全站熱搜

    大師兄 發表在 痞客邦 留言(0) 人氣()