当前位置:编程学习 > 网站相关 >>

WCF后续之旅(3): WCF Service Mode Layer 的中枢—Dispatcher

在本系列的第一部分、第二部分中,我们对WCF的channel layer进行了深入的讨论。我们接下来继续讨论WCF的service mode layer。本篇文章着重介绍service 端的ServiceMode。写作此篇文章旨在达到以下两个目的:

希望读者对ServiceMode有一个大致的了解,结合前面介绍的channel layer的相关知识,帮助读者了解WCF的整个实现机制和执行的流程。
介绍ServiceMode涉及到的绝大部分extension point,让读者在具体的项目开发中能够根据实际的需要灵活、自由地对WCF进行扩展。
较之channel layer,ServiceMode要复杂得多,其内部隐藏了太多MS没有公布出来的实现细节。由于到目前为止,还不曾出现过关于此方面详细的官方介绍,以下所有的介绍来源于以下几个方面:

对MSDN的查阅
对相关WCF著作的查阅,比如《Programming WCF Service》、《Inside Microsoft Windows Communication Foundation》等等。
通过Reflector反射出来的代码的理解,本片文章的绝大部分内容来源于此。
所以,对于文中的某些表述,由于个人能力所限,可能有失偏颇。如有不当之处,还望各位朋友及时指正。

1. Dispatcher为我们做了什么?

由于应用WCF的是一个分布式环境,按照所处的环境的不同,可以将ServiceMode分成client端的ServiceMode和service端的ServiceMode。就其实现的复杂度而言,service端的ServiceMode要比client端的复杂很多。对于Service端来讲,WCF的ServiceMode需要解决的是:

如何根据不同的listening URI创建ChannelListener并进行监听;
当request抵达,如何创建适合的Channel接收request message;
如何将Message分发到对应的Endpoint进行处理;
如何进一步将Message分发到对应的service instance;
以及如何进一步地分发的具体的service instance的匹配的method call。
由于“分发(Dispatch)”是其根本的功能和任务,所以Dispatcher是整个Service端ServiceMode的核心。正如标题所述,Dispatcher是整个WCF service mode layer的中枢,本篇文章讲着重围绕着Dispatcher来展开介绍。

Dispatcher并不是指的某一个对象,而是指完成整个dispatch功能的一组相关对象的总称。这包括3个核心的对象:ChannelListener、ChannelDispatcher和EndpointDispatcher,和一些辅助的对象。

ChannelListener在本系列的前面两个部分已经进行了详细的介绍,我们知道其主要功能在于:绑定到一个固定的Listening URI,监听来自外界的请求。一旦请求抵达,创建对应的Channel接收Request message。但是我们的业务逻辑定义在一个个的service类中,所以WCF必须提供一种机制通过我们接收到的message去激活对应service instance并调用对应的方法。对于的激活(Activation)包含两种:创建一个新的service instance(PerCall instancing mode)和复用一个已经存在的service Instance(PerSession和Singleton instancing mode)。ChannelDispatcher的核心功能就是提供了这样一种功能(尽管它还提供了其他的有用的功能,为了是内容不至于太散,在这里就不再作相关的介绍)。ChannelDispatcher通常和一个ChannelListener关联,而ChannelListener又对应着一个固定的listening URI。对于一个被host的service来讲,可能定义了不同的listening address,所以一个service一般对应着一到多个ChannelDispatcher。更进一步说,当我们host一个service的时候,WCF会为之创建一个ServiceHostBase对象(ServiceHost或者是你自定义的继承自ServiceHostBase的对象),所以一个ServiceHostBase对象对应一到多个ChannelDispatcher对象。

对于接收到的request message,ChannelDispatcher不会自己对其进行处理,而是将其分发到与之相匹配为的EndpointDispatcher上,所以处理message的的绝大部分功能实际上是由EndpointDispatcher来实现的。对于同一个listening address,我们一般会不止一个endpoint,所以一个ChannelDispatcher拥有不止一个EndpointDispatcher。对于EndpointDispatcher来讲,有一个绝对绝对值得特别介绍的是DispatchRumtime。DispatchRumtime和一个特定的EndpointDispatcher匹配,通过定制DispatchRumtime,你可以很容易地按照你具体的需要改变整个service或者某个具体的Operation相关的运行时行为。对于WCF一门重要的课题, WCF extensions来讲,你的绝大部分BehaviorExtesionElment,都是通过具体的Behavior对DispatchRumtime进行定制而实现的。

2. WCF Dispatching System的执行流程

有了上面对于ChannelDispatcher和ChannelDispatcher的了解,我们来简单介绍一下WCF的Dispatching System得执行流程:

Step 1:ServiceHost和ServiceDescription的创建

WCF service不能独立地执行,必须Host到一个可执行程序中,可以使一般的managed application、IIS、WAS和Windows service等等。Hosting的工作一般分两个步骤,为service创建ServiceHost;打开ServiceHost开始监听请求。

注:确实地讲,完成Hosting的不一定是ServiceHost,任何继承自SerivceHostBase的都可以用于service的hosting。ServiceHost继承自ServiceHostBase,我们一般用它来完成Hosting的工作;为了简单,这里的ServiceHost可以看成是任何继承自己ServiceHostBase的Service Host type。

ServiceHost提供了两个重载的constructor:

public ServiceHost(object singletonInstance, params Uri[] baseAddresses);
public ServiceHost(Type serviceType, params Uri[] baseAddresses); 第一个constructor接收一个service instance,采用Singleton的instancing mode进行Host;而另一个传入service type进行hosting,instancing mode有ServiceBehavior的InstanceContextMode决定。

构造serviceHost,最重要的任务是通过reflection或者解析configuration的方式创建ServiceDescription。这个创建出来的ServiceDescition将是所有后续工作的根本依据。我们来简单了解一下ServiceDescription的属性定义:

public class ServiceDescription
{
// Properties
public KeyedByTypeCollection<IServiceBehavior> Behaviors { get; }
public string ConfigurationName { get; set; }
public ServiceEndpointCollection Endpoints { get; }
public string Name { get; set; }
public string Namespace { get; set; }
public Type ServiceType { get; set; }
} 这里最重要的两个属性是Behaviors 和Endpoints:

Behaviors :和service相关的所有service behavior的集合,这里的service behavior仅包含你通过ServiceBehaviorAttribute指定的service behavior,也包含一些自定义的custom service behavior(自定义service behavior在WCF extension中十分常见)。由于该属性的类型是KeyedByTypeCollection<IServiceBehavior> ,所以很容易通过具体的service behavior type得到对应的behavior。
Endpoints:service相关联的所有ServiceEndpoint的集合。下面是ServiceEndpoint的属性定义:
public class ServiceEndpoint
{
public EndpointAddress Address { get; set; }
public KeyedByTypeCollection<IEndpointBehavior> Behaviors { get; }
public Binding Binding { get; set; }
public ContractDescription Contract { get; }
public Uri ListenUri { get; set; }
public ListenUriMode ListenUriMode { get; set; }
public string Name { get; set; }
}除了构成Endpoint的ABC:Address、Binding和Contract之外还有重要的属性Behaviors,一个包含所有EndpointBehavior的集合。ServiceBehavior、EndpointBehavior、ContractBehavior以及OperationBehavior是我们用户WCF extension的“四大”behavior。这里再额外提一下Contract对应的类型ContractDescription 的定义:

public class ContractDescription
{
public KeyedByTypeCollection<IContractBehavior> Behaviors { get; }
public Type CallbackContractType { get; set; }
public string ConfigurationName { get; set; }
public Type ContractType { get; set; }
public bool HasProtectionLevel { get; }
public string Name { get; set; }
public string Namespace { get; set; }
public OperationDescriptionCollection Operations { get; }
public ProtectionLevel ProtectionLevel { get; set; }
public SessionMode SessionMode { get; set; }
} Behaviors :所有ContractBehavior的集合。
ContractType :Contract的类型,返回标注了ServiceContractAttribute的class对应的type,可能是interface也可能是class。
Operations :Contract中所有Operation的描述,每个元素与应用了OperationAttribute的method一一匹配。 OperationDescriptionCollection 的定义也相当重要,至于具体的定义,可以参考MSDN,限于篇幅,在这里就不多作介绍了。
SessionMode:Session的模式:Allowed、Required、NotAllowed。
注:当通过实例化ServiceHost创建的ServiceDescription可以通过SeriviceHost对象的Description属性获得,你还可以代码的方式对其进行添加、删除和修改。

Step 2:ServiceHost.Open()和Channel Listener & ChannelDipatcher的创建

当调用ServiceHost instance的Open方法后。WCF遍历ServiceHost的Endpoints属性中的每个ServiceEndpoint,对于每个不同的不同的ListenUri和ListenUriMode的不同,通过Service

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,