Fork me on GitHub

WCF服务上应用protobuf

protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,其最大的特点是基于二进制,因此比传统的XML表示高效短小得多。虽然是二进制数据格式,但并没有因此变得复杂,开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。

protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。

更多信息可参考官方文档

protobuf这样的库是很方便高效的,那么自然的想到在网络编程中用来做业务消息的序列化、反序列化支持。在基于UDP协议的网络应用中,由于UDP本身是有边界,那么用protobuf来处理业务消息就很方便。但在TCP应用中,由于TCP协议没有消息边界,这就需要有一种机制来确定业务消息边界。在TCP网络编程中这是必须面对的问题。在tcp网络编程中,要反序列化业务消息,就要先知道业务数据的大小。而且在实际应用中可能在一个发送操作中,发送多个业务消息,而且每个业务消息的大小、类型都不一样。而且可能发送很大的数据流,比如文件。显然消息边界的确认问题和protobuf库无关,还得自己搞定。在官方文档中也提到,protobuf并不太适合来作大数据的处理,当业务消息超过1M时,就应该考虑是否应该用另外的替代方案。当然对于大数据,你也可以分割为多个小块用protobuf做小块消息封装进行传递。但对很多应用这样的作法显得比较多余,比如发送一个大的文件,一般是在接收方从协议栈收到多少数据就写多少数据到磁盘,这是一种边接收边处理的流模式,这种模式基本上和每次收到的数据量没有关系。这种模式下再采用分割成小消息进行反序列化就显得多此一举了。

借助于WCF这样的网络编程框架,然后结合protobuf这样的序列化框架,网络编程中技术基础设施层面的东西就给我们解决得差不多了,我们可以真正只关注于业务的实现。

protobuf的dotNet实现protobuf-net, 支持WCF的DataContact,WCF程序几乎不需要什么修改就能使用。

一个最小的可以工作的例子就是protobuf-net提供的(client, server),它使用的是共享契约的方式,通过WCF的配置方式,添加一个Endpoint-behavior,引用一个自定义的WCF扩展。

<behaviors>
      <endpointBehaviors>
        <behavior name="protoEndpointBehavior">
          <protobuf/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <extensions>
      <behaviorExtensions>
        <add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.280, Culture=neutral, PublicKeyToken=257b51d87d2e4d67"/>
      </behaviorExtensions>
    </extensions>
  </system.serviceModel>

在客户端和服务端都加上这个behavior,例如下面的例子

客户端:

    <client>
         <endpoint address="http://localhost:33545/Service1.svc" binding="wsHttpBinding"
             bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
             name="WSHttpBinding_IService1" behaviorConfiguration="protoEndpointBehavior">
             <identity>
                 <dns value="localhost" />
             </identity>
         </endpoint>
     </client>

服务端:

<endpoint address="" binding="wsHttpBinding" contract="TestWcfDto.IService1" behaviorConfiguration="protoEndpointBehavior">                     
   <identity>
      <dns value="localhost"/>
   </identity>
</endpoint>
</service>

注意事项:

1、类继承层次只支持1层

2、类似于WCF的KnownType,Protobuf使用ProtoInclude http://stackoverflow.com/questions/6541718/protobuf-net-wcf-multiple-nested-generic-abstract-objects-serialization-v282 

3、How to add dynamically a list of known type to a Protobuf-net formatter?

参考文章:

.net自带二进制序列化,XML序列化和ProtoBuf序列化的压缩对比

http://www.cnblogs.com/onlytiancai/archive/2009/07/02/protobuf_net_test.html

Windows Communication Protocols (MCPP) http://msdn.microsoft.com/en-us/library/cc216513(PROT.10).aspx

Silverlight Binary Serialization using Protobuf-net

http://www.codeproject.com/KB/silverlight/silverlight-protobufnet.aspx

http://marcgravell.blogspot.com/search/label/protobuf-net

http://blogs.msdn.com/b/dmetzgar/archive/2011/03/29/protocol-buffers-and-wcf.aspx

http://www.drdobbs.com/windows/working-with-protobuf-wcf-services/240159282?pgno=1

posted @ 2010-12-19 13:12  张善友  阅读(8710)  评论(6编辑  收藏