zoukankan      html  css  js  c++  java
  • 基于.NET CORE微服务框架 -谈谈surging 的messagepack、protobuffer、json.net 序列化

    1、前言

         surging内部使用的是高性能RPC远程服务调用,如果用json.net序列化肯定性能上达不到最优,所以后面扩展了protobuf,messagepack序列化组件,以支持RPC二进制传输.

         在这里需要感谢白纸无字Zonciu,新增了messagepack序列化,让surging 性能上跨了一大步。此篇文章我们来谈谈messagepack、protobuffer、json.net ,并且性能做下对比

        开源地址:https://github.com/dotnetcore/surging

    2、序列化组件

       2.1 surging 使用的是以下序列化组件:

          json.net:surging 使用的是Newtonsoft.Json, 它是基于json格式的序列化和反序列化的组件.官方网站: http://json.codeplex.com/

          protobuf:surging 使用的是protobuf-net, 它是基于二进制格式的序列化和反序列化的组件.官方网站: https://github.com/mgravell/protobuf-net

          messagepack:surging 使用的是MessagePack-CSharp, 它是基于二进制格式的序列化和反序列化的组件.官方网站: https://github.com/neuecc/MessagePack-CSharp

          2.2 各个组件的优点

           json.net 有以下优点:

           侵入性:可以不添加attribute,就能进行序列化操作

           灵活性:可以灵活性配置,比如允许被序列化的成员自定义名字,屏蔽的非序列化属性成员

           可读性: 数据格式比较简单, 易于读写

           依赖性:可以序列化成JObject,无需依赖对象进行序列化和泛型化。

      protobuf 有以下优点:

          性能高  序列化后体积相比Json和XML很小,适合RPC二进制传输
       跨语言:支持跨平台多语言
            兼容性:消息格式升级和兼容性还不错
            速度快 :序列化反序列化速度很快,快于Json的处理速速

         messagepack有以下优点:

          性能高  序列化后体积相比Json和XML很小,适合RPC二进制传输
       跨语言:支持跨平台多语言
            兼容性:消息格式升级和兼容性还不错
            速度快 :序列化反序列化速度很快,快于Json的处理速度

     针对于protobuf和messagepack都是基于二进制格式的序列化和反序列化,优点都一样,但是基于messagepack的MessagePack-CSharp组件侵入性更小,可以不需要加attribute,而且性能上更优.下一节来看看组件在surging 中的表现

    3. 性能比较

    服务端:

    (注:如果不加UseProtoBufferCodec和UseMessagePackCodec就是json.net序列化)

    var host = new ServiceHostBuilder()
                   .RegisterServices(option=> {
                       option.Initialize(); //初始化服务
                       option.RegisterServices();//依赖注入领域服务
                       option.RegisterRepositories();//依赖注入仓储
                       option.RegisterModules();//依赖注入第三方模块
                       option.RegisterServiceBus();//依赖注入ServiceBus
                   })
                   .RegisterServices(builder =>
                   {
                       builder.AddMicroService(option =>
                       {
                           option.AddServiceRuntime();//
                           // option.UseZooKeeperManager(new ConfigInfo("127.0.0.1:2181")); //使用Zookeeper管理
                           option.UseConsulManager(new ConfigInfo("127.0.0.1:8500"));//使用Consul管理
                           option.UseDotNettyTransport();//使用Netty传输
                           option.UseRabbitMQTransport();//使用rabbitmq 传输
                           option.AddRabbitMQAdapt();//基于rabbitmq的消费的服务适配
                         //  option.UseProtoBufferCodec();//基于protobuf序列化传输
                           option.UseMessagePackCodec();//基于MessagePack序列化传输
                           builder.Register(p => new CPlatformContainer(ServiceLocator.Current));//初始化注入容器
                       });
                   })
                   .SubscribeAt()     //消息订阅
                   .UseServer("127.0.0.1", 98)
                 //.UseServer("127.0.0.1", 98,“true”) //自动生成Token
                 //.UseServer("127.0.0.1", 98,“123456789”) //固定密码Token
                   .UseStartup<Startup>()
                   .Build();
                   
               using (host.Run())
               {
                   Console.WriteLine($"服务端启动成功,{DateTime.Now}。");
               }
    

    客户端:

       var host = new ServiceHostBuilder()
                    .RegisterServices(option =>
                    {
                        option.Initialize();
                        option.RegisterServices();
                        option.RegisterRepositories();
                        option.RegisterModules();
                    })
                    .RegisterServices(builder =>
                    {
                        builder.AddMicroService(option =>
                        {
                            option.AddClient();
                            option.AddClientIntercepted(typeof(CacheProviderInterceptor));
                            //option.UseZooKeeperManager(new ConfigInfo("127.0.0.1:2181"));
                            option.UseConsulManager(new ConfigInfo("127.0.0.1:8500"));
                            option.UseDotNettyTransport();
                            option.UseRabbitMQTransport();
                             option.UseProtoBufferCodec();
                            //option.UseMessagePackCodec();
                            builder.Register(p => new CPlatformContainer(ServiceLocator.Current));
                        });
                    })
                    .UseClient()
                    .UseStartup<Startup>()
                    .Build();
    
                using (host.Run())
                {
                    Startup.Test(ServiceLocator.GetService<IServiceProxyFactory>());
                    Startup.TestRabbitMq();
                }

    测试  0  object(注:测试无参数)

      /// <summary>
            /// 测试
            /// </summary>
            /// <param name="serviceProxyFactory"></param>
            public static void Test(IServiceProxyFactory serviceProxyFactory)
            {
                Task.Run(async () =>
                {
                    var userProxy = serviceProxyFactory.CreateProxy<IUserService>("User");
                    await userProxy.GetUserId("user"); 
                    do
                    {
                        Console.WriteLine("正在循环 1w次调用 GetUser.....");
                        //1w次调用
                        var watch = Stopwatch.StartNew();
                        for (var i = 0; i < 10000; i++)
                        {
                           var a =userProxy.GetDictionary().Result;
                        }
                        watch.Stop();
                        Console.WriteLine($"1w次调用结束,执行时间:{watch.ElapsedMilliseconds}ms");
                        Console.ReadLine();
                    } while (true);
                }).Wait();
            }
    

    测试  1  object(注:测试参数传对象)

        /// <summary>
            /// 测试
            /// </summary>
            /// <param name="serviceProxyFactory"></param>
            public static void Test(IServiceProxyFactory serviceProxyFactory)
            {
                Task.Run(async () =>
                {
    
                    var userProxy = serviceProxyFactory.CreateProxy<IUserService>("User");
                    await userProxy.GetUserId("user"); 
                    do
                    {
                        Console.WriteLine("正在循环 1w次调用 GetUser.....");
                        //1w次调用
                        var watch = Stopwatch.StartNew();
                        for (var i = 0; i < 10000; i++)
                        {
                           var a =userProxy.GetUser(new UserModel { UserId = 1 }).Result;
                        }
                        watch.Stop();
                        Console.WriteLine($"1w次调用结束,执行时间:{watch.ElapsedMilliseconds}ms");
                        Console.ReadLine();
                    } while (true);
                }).Wait();
    }
    

     测试  10  object(注:测试参数传List 集合对象)

       /// <summary>
            /// 测试
            /// </summary>
            /// <param name="serviceProxyFactory"></param>
            public static void Test(IServiceProxyFactory serviceProxyFactory)
            {
                Task.Run(async () =>
                {
                    var userProxy = serviceProxyFactory.CreateProxy<IUserService>("User");
                    await userProxy.GetUserId("user");
                    var list = new List<UserModel>();
                    for(int i=0;i<10;i++)
                    {
                        list.Add(new UserModel { UserId = 1, Age = 18, Name = "fanly" });
                    }
                    do
                    {
                        Console.WriteLine("正在循环 1w次调用 GetUser.....");
                        //1w次调用
                        var watch = Stopwatch.StartNew();
                        for (var i = 0; i < 10000; i++)
                        {
                           var a =userProxy.Get(list).Result;
                        }
                        watch.Stop();
                        Console.WriteLine($"1w次调用结束,执行时间:{watch.ElapsedMilliseconds}ms");
                        Console.ReadLine();
                    } while (true);
                }).Wait();
            }
    

    测试100 object(注:测试参数传List 集合对象)

        /// <summary>
            /// 测试
            /// </summary>
            /// <param name="serviceProxyFactory"></param>
            public static void Test(IServiceProxyFactory serviceProxyFactory)
            {
                Task.Run(async () =>
                {
                    var userProxy = serviceProxyFactory.CreateProxy<IUserService>("User");
                    await userProxy.GetUserId("user");
                    var list = new List<UserModel>();
                    for(int i=0;i<100;i++)
                    {
                        list.Add(new UserModel { UserId = 1, Age = 18, Name = "fanly" });
                    }
                    do
                    {
                        Console.WriteLine("正在循环 1w次调用 GetUser.....");
                        //1w次调用
                        var watch = Stopwatch.StartNew();
                        for (var i = 0; i < 10000; i++)
                        {
                           var a =userProxy.Get(list).Result;
                        }
                        watch.Stop();
                        Console.WriteLine($"1w次调用结束,执行时间:{watch.ElapsedMilliseconds}ms");
                        Console.ReadLine();
                    } while (true);
                }).Wait();
            }

    通过以上测试代码,我们得到了如下的测试结果

          通过上图,可以发现messagepack不管是小数据量还是大数据量都保持比较稳定的性能,而json.net 在100object平均已经达到了1.1ms,和messagepack、protobuffer比差太多,而 protobuffer在此次测试中表现的极其不稳定只有在1 object 和100 object 性能比较不错,但是与messagepack比还是相差比较大。所以我建议还是使用messagepack,性能上更优,侵入性也非常低

    我们来看看性能最优的messagepack 详细测试数据

    o object:

    1 object:

     10 object:

    100 object

    测试环境

    CPU:Intel Core i7-4710MQ

    内存:16G

    硬盘:1T SSD+512G HDD

    网络:局域网

    6、总结

    surging 已经完成JWT验证和AppSecret验证,下篇文章会详细介绍surging 身份认证,如感兴趣请多关注或者加入QQ群:615562965

       

  • 相关阅读:
    仿新浪首页、主题、详情页,纯html静态页面
    hdoj 4790 Just Random 【数学】
    Codeforces 97B Superset 平面分治
    HDU 1017 A Mathematical Curiosity【看懂题意+穷举法】
    Codeforces Round #221 (Div. 2) D
    一个bug在redmine中的诞生到终结
    hi3531 SDK已编译文件系统制作jffs2文件系统镜像并解决这个问题 .
    js前端3des加密 后台java解密
    进程经常使用小知识汇总
    泛型集合的使用
  • 原文地址:https://www.cnblogs.com/fanliang11/p/7858371.html
Copyright © 2011-2022 走看看