复习WCF(9)----- 大型数据和流

 

WCF是基于XML的通信基础结构

 

编码数据:文本和2进制

~最常有的顾虑包括:认为与二进制格式相比XML的开销非常可观(因为其开始标记和结束标记的重复性),数值的编码可能要大的多(因为他们是以文本值来表示的)

并且没有办法有效的表示2进制数据(因为他们必须进行特殊的编码才能嵌入到文本格式中)

~尽管上面的问题是存在的,但是在XML Web Service环境中的XML文本编码消息与旧式的远程过程调用(RPC)环境的2进制编码消息之间的实际差异,通常远远小

于最初考虑中所预想的程度。(也就是说,XML的文本编码,并没有比我们以往的RPC环境里的2进制编码要大很多)

~虽然XML是透明可读的,但其实也没那么好可读(那么多标签那么多节点也是很头痛的) ,但是相比来说,2进制消息则是相当晦涩,没有工具根本就无法理解......

所以通常来说,易读性绝对是XML好多了,那么我们很容易就忽略了这一点:2进制的消息里面呢,它还有一部分的元数据(这个元数据也会增加开销,就像XML里的重复

标签也会增加开销一样)。

~所以如果要选择2进制或者XML,不能简单的认为2进制就小于XML

~XML文本消息的一个明确而无可争议的优点是:它们是基于标准的,并且提供最为广泛的互操作性选项和平台支持

 

二进制内容

~从最终的消息大小来说,2进制编码肯定是会优于文本编码的,优于文本编码只是在某些地方才优于,比如说传图片、视频、音效或者是一些其他的非透明的2进制数据。

2进制在传输这些内容的时候,肯定是比文本有优势得多,因为如果这些东西要放到文本里的话就要做特殊的编码,比如说最常用的就是Base64编码

~在Base64编码的字符串里,每个字符都表示原始8位数据的6位,这导致Base64的编码开销比率是4:3,而且还有些额外的格式字符(回车啊换行啊什么的),虽然

XML编码与2进制编码之间的差异显著与否通常取决于具体情况,但是当传送500MB时大小增加超过33%通常是不受欢迎的

~所以为了避免这种编码开销,WCF有个新的“消息传输优化机制(MTOM)”,这个机制允许将消息中包含的大型数据元素外部化(就是说不要把它编码到XML的文本里面去)

将其作为一个无任何特殊编码的2进制数据随消息一起传送,有点像附件啊嵌入的内容,利用传输协议(SMTP)电子邮件类似的方式交换。MTOM会打包为多部分/相关MIME序列

其中根部分是实际的SOAP消息(就是SOAP消息里只是做一些类似Link的感觉,这些类似Link的动作告诉我们有一部分内容是放在外部的)

~但是,与Base64一样,对于MIME格式,MTOM也有一些不必要的开销(你看,因为把数据附加在后面,而且在原始的消息里面加了一部分说明信息,也就是开始说的类似于

Link的动作,肯定会增加一些开销的对不对),这样仅在2进制数据元素的大小超过1KB时,才能体现出使用MTOM的好处

 

大型的数据内容

~不考虑网络带宽,如果要传500MB的东西,默认情况下,WCF会以缓冲的模式处理消息(就是意味着整个消息,在发送前和接收后,都存在在内存中,就是说消息传到服务器

后先全部存在内存中,然后再去处理消息)。尽管对于大多数情形来说这是个很好的策略,并且是消息传递功能(如数字签名)和可靠传递所必须的,但是大型消息可能很容易

最终导致耗尽系统资源

~处理大型负载的策略是流!尽管消息(尤其是以XML表示的消息)通常会被认为是相对紧凑的数据包,但消息大小也可能达到GB的等级,从而与连续的数据流很相似,而不是

易于处理的数据包。当以流模式而不是缓冲模式传输数据时,发送方会以流的形式将消息正文的内容提供给接收方,并且消息基础结构会不断的将已经就绪的数据从发送方转发

给接收方

~传输此类大型数据内容的最常见情形是传输具有以下特点的二进制数据对象:

    1.无法方便的分成消息序列

    2.必须以及时方式传递

    3.当开始传输时,还不是已经全部就绪

 

 

编码

~编码定义了一组规则,规定消息在线路中的存在形式

~编码器实现此类编码,并负责将Message内存中消息转变为可以通过网络发送的字节流或字节缓冲区(对于发送方而言是这样)。在接收方,编码器会将一系列字节转为内存里

的消息

WCF包括3个编码器

1.TextMessageEncodingBindingElement

       文本消息编码器是所有基于Http的绑定的默认编码器(所有HTTP绑定默认都是以文本编码来传输的),并且是最关注互操作性的所有自定义绑定的正确选择。此编码器读取

和编写标准SOAP1.1/SOAP1.2文本消息,而不会对2进制数据进行任何特殊处理。如果消息的MessageVersion设置为None,则SOAP信封包装会从输出中省略,只有消息正文

内容会进行序列化

2.MtomMessageEncodingBindingElement

       MTOM消息编码器也是一个文本编码器,但是可以实现对2进制数据的特殊处理,默认情况下在任何标准绑定中都不会使用,因为它是一个严格按具体情况进行优化的实用工具

只有当2进制数据的量/大小,不超过某个阀值的时候,MTOM才具有优势,如果消息包含的2进制数据超过了这个阀值,则这些数据会外部化到消息信封之后的MIME部分

3.BinaryMessageEncodingBindingElement

       二进制消息编码器是Net* 绑定的默认编码器(以Net打头的编码器,比如Net.Tcp、Net.Msmq等等),当通信的双方都基于WCF时,这个编码器始终是正确的选择。二进制

消息编码器使用.Net二进制XML格式,该格式是XML信息集(Infomation Sets,Infosets)的Microsoft特定二进制表示法,与等效的XML1.0表示法相比产生的需求量通常较小,并

将二进制数据编码为字节流

 

每一个标准绑定都包括一个预配置编码器,因此默认情况下带Net*前缀的绑定使用2进制编码器(通过BinaryMessageEncodingBindingElement类),而BasicHttpBinding

和WSHttpBinding类则使用文本消息编码器(通过TextMessageEncodingBindingElement类)

 

通常,文本消息编码是要求互操作性的任意通信路径的最佳选择,而2进制的消息编码则是其他任意通信路径的最佳选择。通常,对于单个消息而言,二进制消息编码生成的消息

大小要小于文本编码,并且在通信会话期间消息大小会逐渐变的更小。与文本编码不同的是,二进制编码不需要对二进制数据使用特殊处理(例如Base64)。

 

 

启用MTOM

当要求互操作性,并且必须发送大型二进制数据时,MTOM消息编码是一个备选的编码策略,可以在标准BasicHttpBinding或WsHttpBinding绑定上启用它,方法是:将该绑定

的MessageEncoding属性设置为Mtom,或者将MtomMessageEncodingBindingElement编写为CustomBinding 如图:

 

因为MTOM是在绑定级别启用的,所以启用MTOM会影响给定终结点上所有的操作,通常情况下,只有在终结点交换超过1KB二进制数据的消息时,才启用MTOM

 

编程模型

不论在应用程序中使用三个内置编码器中的哪一个,在传输二进制数据方面的编程体验都是相同的,区别在于WCF如何基于数据类型来处理数据

 

 

数据的流模式

当有大量数据要传输时,WCF中的流传输模式是整体缓冲和处理内存中消息的默认行为的一个可行的替代方法

如果数据无法分段、消息必须以及时的方式传递或者当传输启动时数据尚未完全就绪,则应该考虑使用流模式,且只能对大型数据(带文本或2进制内容)启用流模式

当启用了流模式时,WCF的很多功能将不能用

    1.无法执行消息的数字签名,因为它们需要对整个消息内容进行哈希运算。采用流模式的时候,当构造和发送消息头时,内容尚未完全就绪,因此无法计算数字签名

    2.加密,加密依赖于数字签名来验证是否已正确的重新构造数据

由于上述功能约束,只能对流模式使用传输级安全选项,并且无法打开可靠会话。因此,流模式仅在下列系统定义的绑定中可用

    1.BasicHttpBinding

    2.NetTcpBinding

    3.NetNamePipeBinding

由于NetTcpBinding和NetNamePipeBinding的基础传输具有内在的可靠传递和基于连接的会话支持,因此与HTTP不同,这两个绑定在实践中受上述约束的影响非常小

流模式在消息队列(MSMQ)传输中不可用,因此不能与NetMsmqBinding和MsmqIntegrationBnding类一起使用。

当使用对等通道传输时,流模式也不可用,因此流模式在NetPeerTcpBinding中不可用

 

启用流模式

以流模式发送和接收请求,以缓冲模式接受和返回响应(StreamedRequest)

以缓冲模式发送和接受请求,以流模式接受和返回响应(StreamedResponse)

在两个方向都以流模式发送/接收请求/响应(Streamed)

通过将传输模式设置为Buffered来禁用流模式,该设置是所有绑定的默认值

 

流模式的编程模型

流式传输的编程模型非常简单。要接收流数据,就指定具有单个Stream类的输入参数。返回流数据,应返回一个Stream引用 如下图:

上面示例中Echo接收并返回一个流,因此应当用在具有Streamed的绑定上。对于操作RequestInfo,StreamedResponse最适合,因为它仅返回Stream。单向操作最适合StreamedRequest。

注意,如果为Echo或ProvideInfo这两个服务添加第二个参数,会导致服务模型回复为缓冲策略,并使用流的运行时序列化表示。只有具有单个输入流参数的操作才与端对端请求流兼容

类似的,这个规则也适用于消息协定。如下面的消息协定所示,在流模式的消息协定中,只能有一个正文成员。如果希望使用流传送更多信息,必须在消息头中携带这一信息。消息正文是专门为流内容保存的

 

 

 

posted @ 2013-03-01 13:41  韬韬韬你羞得无礼  Views(319)  Comments(0)    收藏  举报