分布式RPC框架性能大比拼

标签: 大并发编程 | 发表时间:2016-09-05 13:18 | 作者:
出处:http://colobu.com/

Dubbo 是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。不过,略有遗憾的是,据说在淘宝内部,dubbo由于跟淘宝另一个类似的框架HSF(非开源)有竞争关系,导致dubbo团队已经解散(参见 http://www.oschina.net/news/55059/druid-1-0-9 中的评论),反到是当当网的扩展版本仍在持续发展,墙内开花墙外香。其它的一些知名电商如当当、京东、国美维护了自己的分支或者在dubbo的基础开发,但是官方的库缺乏维护,相关的依赖类比如Spring,Netty还是很老的版本(Spring 3.2.16.RELEASE, netty 3.2.5.Final),倒是有些网友写了升级Spring和Netty的插件。

Montan是新浪微博开源的一个Java 框架。它诞生的比较晚,起于2013年,2016年5月开源。Motan 在微博平台中已经广泛应用,每天为数百个服务完成近千亿次的调用。

rpcx是Go语言生态圈的Dubbo, 比Dubbo更轻量,实现了Dubbo的许多特性,借助于Go语言优秀的并发特性和简洁语法,可以使用较少的代码实现分布式的RPC服务。

gRPC是Google开发的高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。本身它不是分布式的,所以要实现上面的框架的功能需要进一步的开发。

以下是它们的功能比较:

Dubbo Montan rpcx gRPC
开发语言 Java Java Go 跨语言
分布式 ×
多序列化框架支持
 

(当前支持Hessian2、Json,可扩展)

 
×
(只支持protobuf)
多种注册中心 ×
管理中心 × ×
跨编程语言 × × (支持php client和C server) ×

对于RPC的考察, 性能是很重要的一点,因为RPC框架经常用在服务的大并发调用的环境中,性能的好坏决定服务的质量以及公司在硬件部署上的花费。

本文通过一个统一的服务,测试这四种框架实现的完整的服务器端和客户端的性能。
这个服务传递的消息体有一个protobuf文件定义:

     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
     
syntax = "proto2";
package main;
option optimize_for = SPEED;
message BenchmarkMessage {
required string field1 = 1;
optional string field9 = 9;
optional string field18 = 18;
optional bool field80 = 80 [default=false];
optional bool field81 = 81 [default=true];
required int32 field2 = 2;
required int32 field3 = 3;
optional int32 field280 = 280;
optional int32 field6 = 6 [default=0];
optional int64 field22 = 22;
optional string field4 = 4;
repeated fixed64 field5 = 5;
optional bool field59 = 59 [default=false];
optional string field7 = 7;
optional int32 field16 = 16;
optional int32 field130 = 130 [default=0];
optional bool field12 = 12 [default=true];
optional bool field17 = 17 [default=true];
optional bool field13 = 13 [default=true];
optional bool field14 = 14 [default=true];
optional int32 field104 = 104 [default=0];
optional int32 field100 = 100 [default=0];
optional int32 field101 = 101 [default=0];
optional string field102 = 102;
optional string field103 = 103;
optional int32 field29 = 29 [default=0];
optional bool field30 = 30 [default=false];
optional int32 field60 = 60 [default=-1];
optional int32 field271 = 271 [default=-1];
optional int32 field272 = 272 [default=-1];
optional int32 field150 = 150;
optional int32 field23 = 23 [default=0];
optional bool field24 = 24 [default=false];
optional int32 field25 = 25 [default=0];
optional bool field78 = 78;
optional int32 field67 = 67 [default=0];
optional int32 field68 = 68;
optional int32 field128 = 128 [default=0];
optional string field129 = 129 [default="xxxxxxxxxxxxxxxxxxxxx"];
optional int32 field131 = 131 [default=0];
}

事实上这个文件摘自gRPC项目的测试用例,使用反射为每个字段赋值,使用protobuf序列化后的大小为 581 个字节左右。因为Dubbo和Motan缺省不支持Protobuf,所以序列化和反序列化是在代码中手工实现的。

服务很简单:

     
1
2
3
4
     
service Hello {
// Sends a greeting
rpc Say (BenchmarkMessage) returns (BenchmarkMessage) {}
}

接收一个BenchmarkMessage,更改它前两个字段的值为"OK" 和 100,这样客户端得到服务的结果后能够根据结果判断服务是否正常的执行。
Dubbo的测试代码改自 dubo-demo,
Motan的测试代码改自 motan-demo
rpcx和gRPC的测试代码在 rpcx benchmark

正如左耳朵耗子对Dubbo批评一样,Dubbo官方的测试不正规 ( 性能测试应该怎么做?)。
本文测试将用吞吐率、相应时间平均值、响应时间中位数、响应时间最大值进行比较(响应时间最小值都为0,不必比较),当然最好以Top Percentile的指标进行比较,但是我没有找到Go语言的很好的统计这个库,所以暂时比较中位数。
另外测试中服务的成功率都是100%。

测试是在两台机器上执行的,一台机器做服务器,一台机器做客户端。

两台机器的配置都是一样的,比较老的服务器:

  • CPU: Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz, 24 cores
  • Memory: 16G
  • OS: Linux 2.6.32-358.el6.x86_64, CentOS 6.4
  • Go: 1.7
  • Java: 1.8

分别在client并发数为100、500、1000、2000 和 5000的情况下测试,记录吞吐率(每秒调用次数, Throughput)、响应时间(Latency) 、成功率。
(更精确的测试还应该记录CPU使用率、内存使用、网络带宽、IO等,本文中未做比较)

首先看在四种并发下各RPC框架的吞吐率:
吞吐率
rpcx的性能遥遥领先,并且其它三种框架在并发client很大的情况下吞吐率会下降。

在这四种并发的情况下平均响应:
平均响应时间
这个和吞吐率的表现是一致的,还是rpcx最好,平均响应时间小于30ms, Dubbo在并发client多的情况下响应时间很长。
我们知道,在微服务流行的今天,一个单一的RPC的服务可能会被不同系统所调用,这些不同的系统会创建不同的client。如果调用的系统很多,就有可能创建很多的client。
这里统计的是这些client总的吞吐率和总的平均时间。

平均响应时间可能掩盖一些真相,尤其是当响应时间的分布不是那么平均,所以我们还可以关注另外一个指标,就是中位数。
这里的中位数指小于这个数值的测试数和大于这个数值的测试数相等。
响应时间中位数
gRPC框架的表现最好。

另外一个就是比较一下最长的响应时间,看看极端情况下各框架的表现:
最大响应时间
rpcx的最大响应时间都小于1秒,Motan的表现也不错,都小于2秒,其它两个框架表现不是太好。

本文以一个相同的测试case测试了四种RPC框架的性能,得到了这四种框架在不同的并发条件下的性能表现。期望读者能提出宝贵的意见,以便完善这个测试,并能增加更多的RPC框架的测试。

相关 [分布 rpc 框架] 推荐:

分布式RPC框架性能大比拼

- - 鸟窝
Dubbo 是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成. 不过,略有遗憾的是,据说在淘宝内部,dubbo由于跟淘宝另一个类似的框架HSF(非开源)有竞争关系,导致dubbo团队已经解散(参见 http://www.oschina.net/news/55059/druid-1-0-9 中的评论),反到是当当网的扩展版本仍在持续发展,墙内开花墙外香.

一个轻量级分布式 RPC 框架 — NettyRpc

- - ImportNew
最近在搜索Netty和Zookeeper方面的文章时,看到了这篇文章《 轻量级分布式 RPC 框架》,作者用Zookeeper、Netty和Spring写了一个轻量级的分布式RPC框架. 花了一些时间看了下他的代码,写的干净简单,写的RPC框架可以算是一个简易版的 dubbo. 这个RPC框架虽小,但是麻雀虽小,五脏俱全,有兴趣的可以学习一下.

JAVA RPC 通讯框架

- - 经验沉淀 知识结晶
Bison 是一个JAVA 程间的通信框架,基于apache mina 实现,对mina进行了byteBuffer 缓冲区重用以及半包出处时减少拷贝. 客户端(bison-client) 功能点. 2 支持高用性:高可用的一个基本原则,可以接受快速的失败,但不能接受长时间的等待. Githup地址:https://github.com/gavenpeng/Bison.

【RPC框架HttpInvoker一】HttpInvoker:Spring自带RPC框架

- - 开源软件 - ITeye博客
HttpInvoker是Spring原生的RPC调用框架,HttpInvoker同Burlap和Hessian一样,提供了一致的服务Exporter以及客户端的服务代理工厂Bean,这篇文章主要是复制粘贴了Hessian与Spring集成一文,. 【RPC框架Hessian四】Hessian与Spring集成.

zmq-rpc:基于zeromq网络层编写的protobuf RPC框架

- Shengbin - codedump
阅读过zmq的代码之后,感觉这个网络层是我目前见过最高效的–线程之间使用lockfree的消息队列保存消息,可以启动多个I/O线程分担压力等等特性.于是决定基于它写一个protobuf RPC的框架.. 另外,这里使用的protobuf是旧版本2.3.0,新版本2.4.1的生成的RPC service接口跟原来不太一致,暂时还没有去研究它.BTW,升级版本之后导致原来的接口发生变化这是一个很操蛋的事情..

集成libevent,google protobuf的RPC框架

- goodman - C++博客-那谁的技术博客
chenshuo的evproto同样也是集成libevent与google protobuf的RPC框架,不过在对libevent的使用上,这里的做法与他不尽相同:. 1) 他使用了libevent自带的RPC功能, 而这里只使用到libevent对网络I/O进行的封装的最基本的功能.. eventrpc项目目前是avidya下的一个子项目,avidya项目的定位是实现一些分布式的玩具系统(比如google已经公开论文的chubby,mapreduce,GFS等),也许以后不一定能被用上,但是也要实践做一把.由于有一个好用的RPC框架是做分布式的必需品,所有首先实现eventrpc这个子项目了,以后也许还会实现其他语言的版本,如python,java..

NFS-RPC框架优化过程

- EricSheng - BlueDavy之技术blog
NFS-RPC框架从编写之初,到现在为止(应该还会有些提升,不过估计不大),每秒支撑的请求数上升了好几倍,测试结果的演变为:. 以上测试结果为在100并发、100 request byte、100 response byte以及单连接下的背景下得出的,在这篇blog中来分享下这个框架所做的一些优化动作,希望能给编写rpc框架或使用mina/netty/grizzly的同学们一点点帮助,也希望得到高手们更多的指点.

RPC调用框架比较分析

- - 开源软件 - ITeye博客
RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. 简言之,RPC使得程序能够像访问本地系统资源一样,去访问远端系统资源. 比较关键的一些方面包括,通讯协议,序列化,资源(接口)描述,服务框架,性能,语言支持等.

RPC框架实现 - 容灾篇 - bangerlee

- - 博客园_首页
RPC(Remote Procedure Call,远程过程调用)框架是分布式服务的基石,实现RPC框架需要考虑方方面面. 其对业务隐藏了底层通信过程(TCP/UDP、打包/解包、序列化/反序列化),使上层专注于功能实现;框架层面,提供各类可选架构(多进程/多线程/协程);应对设备故障(高负载/死机)、网络故障(拥塞/网络分化),提供相应容灾措施.

基于hessian和netty的RPC框架设计和实现

- - Java - 编程语言 - ITeye博客
基于hessian和netty的RPC框架设计和实现.         对系统进行服务化改造,或者构建一个分布式系统,RPC是核心的组件,目前主流的RPC框架有hessian\thrift\ avro等,如果不考虑跨语言的话thrift\ avro使用起来稍显复杂,要写IDL序列化配置,hessian又依赖servlet容器,于是使用netty和hessian构建了一个的RPC框 架.