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=;i<;i++)
{
list.Add(new UserModel { UserId = , Age = , Name = "fanly" });
}
do
{
Console.WriteLine("正在循环 1w次调用 GetUser.....");
//1w次调用
var watch = Stopwatch.StartNew();
for (var i = ; i < ; 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

基于.NET CORE微服务框架 -surging 基于messagepack、protobuffer、json.net 性能对比的更多相关文章

  1. 基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)

    一.前言 至今为止编程开发已经11个年头,从 VB6.0,ASP时代到ASP.NET再到MVC, 从中见证了.NET技术发展,从无畏无知的懵懂少年,到现在的中年大叔,从中的酸甜苦辣也只有本人自知.随着 ...

  2. 基于.NET CORE微服务框架 -谈谈surging API网关

    1.前言 对于最近surging更新的API 网关大家也有所关注,也收到了不少反馈提出是否能介绍下Api网关,那么我们将在此篇文章中剥析下surging的Api 网关 开源地址:https://git ...

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

    1.前言 surging受到大家这么强烈的关注,我感到非常意外,比如有同僚在公司的分享会上分享surging, 还有在博客拿其它的RPC框架,微服务做对比等等,这些举动都让我感觉压力很大,毕竟作为个人 ...

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

    一.前言 对于不久开源的surging受到不少.net同学的青睐,也受到.net core学习小组的关注,邀请加入.NET China Foundation以方便国内.net core开源项目的推广, ...

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

    1.前言 surging受到不少.net同学的青睐,也提了不少问题,提的最多的是什么时候集成API 网关,在这里回答大家最近已经开始着手研发,应该在1,2个月内会有个初版API网关,其它像Token身 ...

  6. .net Core 微服务框架 surging 使用

    surging 是一个分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper.Consul作为surging服务的注册中心, 集成了哈希,随机,轮询作为负载均衡的算法,RPC集成采用的 ...

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

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

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

    1.前言 经过10多天的努力,surging 网关已经有了大致的雏形,后面还会持续更新完善,请大家持续关注研发的动态 最近也更新了surging新的版本 更新内容: 1. 扩展Zookeeper封装2 ...

  9. 基于thrift的微服务框架

    前一阵开源过一个基于spring-boot的rest微服务框架,今天再来一篇基于thrift的微服务加框,thrift是啥就不多了,大家自行百度或参考我之前介绍thrift的文章, thrift不仅支 ...

随机推荐

  1. Python自学笔记-面向对象编程(Mr seven)

    类的成员可以分为三大类:字段.方法和属性. 一.字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, 普通字段属于对象 静态字段属于类 二.方法 方法 ...

  2. 小程序解释HTML富文本的两种办法

    今天写着着代码,读取数据库的内容时突然跳出"<span>.<p>. "这些HTML标签.字符,吓一跳:本来如果是写HTML.JS倒也没什么,但是我在写小程序 ...

  3. 平板不能设置代理的情况下利用随身wifi进行http代理访问

    需求来源:平板或手机是个封闭系统无法给wifi设置代理,需要利用filllder进行抓包,内容篡改等实验 拥有硬件资源:PC机器 + 小米随身wifi 方案1: NtBind Dns + Nginx ...

  4. Swift 算法实战之路:栈和队列

    这期的内容有点剑走偏锋,我们来讨论一下栈和队列.Swift语言中没有内设的栈和队列,很多扩展库中使用Generic Type来实现栈或是队列.笔者觉得最实用的实现方法是使用数组,本期主要内容有: 栈和 ...

  5. hadoop之 hadoop 2.2.X 弃用的配置属性名称及其替换名称对照表

    Deprecated Properties  弃用属性 The following table lists the configuration property names that are depr ...

  6. WordCount项目

    采用的源码来自http://blog.csdn.net/lnz001/article/details/54851551 经修改后,已上传至GitHub.https://github.com/FengX ...

  7. Linux.杀毒.Centos安装杀毒软件Clam

    Linux系统用了几年, 甚少中毒 但前不久在阿里云的服务器被种马,折腾了几周才解决干净 感觉还是装个杀毒/马软件定期扫一扫比较稳妥, 这个Clam是免费的, 安装和配置办法记录如下: 已验证适用环境 ...

  8. 【工具】Spring项目转化Spring Web项目插件

    前言 源于前一篇博文中提到,将Spring项目转化为Spring Web项目,发现添加项目文件和修改pom.xml文件等都是手动完成的,心想着开发一个Idea插件来自动化完成上面的过程,实现一键转化. ...

  9. url编码&&PHP大法

    URL编码 Url编码通常也被称为百分号编码(Url Encoding,also known as percent-encoding),是因为它的编码方式非常简单,使用%百分号加上两位的字符--012 ...

  10. 使用fabric解决百度BMR的spark集群各节点的部署问题

    前言 和小伙伴的一起参加的人工智能比赛进入了决赛之后的一段时间里面,一直在构思将数据预处理过程和深度学习这个阶段合并起来.然而在合并这两部分代码的时候,遇到了一些问题,为此还特意写了脚本文件进行处理. ...