分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 教程案例

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

发布时间:2023-09-06 01:25责任编辑:顾先生关键词:.NETjsjson

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

6、总结

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

   

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

原文地址:http://www.cnblogs.com/fanliang11/p/7858371.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved