对于一个分布式应用的开发与设计来说,通信问题是不得不考虑,同时也是最为复杂、最难实现的问题。在过去的若干年中, 微软先后推出了一系列广受欢迎的通信技术, 比如DCOM、Enterprise Service、.NET Remoting、XML Web Service、MSMQ等等。这些技术提供了各自的编程模型,是开发人员从繁琐的完全基于通信的编程中解脱出来,使之仅仅需要关注具体的业务逻辑。WCF是所有的这些通信技术集大成者,它充分地整合了所有这些使用于不同领域、不同场景的通信技术,提供了一个统一的编程模型。
无论从功能上讲,还是从WCF的整个基础构架的层次结构上讲,WCF可以分成两个不部分:编程模型和通信实现。编程模型通过WCF服务模型层(service mode layer)提供,而信道层 (channel layer) 则提供了具体的通信的实现。服务模型层建立在信道层之上,对于一般的WCF开发人员来讲,他们仅仅会接触到服务模型层,而信道层则是被屏蔽掉的。
二、 信道与信道栈(Channel and Channel Stack)
WCF的通信是基于消息的,如果从消息交换(message exchange)的角度讲,信道层则可以看成是进行消息交换参与者之间的中介。信道层通过一个个信道组成一个连续的信道栈,该信道栈构成了一个消息流通的管道。消息的发送者通过该管道流到消息的接收者,消息的接收者对消息进行相应的处理,生成新的消息通过该管道回复给消息的发送者。
但是,不要将这个通过一系列信道组成的管道的功能仅仅局限于消息的传输,实际上该管道承载着许多额外的功能。
我们可以打个比方,比如一个自来水厂,水源可能取自天然的湖水,在水厂生产的水最终通过自来水管流到居民的家中被饮用之前,需要对水进行必要的处理。中间的流程可能是这样的:湖水被汲取到一个池子中先进行杂质的过滤(我们称这个池为过滤池);被过滤后的水流到第二个池子中进行消毒处理(我们称这个池为消毒池);被消毒处理的后水流到第三个池子中进行水质软化处理(我们称这个池为软化池);最终水通过自来水管道流到居民的家中。
实际上,我们将的信道栈就相当于一个自来水厂,而构成信道栈的一个个信道就相当过滤池、消毒池、软化池以及自来水管道。唯一不同的是,自来水厂处理的是水,而信道栈处理的是消息(message)。这样设计的最大的好处就是具有很强的可扩展性,因为我们不可能、也没有必要设计出一种信道能够进行所有的消息处理任务,我们需要做的仅仅让一个信道专注于某一种功能的实现,通过对信道的合理组合从而实现我们实际的消息处理的功能。
对于一个自来水厂来说,最终的目的上自己生产的水让消费者能够饮用,所以自来水管道是必须的,至于中间的环节,过滤、消毒、软化、……,可能在水质良好的情况下就不是必要的了。与此类似,对于一个信道栈来说,有两种信道是必须的:传输信道(transport channel)和消息编码信道(message encoding channel)。原因很简单,信道栈的目的就是实现消息的传输,传输信道肯定是必须的,而进行传输的前提,需要对消息进行合理编码,比如基于文本编码和二进制编码。如下图所示:
由于WCF采用完全基于消息的通信方式,所有功能的实现,无论是业务有关的,还是业务无关的,都是通过消息交换来实现的。对于信道栈来说,除了必要的消息处理功能(消息编码与传输),为了一些额外的功能的实现需要添加新的信道。比如,对于无状态的http协议需要提供对会话的支持,需要添加相应的会话支持的信道;为了通过对事物的支持,将多个服务调用纳入同一个事物中,需要专门的事物支持的信道;为了减少网络流量,在传输之前需要对消息进行压缩,需要专门的消息压缩信道,等等。
从另一个方面讲,WCF是基于WS-*的,WS-*通过一系列的协议制定了一套业界的Web Service标准,使不同厂商之间的互操作成为可能。WCF对最新的WS-*提供了支持,而且毫无疑问,随着WS-*的逐步完善,WCF将会与之保持同步。对于绝大部分WS-*协议的支持,都是通过在信道栈中添加相应的信道实现的, 所以我们把这样的信道称为协议信道(protocol channel)。如下图所示,在传输信道和消息编码信道之上, WS-Security实现了消息层的安全;WS-RM(WS-Reliable Messaging)实现了可靠消息通信;WS-AT(WS-Atomic Transaction)实现了分布式的事务支持。
三、 WCF的绑定模型(WCF Binding Mode)
绑定模型如下图所示,其中最左边的部分就是信道栈,而右边就则是绑定对象本身。WCF通信的本质在于通过绑定对象提供的API构建信道栈,从而实现基于消息的通信。在信道栈和绑定之间,还存在着一些中间对象。它们是信道管理器(Channel Manager)、绑定元素(Binding Element)和绑定上下文(Binding Context)。
在整个绑定模型中,信道和信道栈位于最底层。信道栈是消息进行通信的通道,组成信道栈的各个信道处于各自的目的对消息进行相应的处理。按照功能划分,可以将信道分成三类:传输信道、消息编码信道和协议信道。传输信道实现了基于某种协议(HTTP、HTTPS、TCP等等)的消息传输;消息编码实现了对消息的编码,常见的消息编码方式有:Text/XML、Binary和MTOM;而协议信道则实现了WCF对若然WS-*协议的支持,比如WS-Security、WS-RM、WS-AT等等。
在WCF中,信道栈的创建和生命周期的管理通过信道管理器(channel manager)来进行管理。对于信道管理器,大家可能有点了陌生,不过如果回顾一下我们前面演示的通过绑定进行直接通信的例子,大家一定还记得这么两个对象:信道监听器(channel listener)和信道工厂(channel factory)。实际上,信道监听器和信道工厂是信道管理器两个别名。在服务端,通过信道监听器对服务请求进行监听,当请求消息被成功检测,则通过信道监听器创建信道栈对请求消息进行接收和处理;在客户端,信道栈被信道工厂创建,并用于请求消息的处理和发送。
一般来讲,信道管理器,无论是信道监听器还是信道工厂,都对应着一个绑定元素(binding element)对象。绑定元素负责对相应信道管理器的创建。从创建对象的角度来看,信道管理器负责对信道的创建 ,而绑定元素则负责对信道管理器的创建。绑定元素,顾名思义,就是组成绑定的元素。从本质上讲,每一个绑定对象,就是一个绑定元素对象的有序集合;绑定元素的构成和次序决定绑定对象的特性。
而我们所说的信道栈,指的是若干相关的信道按照一定的排列次序组成的一个消息流通的管道。信道栈中的信道的先后次序是如何来维护的呢?由于信道的创建者是信道管理器,所以信道管理者的次序决定信道的次序。从某种意义上讲,所有的信道管理器组成一个信道管理器栈。以此类推,信道管理器栈中每个信道管理器的先后次序由构成绑定对象的所有绑定元素的次序决定。但是绑定元素的次序先后次序又是如何决定的呢?那就需要使用到另一个有用的对象:绑定上下文(binding context)对象,一般来说,一个绑定上下文维护着基于该绑定对象当前绑定元素的有序列表,可以很容易地定位到下一个绑定元素。
WCF中的绑定模型:
[WCF中的Binding模型]之一: Binding模型简介
[WCF中的Binding模型]之二: 信道与信道栈(Channel and Channel Stack)
[WCF中的Binding模型]之三:信道监听器(Channel Listener)
[WCF中的Binding模型]之四:信道工厂(Channel Factory)
[WCF中的Binding模型]之五:绑定元素(Binding Element)
[WCF中的Binding模型]之六:从绑定元素认识系统预定义绑定