基于.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

6、总结

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

时间: 2024-10-01 04:43:35

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

基于.NET CORE微服务框架 -谈谈surging的服务容错降级

一.前言 对于不久开源的surging受到不少.net同学的青睐,也受到.net core学习小组的关注,邀请加入.NET China Foundation以方便国内.net core开源项目的推广,我果断接受邀请加入了队伍进行互相交流学习,最近也更新了surging新的版本 更新内容: 1. Castle.Core 兼容性问题,下一版本会去除,解决部分用户第一次编译VS卡死问题2. 增加容错降级3. 路由容错重构,针对于失败重试和失败没有重试,失败回调,4.增加部分功能单元测试5. 升级支持.

基于.NET CORE微服务框架 -谈谈Cache中间件和缓存降级

1.前言 surging受到不少.net同学的青睐,也提了不少问题,提的最多的是什么时候集成API 网关,在这里回答大家最近已经开始着手研发,应该在1,2个月内会有个初版API网关,其它像Token身份验证,限流降级等功能完成时间会往后推 最近也更新了surging新的版本 更新内容: 1. Cache中间件基于Redis 所依赖的第三方库已将servicestack.redis转成stackexchange 2. 增加缓存降级3. 增加拦截缓存降级的例子 开源地址:https://github

基于.NET CORE微服务框架 -浅析如何使用surging

1.前言 surging受到大家这么强烈的关注,我感到非常意外,比如有同僚在公司的分享会上分享surging, 还有在博客拿其它的RPC框架,微服务做对比等等,这些举动都让我感觉压力很大,毕竟作为个人的开源项目,无法与成熟的开源社区的项目相比,也只有等到后面有许许多多志同道合的朋友加入一起研发完善surging,这样才能让surging 成为流行的微服务框架. 这篇文章介绍如何使用surging 开源地址:https://github.com/dotnetcore/surging 2.设计模式

基于.NET CORE微服务框架 -Api网关服务管理

1.前言 经过10多天的努力,surging 网关已经有了大致的雏形,后面还会持续更新完善,请大家持续关注研发的动态 最近也更新了surging新的版本 更新内容: 1. 扩展Zookeeper封装2. 增加服务元数据3. 增加API网关 开源地址:https://github.com/dotnetcore/surging 2.软件环境 IDE:Visual Studio 2017 15.3 Preview ,vscode 框架:.NET core 2.0 依赖程序:Zookeepe.Rabbi

基于.net core 微服务的另类实现

原文:基于.net core 微服务的另类实现 基于.net core 的微服务,网上很多介绍都是千篇一律基于类似webapi,通过http请求形式进行访问,但这并不符合大家使用习惯.如何像形如[ GetService<IOrderService>().SaveOrder(orderInfo)]的方式, 调用远程的服务,如果你正在为此苦恼, 本文或许是一种参考. 背景 原项目基于传统三层模式组织代码逻辑,随着时间的推移,项目内各模块逻辑互相交织,互相依赖,维护起来较为困难.为此我们需要引入一种

ASP.NET Core微服务框架Ocelot+Consul+IdentityServer4实战演练

一.背景介绍 API网关的流行源于最近几年移动应用与企业间接口对接的兴起,使得原来单一的PC客户端,变化到PC客户端.各种浏览器.手机移动端及智能终端等.同时系统之间大部分都不是单独运行,经常会涉及与其他系统对接.共享数据的需求.随着微服务架构概念的提出,API网关成为了微服务架构的一个标配组件.随着业务快速发展,面向手机移动应用业务越来越多,为了减少客户端与服务的耦合,节约后端微服务的开发成本,建立一个高性能.高可用.减少上线风险的API网关成为一个迫切的需求. 1).目前面临现状:假设你正好

基于Spring-Cloud的微服务框架设计

先进行大的整体的框架整理,然后在针对每一项进行具体的详细实现 原文地址:https://www.cnblogs.com/breka/p/9789995.html

几个基于jvm 的微服务框架

一个简单的整理,留待深入学习 micronaut http://micronaut.io/ sparkjava http://saprkjava.com spring cloud http://projects.spring.io/spring-cloud/ javalin https://javalin.io ktor.io http://ktor.io dropwizard https://dropwizard.io 原文地址:https://www.cnblogs.com/rongfeng

【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发

<ASP.NET Core 微服务实战>译者序:https://blog.jijiechen.com/post/aspnetcore-microservices-preface-by-translator/ "微服务"的概念在 2014 年正式提出之后,越来越多的团队开始用它来设计自己的业务系统,各种微服务框架和开发过程管理方法也同时兴起.不断成熟.微服务设计方法清晰地定义了各个开发团队的业务边界,微服务框架以不同的方式实现了服务之间的协作与集成,根据康威定律我们可以推导这