分布式RPC框架性能大比拼 dubbo、motan、rpcx、gRPC、thrift的性能比较

匿名 (未验证) 提交于 2019-12-03 00:30:01


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

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

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

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

thrift是Apache的一个跨语言的高性能的服务框架,也得到了广泛的应用。

后续还会增加更多的 RPC 框架的比较,敬请收藏本文网址

以下是它们的功能比较:


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


这个服务传递的消息体有一个protobuf文件定义:

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]; }
  • 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

相应的Thrift定义文件为

namespace java com.colobu.thrift struct BenchmarkMessage {   1:  string field1,   2:  i32 field2,   3:  i32 field3,   4:  string field4,   5:  i64 field5,   6:  i32 field6,   7:  string field7,   9:  string field9,   12:  bool field12,   13:  bool field13,   14:  bool field14,   16:  i32 field16,   17:  bool field17,   18:  string field18,   22:  i64 field22,   23:  i32 field23,   24:  bool field24,   25:  i32 field25,   29:  i32 field29,   30:  bool field30,   59:  bool field59,   60:  i32 field60,   67:  i32 field67,   68:  i32 field68,   78:  bool field78,   80:  bool field80,   81:  bool field81,   100:  i32 field100,   101:  i32 field101,   102:  string field102,   103:  string field103,   104:  i32 field104,   128:  i32 field128,   129:  string field129,   130:  i32 field130,   131:  i32 field131,   150:  i32 field150,   271:  i32 field271,   272:  i32 field272,   280:  i32 field280, } service Greeter {     BenchmarkMessage say(1:BenchmarkMessage name); }
  • 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

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

服务很简单:

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





Thrift使用Java进行测试。



另外测试中服务的成功率都是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
  • Dubbo: 2.5.4-SNAPSHOT (2016-09-05)
  • Motan: 0.2.2-SNAPSHOT (2016-09-05)
  • gRPC: 1.0.0
  • rpcx: 2016-09-05


  • (更精确的测试还应该记录CPU使用率、内存使用、网络带宽、IO等,本文中未做比较)



吞吐率


thrift比rpcx性能差一点,但是还不错,远好于gRPC,dubbo和motan,但是随着client的增多,性能也下降的很厉害,在client较少的情况下吞吐率挺好。



平均响应时间



这里统计的是这些client总的吞吐率和总的平均时间。




响应时间中位数

gRPC框架的表现最好。



最大响应时间

rpcx的最大响应时间都小于1秒,Motan的表现也不错,都小于2秒,其它两个框架表现不是太好。

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!