WCF服务端运行时架构体系详解[中篇]
在这篇文章中,我们对信道分发器本身作一个深入的了解,首先来看看它具有哪些可供扩展的组件,以及我们可以针对信道分发器对WCF实现哪些可能的扩展。
信道分发器对应的类型为ChannelDispatcher,下面的代码片断给出了ChannelDispatcher部分属性成员的定义。而这些属性代表了包含在信道分发器中那些可供扩展的组件。信道分发器是基于信道易做图创建的,后者用于请求消息的监听和消息接收信道栈的创建。信道易做图对应于只读属性Listener。
1: public class ChannelDispatcher : ChannelDispatcherBase 2: { 3: //其他成员 4: public SynchronizedCollection<IChannelInitializer> ChannelInitializers { get; } 5: public Collection<IErrorHandler> ErrorHandlers { get; } 6: public ServiceThrottle ServiceThrottle { get; set; } 7: 8: public override IChannelListener Listener { get; } 9: }
ErrorHandler & ServiceThrottle
而属性ErrorHandlers代表的是一组ErrorHandler对象的集合。而ErrorHandler用于异常的处理的错误消息的提供。而类型为ServiceThrottle的同名属性用于进行流量控制,相关的内容你也可以参考《WCF中并发(Concurrency)与限流(Throttling)》。
ChannelInitializer
至于属性ChannelInitializers,则代表的是一组实现了接口System.ServiceModel.Dispatcher.IChannelInitializer的被称为信道初始化器的对象。顾名思义,所谓信道初始化器,就是当服务信道被创建之后用于对其进行初始化操作。接口IChannelInitializer的定义如下,它只具有一个唯一的Initialize方法。
1: public inte易做图ce IChannelInitializer 2: { 3: void Initialize(IClientChannel channel); 4: }
从扩展性角度来讲,你可以将自定义的ErrorHandler和ServiceThrottle应用到信道分发器中分别实现对异常的处理和流量的控制。你也可以自定义信道初始化器改变创建的信道状态。上述的关于信道分发器的结构可以简单地通过下图表示。
信道分发器结构
为了实现自定义的异常处理和流量扩展等功能,你可以将自定义的相关组件应用到信道分发器中。另一方面,信道分发器本身具有一些用于控制器运行行为的属性。你也可以根据需要改变这些属性是信道分发器按照你希望的行为进行运作。下面的代码片断列出了信道分发器主要的可供修改的属性。其中通过属性MessageVersion表示的消息的版本(SOAP版本和WS-Addressing版本)决定于绑定的同名属性。
1: public class ChannelDispatcher : ChannelDispatcherBase 2: { 3: //其他成员 4: public bool IncludeExceptionDetailInFaults { get; set; } 5: public bool ManualAddressing { get; set; } 6: public MessageVersion MessageVersion { get; set; } 7: public int MaxPendingReceives { get; set; } 8: public bool ReceiveSynchronously { get; set; } 9: public bool IsTransactedReceive { get; set; } 10: public int MaxTransactedBatchSize { get; set; } 11: public IsolationLevel TransactionIsolationLevel { get; set; } 12: public TimeSpan TransactionTimeout { get; set; } 13: }
IncludeExceptionDetailInFaults
IncludeExceptionDetailInFaults:表示服务端抛出的异常的详细信息是否需要通过错误消息回传给客户端。基于安全的需要,该属性的默认值为False。通常只有在调试的时候我们才需要让客户端得到服务端原始的错误信息,所以这个开关由服务行为ServiceDebugBehavior来控制。如下面的代码所示,ServiceDebugBehavior具有一个同名的属性。你也可以直接通过在服务类型上应用ServiceBehaviorAttribute特性通过命名属性控制这个开关。关于该属性背后的原理,你可以参考我的文章《ServiceDebugBehavior服务行为是如何实现异常的传播的?》
1: public class ServiceDebugBehavior : IServiceBehavior 2: { 3: //其他成员 4: public bool IncludeExceptionDetailInFaults { get; set; } 5: } 6: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior 7: { 8: //其他成员 9: public bool IncludeExceptionDetailInFaults { get; set; } 10: }
ManualAddressing
而属性ManualAddressing则涉及到寻址(Addressing)的概念。对于一个支持WS-Addressing的SOAP消息来说,在其报头列表中包括一系列WS-Addressing报头(比如To、ReplyTo、RelatesTo等)以提供消息路由需要的寻址信息。在默认的情况下,这些寻址报头最终是通过位于信道栈最底层的传输信道(Transport Channel)来添加的。但是在某些情况下,我们希望手工地位消息添加相应的寻址报头,并希望该消息按照这些手工添加的寻址信息进行路由。我们将这种机制成为手工寻址(Manual Addressing)。
如果启用手工寻址,当消息最终通过传输信道向传输层发送的时候,传输信道会认为相应的寻址报头已经被成功添加,所以不会进行寻址报头的重复添加。ChannelDispatcher的ManualAddressing属性表示是否启用了手工寻址,其默认值决定于绑定的传输绑定元素的同名属性。按照寻址的需要,你可以在运行时动态变该属性值强制启用或者禁用手工寻址。
1: public abstract class TransportBindingElement : BindingElement 2: { 3: //其他成员 4: public bool ManualAddressing { get; set; } 5: }
MaxPendingReceives
MaxPendingReceives表示允许的最大挂起(未处理)的消息数,默认值为1。该值可以通过终结点行为DispatcherSynchronizationBehavior来修改。如下所示,DispatcherSynchronizationBehavior具有一个同名的属性。
1: public class DispatcherSynchronizationBehavior : IEndpointBehavior 2: { 3: //其他成员 4: public int MaxPendingReceives { get; set; } 5: }
ReceiveSynchronously
对于服务端信道层对请求消息的接收,到底采用同步还是异步的方式更加有效往往取决于具体采用的通信方式。在默认的情况下,对于同步/异步消息接收方式的选择取决于终结点的绑定。对于所有的系统预定义绑定类型,它们都实现了一个特殊的接口IBindingRuntimePreferences。如下面的代码片断所示,IBindingRuntimePreferences接口具有一个唯一的只读属性:ReceiveSynchronously。该属性就表示具体的绑定是否应该采用同步的消息接收方式。而在默认的情况下,绑定的ReceiveSynchronously属性值被作为对应的信道分发器的同名属性值。
1: public inte易做图ce IBindingRuntimePreferences 2: { 3: bool ReceiveSynchronously { get; } 4: }
对于几个我们常用的系统预定义绑定(BasicHttpBinding、WSHttpBinding、WSHttp2007Binding、WSDualHttpBinding、NetTcpBinding、NetNamedPipeBinding和NetMsmqBinding),除了NetMsmqBinding的ReceiveSynchronously属性可以是True外,其他绑定的该属性总是返回False。也就是说,除了NetMsmqBinding,其他的绑定总是以异步的方式进行消息的接收,这样可以及时地处理同时抵达的消息请求,并极大的改善服务的吞吐量。而对于NetMsmqBinding来说,它的ReceiveSynchronously属性和ExactlyOnce具有相同的值。
虽然在默认的情况下,绑定的ReceiveSynchronously属性决定了信道分发器的同名属性。但是你也可以通过扩展来改变该属性值。实际上,WCF为我们定义了一个类型为System.ServiceModel.Description.SynchronousReceiveBehavior的终结点行为来对信道分发器的ReceiveSynchronously属性值进行设定。当终结点应用了该行为之后,对应的信道分发器被自动设置为True,意味着采用同步的方式接收请求消息。
IsTransactedReceiv
补充:Web开发 , ASP.Net ,