《WCF技术内幕》翻译9:第1部分_第2章_面向服务:消息编码

Posted on 2009-11-06 18:41 Frank Xu Lei 阅读(292) 评论(3)   编辑 收藏 网摘 所属分类: 《WCF技术内幕》翻译, SOA and EAI

消息编码

  随着时间的流逝,也许我们会条件反射式地认为XMLSOAP)是一个结构文本。毕竟,文本是人可读的,每个计算机系统也可以处理文本。基于文本的XML的普遍共性与我们的与其它系统交互的想法产生了共鸣。可以容易的解释的基于文本的XML本质上会体积变大。可以理解使用XML会带来性能损失。就像要花费点精力把信装到信封里一样,它需要一些处理时间与XML交互。某些情况下,基于文本的XML数据大小限制了它的应用,特别是当我们要通过网络发送一个XML消息的时候。

  此外,如果我们限制自己使用基于文本的XML,那么我们怎么才能在XML文档里发送二进制数据(像音乐或者视频)?如果你已经阅读了标准的XMLSchema数据类型,你会发现2个二进制数据类型:: xs:base64Binary xs:hexBinary本质上说,两个数据类型都代表一组有序的8位字节。使用这些XML数据类型或许可以解决一些嵌入二进制数据到文档中的问题,但是事实上,这已经使得性能问题更加糟糕。众所周知的问题就是,base64编码会增加数据30%的大小。这个情况对于xs:hexBinary更坏,因为它会增加位原来的2倍大小。两个数据都是基于UTF-8编码的假设。如果我们采用UTF-16编码,这些倍数因子都会翻倍增加。

XML 信息集( XML Infoset

  为了找到性能的瓶颈的答案,我们详细来看一下XML文档的结构。如果我们看一下规范,XML是一个精确的撰写结构化数据的语法(定义在 http://www.w3.org/TR/REC-xml/)。它要求定义格式良好的XML文档必须包涵一个开始和结束元素、一个根节点等等。奇怪的是,XML规范发布以后,激起了抽象定义XML文档的需求。XML信息集(定义在http://www.w3.org/TR/xml-infoset/)提供了这个抽象定义。

  实际上,XML信息集定义是项目之间的关系,不定义任何具体的语法,我们能够解释许多不同的消息编码,包括一些比文本更高校的编码格式,而不需要修改我们的程序。

SOAPXML信息集

  记得SOAP是建立在XML之上的。这个产生一个问题:到底SOAP消息是建立在早期的XML语法上还是XML信息集上呢?答案是2者都有。2SOAP规范并存:SOAP 1.1 SOAP 1.2SOAP1.1建立在旧的XML语法上,SOAP1.2建立在XML 信息集上。有这么一个事实,就可以猜想SOAP1.2建立的消息SOAP1.1的解析器可能无法阅读。WCF是建立在SOAP1.2XML信息集上),但是它可以同时处理SOAP 1.1 SOAP 1.2的消息。

   WCF可以用来和定制与其它实际的消息编码一起工作,只要消息是遵照SOAP1.1或者SOAP1.2的(它可以和不是SOAP消息一起工作)。如你将会在接下来的章节里看到的一样,WCF是一个可灵活接入和组合的架构。所以自定义编码器可以轻易地安装到WCF的管道上。当一个新的编码器开发完毕,微软或者第三方都可以在消息堆栈里创建和插入它。我将会在第6章:《通道》里详细介绍消息编码器。现在我们来看一下WCF里的编码器。在写本书的时候,WCF提供了三个编码器:文本(text)、(二进制)binary 消息传输优化机制(Message Transmission Optimization Mechanism MTOM)

文本编码器

  和你从它的名字里猜到的一样,文本编辑器的输出结果是基于文本编码的消息。每个明白Unicode文本的系统都可以阅读和处理这个编码器传递来的消息,在与别的非WCF系统互操作时,这个是一个很帮的选择。二进制数据通过xs:base64Binary扩展样式定义(XSD数据类型可以包涵到基于文本的消息里。这是一个使用WCF文本编码器编码过的消息(为了清晰,移除了一部分元素)。

< s:Envelope  xmlns:s ="http://www.w3.org/2003/05/soap-envelope" >

    
< s:Header > </ s:Header >

    
< s:Body >

      
< SubmitOrder  xmlns ="http://wintellect.com/OrderProcess" >

        
< Order  xmlns:i ="http://www.w3.org/2001/XMLSchema-instance" >

        
< OrderByte  xmlns ="http://wintellect.com/Order" >

mktjxwyxKr/9oW/jO48IhUwrZvNOdyuuquZEAIcy08aa+HXkT3dNmvE/

+zI96Q91a9Zb17HtrCIgtBwmbSk4ys2pSEMaIzXV3cwCD3z4ccDWzpWx1/

wUrEtSxJtaJi3HBzBlk6DMW0eghvnl652lKEJcUJ6Uh/LRlZz3x1+aereeOgdLkt4gCnNOEFECL8CtrJtY/taPM4A+k/

4E1JPnBgtCRrGWWpVkO0UqRXahz2XbShrDQnzgDwaHDf/

fHDXfZgpFwOgPF1IG88KQZO0JncSYKIp5I8OPYTeqD0yVhB8QSt9sWw59yzLHvU65UKoYfXA7RvOqZkJGtV6wZAgGcA=

=

          
</ OrderByte >

        
< OrderNumber  xmlns ="http://wintellect.com/Order" >

            12345

          
</ OrderNumber >

        
</ Order >

      
</ SubmitOrder >

    
</ s:Body >

 
</ s:Envelope >

二进制编码器

  二进制编码器是最高效的消息编码器,并且只适用与WCF--WCF的通信。在WCF所有的编码器中,二进制编码器产生最小的消息。记住这个编码器产生一个序列化的信息集,即使它是二进制编码格式。将来可能,一个标准的二进制编码会被采用,这些编码的类型可以显著第改善消息应用的性能。

MTOM编码器

  MTOM编码器根据MTOM规范创建消息。(MTOM规范可以在这里查到http://www.w3.org/TR/soap12-mtom/)因为MTOM编码已经规范化,所以其它厂商可以自由创建发送和接受消息的基础结构。结果,MTOM消息编码的WCF消息就可以发送给非WCF的应用(只要它们理解MTOM)。通常来说,MTOM为了允许高效第传输包涵二进制数据的消息,它也提供了数字签名。MTOM消息编码可以通过多用途网络邮件扩展协议(MIME)启用这些特性。MTOM消息的内容被XML-二进制优化包装方法所定义。更多信息:http://www.w3.org/TR/xop10/.

  在运行时,MTOM编码器为了数字签名创建一个基于base64编码的代表,让原始二进制数据可以在消息里打包。一个MTOM消息看起来如下:

// start of a boundary in the multipart message多部分消息的分界线

--uuid:+id=1

Content-ID: 
< http: //wintellect.com/0 >

Content-Transfer-Encoding: 8bit

// set the content type to xop+xml,设置内容类型xop+xml

Content-Type: application/xop+xml;charset=utf8; type="application/soap+xml"

< s:Envelope  xmlns:s ="http://www.w3.org/2003/05/soap-envelope" >

 
< s:Header > </ s:Header >

 
< s:Body >

    
< SubmitOrder  xmlns ="http://wintellect.com/OrderProcess" >

      
< order  xmlns:i ="http://www.w3.org/2001/XMLSchema-instance" >

        
< OrderByte  xmlns ="http://wintellect.com/Order" >

           // add a reference to another message part

          
< xop:Include  href =cid:http://wintellect.com/1/12345

           
xmlns:xop ="http://www.w3.org/2004/08/xop/include" />

        
</ OrderByte >

        
< OrderNumber  xmlns ="http://wintellect.com/Order" >

          12345

       
</ OrderNumber >

      
</ order >

    
</ SubmitOrder >

 
</ s:Body >

</ s:Envelope >

// end of the boundary in the first message part第一部分的内容结束边界

--uuid:+id=1

// add the binary data as an octect stream增加二进制数据为八位字节流

Content-ID: 
< http: //wintellect.com/1/12345 >

Content-Transfer-Encoding: binary

Content-Type: application/octet-stream

// raw binary data here这里是原始二进制数据

  注意到二进制数据被原样保坤在SOAP消息里的另一块区域里。因为二进制数据被打包到SOAP消息的外部区域,那么这么才能给SOAP进行数字签名呢?如果我们使用基于XML的安全机制,像XML加密和XML数字签名里描述的一样,我们不能引用外部的二进制流。这些加密个签名机制要求被保护的数据包装在SOAP消息里。咋一看,对于多部分的消息还真没有什么办法。事实上,这是直接网络消息封装(DIME)和SOAP附件的致命弱点。MTOM提供了一个有趣的解决办法。

   MTOM 编码规范规定一个 MTOM 消息能够包涵二进制数据在 base64 编码的字符里,后者二进制流在额外的消息部分里。它也表示一个基于 base64 编码的二进制数据的代表在处理的时候必须可用。换句话说,额外的消息部分可以为消息传输创建,但是内联的 base64 数据必须对一些操作如:应用数字签名临时可用。当消息处于内联的基于 base64 编码的状态,基于 XML 编码的安全机制可以被应用到 SOAP 消息里。安全机制应用结束,消息可以被序列化为多部分消息。当接受者接受消息的时候,这个消息可以被 XML 安全规范机制强制根据一些列规则进行验证。

  非常有意思地看到,当大量二进制消息是基于base64编码或者二进制流编码在额外的消息部分的时候,WCF MTOM编码器能够正确地选择序列化。WCF编码器使用二进制数据大小作为选择的依据。在之前的消息里,OrderBytes元素大约800k。如果我们减少OrderBytes的大小到128k,在检查一下消息格式,我们可以看到:

// start of a boundary in the multipart message,多部分消息开始边界

--uuid:+id=1

Content-ID: 
< http: //wintellect.com/0 >

Content-Transfer-Encoding: 8bit

// set the content type to xop+xml

Content-Type: application/xop+xml;charset=utf8; type="application/soap+xml"

< s:Envelope  xmlns:s ="http://www.w3.org/2003/05/soap-envelope" >

 
< s:Header > </ s:Header >

 
< s:Body >

    
< SubmitOrder  xmlns ="http://wintellect.com/OrderProcess" >

      
< order  xmlns:i ="http://www.w3.org/2001/XMLSchema-instance" >

        
< OrderByte  xmlns ="http://wintellect.com/Order" >

kF+k2CQd/lCitSYvXnLhuOtaMCk/tZaFZIWeW7keC3YvgstAWoht/wiOiR5+HZPo+TzYoH+qE9vJHnSefqKXg6mw/

9ymoV1i7TEhsCt3BkfytmF9Rmv3hW7wdjsUzoBl9gZ1zR62QVjedbJNiWKvUhgtq8hAGjw+uXlttSohTh6xu7kkAjgoO

3QJntG4qfwMQCQj5iO4JdzJNhSkSYwtvCaTnM2oi0/fBHBUN3trhRB9YXQG/mj7+ZbdWsskg/

Lo2+GrJAwuY7XUROKyY+5hXrAEJ+cXJr6+mKM3yzCDu4B9bFuZv2ADTv6/MbmFSJWnfPwbH1wK0LQi7Ixo95iF

        
</ OrderByte >

        
< OrderNumber  xmlns ="http://wintellect.com/Order" >

          12345

        
</ OrderNumber >

      
</ order >

    
</ SubmitOrder >

 
</ s:Body >

</ s:Envelope >

--uuid:+id=1-

  这个例子里,WCF编码器序列化二进制元素为基于base64编码的string。这个优化是相当符合MTOM规范。

选择恰当的编码

  选择消息编码器强迫你去考虑当前和未来的消息使用问题。大部分来说,应用互操作性和消息里的数据类型会决定我们的选择。性能,在决定那个编码器是最适合我们系统的时候,也会考虑进来。表2-1基于消息类型和那种系统可以可以发送和接受消息列举了编码情况。

2-1:消息编码器排列和场景

消息类型

Binary

Text

MTOM

Text内容, 只与WCF 交互

1

2

3

Text内容, 与现代非WCF系统交互

N/A

1

2

Text内容, 与旧的非WCF systems 交互

N/A

1

N/A

大二进制内容, 只与WCF 交互

1

3

2

大二进制内容, 与现代非WCF系统交互

N/A

2

1

大二进制内容, , 与旧的非WCF systems 交互

N/A

1

N/A

小二进制内容, 只与WCF 交互

1

2

3

小二进制内容, 与现代非WCF系统交互

N/A

1

2

小二进制内容, , 与旧的非WCF systems 交互

N/A

1

N/A

   不应该惊讶,二进制编码器是 WCF 与其它 WCF 系统交互最高效的编码器。我们也许吃惊的是这个事实,在端到端的情况下, MTOM 消息编码是比文本编码器效率还低。互操作性和二进制数据大小是你选择 MTOM 和文本编码器的因素。绝大多数情况, MTOM 编码消息只能发送给 MTOM 编码器的系统。写本书的时候, MTOM 是一个很新的规范,所以只有现代系统可以高效地处理 MTOM 消息。从性能的角度来看, MTOM 编码器只有当包装到消息里的二进制数据很大的时候才有意义。 MTOM 不应该用在不包括二进制数据的消息里,因为 MTOM 的性能此时比文本编码器效率更低。因此,独立测试一个在产品环境里使用的消息非常重要。

  幸运的是,我们可以在第4章:WCF 101里看到,WCF就是这些编码选择都不需要大的改变应用程序的方式来设计的。事实上,这使得一个服务可以与多种不同的消息编码交互成为可能。举例来说,一个服务可以与两个二进制编码和文本编码的消息交互。这个场景的好处在于当与别的WCF参与者通信的时候,服务可以快速执行,并且可以与别的平台通信,比如JAVA


老徐的博客
【作      者】:Frank Xu Lei
【地      址】:http://www.cnblogs.com/frank_xl/
【中文论坛】:微软WCF中文技术论坛
【英文论坛】:微软WCF英文技术论坛

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值