• WCF传输1-你是否使用过压缩或Json序列化?


    1.当遇到需要传输大量数据时,怎么样传输数据?

    2.压缩数据有哪几种常见的方式?

    问题1解答:通过压缩来传输数据

    问题2解答:

                (1)WCF自带的压缩方式

                (2)自定义WCF binding进行压缩

                (3)将对象序列化为JSON格式

    今天来探讨一下WCF自带的压缩方式Gzip和Json序列化

    我的其他WCF文章:

    WCF安全1-开篇

    WCF安全2-非对称加密

    WCF安全3-Transport与Message安全模式

    WCF传输1-你是否使用过压缩或Json序列化?

    先上图:

    1.WCF自带的压缩方式进行压缩数据及传输数据

    参考资料:https://msdn.microsoft.com/en-us/library/system.servicemodel.channels.compressionformat.aspx

    总共有三种方式:
         Deflate:The Deflate compression format.
         GZip:The GZip compression format.
         None: The none compression format.

    注意,.NET framwork版本需要在4.0以上(包含4.0)。

    1.1 Code的实现:

    (1)Server端和Client的配置

    <binarymessageencoding compressionformat="GZip">

        <bindings>
          <customBinding>
            <binding name="BindingForTcp" receiveTimeout="00:05:00" sendTimeout="00:05:00">
                <binaryMessageEncoding compressionFormat="GZip">
                  <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
                </binaryMessageEncoding>
                <httpTransport maxReceivedMessageSize="2147483647">
                  
                </httpTransport>
              </binding>
            </customBinding>
        </bindings>
    
    <services>
          <service name="Jackson0714.WcfServices.Service.GetPersonDetailService"
                   behaviorConfiguration="metadataBehavior" >
            <endpoint address="http://127.0.0.1:3725/GetPersonDetailService"
                      binding="customBinding" 
                      bindingConfiguration ="BindingForTcp"
                      contract="Jackson0714.WcfServices.Service.Interface.IGetPersonDetailService" />
          </service>
    </services>
    

    注意:Client和Server端必须使用相同的binding。 

    (2)Server端代码

    打开端口,host服务

    using System;
    using System.ServiceModel;
    using Jackson0714.WcfServices.Service;
    namespace Jackson0714.WcfServices.Hosting
    {
        class Program
        {
            static void Main(string[] args)
            {
                ServiceHost getPersonDetailServiceHost = null;
                try
                {
                    getPersonDetailServiceHost = new ServiceHost(typeof(GetPersonDetailService));
                    getPersonDetailServiceHost.Open();
                    Console.WriteLine("GetPersonDetailService Started!");
                    Console.ReadKey();
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.StackTrace);
                }
                finally
                {
                    getPersonDetailServiceHost.Close();
                }
            }
        }
    }

    (3)Client端代码

    调用方法GetPersonDetail

    using System;
    using System.ServiceModel;
    using Jackson0714.WcfServices.Service.Interface;
    namespace Jackson0714.WcfServices.Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (ChannelFactory<IGetPersonDetailService> channelFactory = new ChannelFactory<IGetPersonDetailService>("GetPersonDetailService"))
                {
                    IGetPersonDetailService proxy = channelFactory.CreateChannel();
                    Console.WriteLine("Person Decription:{0}", proxy.GetPersonDetail("123").Description);
                }
                Console.Read();
            }
        }
    }
    

    (4)接口

    GetPersonDetail
    using Jackson0714.WcfServices.Common;
    using System.ServiceModel;
    namespace Jackson0714.WcfServices.Service.Interface
    {
        [ServiceContract(Name = "GetPersonDetailService", Namespace = "http://www.Jackson0714.com/")]
        public interface IGetPersonDetailService
        {
            [OperationContract]
            Person GetPersonDetail(string name);
        }
    }
    

    (5)实现接口方法

    GetPersonDetail
    using Jackson0714.WcfServices.Common;
    using Jackson0714.WcfServices.Service.Interface;
    
    namespace Jackson0714.WcfServices.Service
    {
        public class GetPersonDetailService : IGetPersonDetailService
        {
            public Person GetPersonDetail(string name)
            {
                Person person = DataAccess.MockQueryPersonDetail(name);
                return person;
            }
        }
    }
    

    (6)Mock数据库访问层

    MockQueryPersonDetail

    模拟Person类的Description的数据量大小为100000字节

    using Jackson0714.WcfServices.Common;
    using System.Text;
    
    namespace Jackson0714.WcfServices.Service
    {
        class DataAccess
        {
            public static Person MockQueryPersonDetail(string name)
            { 
                Person person = new Person();
                person.Name = "Jackson0714";
                string testString = "0123456789";
                StringBuilder builder = new StringBuilder();
    
                for(long i = 0;i<10000;i++)
                {
                    builder.Append(testString);
                }
                person.Description = builder.ToString();
                return person;
            }
        }
    }
    

    (6)Person类

    Person
    namespace Jackson0714.WcfServices.Common
    {
        public class Person
        {
            private string name;
            public string Name
            {
                get
                {
                    return this.name;
                }
                set
                {
                    name = value;
                }
            }
            private string description;
            public string Description
            {
                get
                {
                    return this.description;
                }
                set
                {
                    description = value;
                }
            }
        }
    }

    1.2 分析结果

    通过WireShare抓包,可以得知Response的数据大小为Content-Length: 100352 bytes。

    经过压缩后,Response的数据大小为Content-Length: 506 bytes。,远小于未压缩的数据量。

    1.3 打印窗口

     

    2.使用JSON格式的数据进行传输

    Server端首先将数据序列化为Json格式的数据,String类型,Client端接收到Json格式的数据后,反序列化为Json格式的数据。

    需要引入Newtonsoft.Json.dll

    下载地址:http://www.newtonsoft.com/json

    2.1 Code的实现:

    (1)定义接口

    GetPersonDetailWithJson
    using Jackson0714.WcfServices.Common;
    using System.ServiceModel;
    namespace Jackson0714.WcfServices.Service.Interface
    {
        [ServiceContract(Name = "GetPersonDetailService", Namespace = "http://www.Jackson0714.com/")]
        public interface IGetPersonDetailService
        {
            [OperationContract]
            string GetPersonDetailWithJson(string name);
        }
    }
    

    (2)实现接口

    GetPersonDetailWithJson

    使用JsonConvert.SerializeObject(person)将person序列化为Json格式的数据。

    public string GetPersonDetailWithJson(string name)
    {
         Person person = DataAccess.MockQueryPersonDetail(name);
         return JsonConvert.SerializeObject(person);
    }
    

    (3)客户端调用GetPersonDetailWithJson

    使用JsonConvert.DeserializeObject<Person>(proxy.GetPersonDetailWithJson("123"))方法反序列化Json格式的数据,将Json格式的数据转换为Person对象。

    using (ChannelFactory<IGetPersonDetailService> channelFactory = new ChannelFactory<IGetPersonDetailService>("GetPersonDetailService"))
    {
          IGetPersonDetailService proxy = channelFactory.CreateChannel();
          Person person = JsonConvert.DeserializeObject<Person>(proxy.GetPersonDetailWithJson("123"));
    
          Console.WriteLine("GetPersonDetailWithJson->Person Decription:{0}", person.Description);
     }
    

    2.2 分析结果

    通过WireShare抓包,可以得知Response的数据大小为Content-Length: 100263bytes。比未经过序列化的数据减少了89 bytes的数据。

    这里有个问题,为什么Json格式的数据比原WCF基于XML传输的数据小???

    原因是WCF的传输的数据是将对象序列化为xml格式,需要用很多标签来记录各个字段的内容。而用JSON格式的数据,已经将对象转化为键值对形式的数据,不包含标签,所以数据量减少了。

    2.3 打印窗口

    3.通过Json+压缩的方式传输

    3.1 Code的实现

    (1) 定义WCF压缩方式

    <binaryMessageEncoding compressionFormat="GZip">

    (2) 将对象序列化为Json格式的数据

    JsonConvert.SerializeObject(person);
    

    (3) 将Json格式的数据反序列化为对象

    Person person = JsonConvert.DeserializeObject<Person>(proxy.GetPersonDetailWithJson("123"));

    3.2 分析结果

    从下图可以看出经过Json格式化然后压缩的数据为1004 bytes,未用Json格式化的数据为1071 bytes,减少了67个bytes。

     

    4.通过压缩或Json格式化需要注意什么?

    (1) 压缩或Json格式化需要消耗一定的资源,如果CPU和内存不足时,慎用压缩或Json格式化。

    (2) 压缩或Json格式化需要消耗一定的时间,如果数据量很大,那么压缩或Json格式化的时间也很大,对于需要快速响应的系统,慎用压缩或Json格式化。

    5.参考资料

    https://msdn.microsoft.com/en-us/library/system.servicemodel.channels.compressionformat.aspx

    https://msdn.microsoft.com/en-us/library/ms751458(v=vs.110).aspx

    我的其他WCF文章:

    WCF安全1-开篇

    WCF安全2-非对称加密

    WCF安全3-Transport与Message安全模式

    WCF传输1-你是否使用过压缩或Json序列化?


    作  者: Jackson0714
    出  处:http://www.cnblogs.com/jackson0714/
    关于作者:专注于微软平台的项目开发。如有问题或建议,请多多赐教!
    版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
    特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信
    声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是作者坚持原创和持续写作的最大动力!

  • 相关阅读:
    Solr4:加入中文分词IKAnalyzer2012 FF
    Solr4:Hello World级别示范
    Solr4:Tomcat7下面配置Solr
    Java:XML篇,使用DOM读取并解析XML
    Solr4:加入中文分词mmseg4j
    Java:XML篇,使用SAX读取并解析XML数据
    SSIS包如何动态指定文件路径
    如何定时执行SSIS包
    用户控件使用事件
    用户控件使用事件与调用页面交互
  • 原文地址:https://www.cnblogs.com/jackson0714/p/WCF_Transport1.html
Copyright © 2020-2023  润新知