基于.NET CORE微服务框架 -谈谈surging 的messagepack、protobuffer、json.net 序列化

1、前言

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

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

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

2、序列化组件

   2.1 surging 使用的是如下序列化组件:网络

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

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

      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

网络:局域网

六、总结

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

相关文章
相关标签/搜索