前言
Dubbo作为一个扩展能力极强的分布式服务框架,在实现rpc特性的时候,给传输协议、传输框架和序列化方式提供了多种扩展实现,供开发者根据实际场景进行选择。
1、支持常见的传输协议:RMI、Dubbo、Hessain、WebService、Http等,其中Dubbo和RMI协议基于TCP实现,Hessian和WebService基于HTTP实现。
2、传输框架:Netty、Mina、grizzly以及基于servlet等方式。
3、序列化方式:Hessian2、dubbo、JSON( fastjson 实现)、JAVA、SOAP、kryo和fst 等。
本文主要基于dubbox框架下的通讯协议进行性能测试对比。
文章模板参考了:,在该文的基础上做了一些调整,测试数据是本人亲自测试的实际结果。
测试方案
基于dubbox 2.8.4框架,使用zookeeper作为注册中心,分别以单线程和多线程的方式测试以下组合。
分组名 | Protocol | Transporter | Serialization | Remark |
A | dubbo | netty | hessian2 |
|
B | dubbo | netty | dubbo |
|
C | dubbo | netty | java |
|
D | dubbo | netty | fst | |
E | dubbo | netty | kryo | |
F | dubbo | mina | hessian2 | |
G | rmi | netty | java |
|
H | rmi | netty | hessian2 |
|
I | Hessian | servlet | hessian2 | Hessian,基于tomcat8.0嵌入式容器 |
J | WebService | servlet | SOAP | CXF,基于tomcat8.0嵌入式容器 |
K | http | servlet | json | 基于tomcat8.0嵌入式容器 |
测试环境
本次测试是所有组件都部署在同一台PC机上进行的,包括zookeeper,消费者和生产者都是在本机上。
机器的配置如下:
内存12G;
CPU是intel i5 2.5ghz 4核;
操作系统Windows visita6.1;
jdk1.6.0.25和jdk1.7.0_79;
JVM配置是默认值,最大堆64M,
传输测试数据
1、单POJO对象,嵌套复杂集合类型
2、POJO集合,包含100个单POJO对象
3、1K字符串
4、100K字符串
5、1M字符串
服务接口和实现
1、服务接口相关代码:
public interface DemoService {
public Object sendRequest(Object requestObject);
}
2、服务实现相关代码,测试数据在服务器端不做任何处理原样返回:
public class DemoServiceImpl implements DemoService{
ResponseObject responseObject = new ResponseObject(100);
public Object sendRequest(Object request) {
return request;
}
}
3、测试框架介绍
本文是基于dubbo自带的benchmark性能测试框架进行测试的,对该框架做了简单的调整和修改,框架代码见:https://github.com/dangdangdotcom/dubbox/tree/master/dubbo-test/dubbo-test-benchmark
单线程测试
1、测试仅记录rpc调用时间,测试数据的读取组装以及首次建立连接等相关耗时时间不作统计,循环执行60秒钟取平均响应时间值。
2、服务消费方测试代码
输入复杂POJO测试代码
private static BidRequest request = new BidRequest();
private static int size = 100;
private static List<BidRequest> requests = new ArrayList<BidRequest>();
static{
request.setId("ssss");
Geo geo = new Geo();
geo.setCity("beijing");
geo.setCountry("china");
geo.setLat(1.0f);
geo.setLon(5.3f);
Device device = new Device();
device.setLang("中文");
device.setOs("windows 7");
device.setVersion("1.0.0");
device.setModel("dddddd");
device.setGeo(geo);
request.setDevice(device);
List<Impression> impressions = new ArrayList<Impression>();
for(int i=0; i<3; i++){
Impression impression = new Impression();
impression.setId("2333"+i);
impression.setBidFloor(2223.3333d);
impressions.add(impression);
}
request.setImpressions(impressions);
for(int i=0; i<size; i++){
requests.add(request);
}
}
@SuppressWarnings({ "unchecked"})
@Override
public Object invoke(ServiceFactory serviceFactory) {
DemoService demoService = (DemoService) serviceFactory.get(DemoService.class);
Object result = demoService.sendRequest(requests);
return result;
}
输入字符串测试代码
private static String message = null;
private static int length = 1024000;
static{
message = new String(new byte[length]);
}
public Object invoke(ServiceFactory serviceFactory) {
DemoService demoService = (DemoService) serviceFactory.get(DemoService.class);
Object result = demoService.sendRequest(requestObject);
return result;
}
3、测试数据耗时记录
A、dubbo 协议、netty 传输、hessian2 序列化
<dubbo:protocol name="dubbo" server="netty" port="20885" serialization="hessian2" />
jdk1.6测试数据
单个POJO | 0.369ms |
POJO集合 (100) | 3.326ms |
1K String | 0.354ms |
100K String | 17.804ms |
1M String | 154.178ms |
jdk1.7测试数据
单个POJO | 0.195ms |
POJO集合 (100) | 1.207ms |
1K String | 0.203ms |
100K String | 4.901ms |
1M String | 47.691ms |
B、dubbo 协议、netty 传输、dubbo 序列化
<dubbo:protocol name="dubbo" server="netty" port="20885" serialization="dubbo" />
jdk1.6测试数据
单个POJO | 0.345ms |
POJO集合 (100) | 6.663ms |
1K String | 0.325ms |
100K String | 17.756ms |
1M String | 128.241ms |
jdk1.7测试数据
单个POJO | 0.203ms |
POJO集合 (100) | 2.47ms |
1K String | 0.193ms |
100K String | 3.917ms |
1M String | 36.186ms |
C、dubbo 协议、netty 传输、java 序列化
<dubbo:protocol name="dubbo" server="netty" port="20885" serialization="java" />
jdk1.6测试数据
单个POJO | 0.541ms |
POJO集合 (100) | 4.194ms |
1K String | 0.391ms |
100K String | 26.561ms |
1M String | 151.337ms |
jdk1.7测试数据
单个POJO | 0.375ms |
POJO集合 (100) | 1.839ms |
1K String | 0.237ms |
100K String | 5.691ms |
1M String | 54.462ms |
D、dubbo 协议、netty 传输、fst序列化
<dubbo:protocol name="dubbo" server="netty" port="20885" serialization="fst" />
jdk1.6测试数据
单个POJO | 0.273ms |
POJO集合 (100) | 0.768ms |
1K String | 0.31ms |
100K String | 20.048ms |
1M String | 353.594ms |
jdk1.7测试数据
单个POJO | 0.187ms |
POJO集合 (100) | 0.429ms |
1K String | 0.281ms |
100K String | 2.861ms |
1M String | 30.599ms |
E、dubbo 协议、netty 传输、kryo序列化
<dubbo:protocol name="dubbo" server="netty" port="20885" serialization="kryo" />
jdk1.6测试数据
单个POJO | 3.087ms |
POJO集合 (100) | 3.749ms |
1K String | 3.017ms |
100K String | 33.283ms |
1M String | 353.851ms |
jdk1.7测试数据
单个POJO | 2.767ms |
POJO集合 (100) | 2.869ms |
1K String | 2.636ms |
100K String | 5.804ms |
1M String | 33.501ms |
F、dubbo 协议、mina 传输、hessian2序列化
<dubbo:protocol name="dubbo" server="mina" port="20885" serialization="hessian2" />
jdk1.6测试数据
单个POJO | 0.378ms |
POJO集合 (100) | 3.47ms |
1K String | 6002.945ms |
100K String | 6061.22ms |
1M String | 5067.535ms |
jdk1.7测试数据
单个POJO | 0.213ms |
POJO集合 (100) | 6004.22ms |
1K String | 6003.739ms |
100K String | 6013.998ms |
1M String | 3779.117ms |
G、RMI 协议、netty 传输、java 序列化
<dubbo:protocol name="rmi" server="netty" port="20885" serialization="java" />
jdk1.6测试数据
单个POJO | 0.349ms |
POJO集合 (100) | 2.874ms |
1K String | 0.203ms |
100K String | 7.129ms |
1M String | 136.697ms |
jdk1.7测试数据
单个POJO | 0.203ms |
POJO集合 (100) | 1.515ms |
1K String | 0.138ms |
100K String | 3.609ms |
1M String | 35.188ms |
H、RMI 协议、netty 传输、hessian2 序列化
<dubbo:protocol name="rmi" server="netty" port="20885" serialization="hessian2" />
jdk1.6测试数据
单个POJO | 0.338ms |
POJO集合 (100) | 2.815ms |
1K String | 0.196ms |
100K String | 8.509ms |
1M String | 134.098ms |
jdk1.7测试数据
单个POJO | 0.213ms |
POJO集合 (100) | 1.511ms |
1K String | 0.139ms |
100K String | 3.589ms |
1M String | 36.322ms |
I、Hessian协议、servlet(tomcat容器)、hessian2 序列化
用到了tomcat-embed-core-8.0.11,需要用jdk1.7以上版本,所以本次测试使用jdk1.7
<dubbo:protocol name="hessian" port="20885" server="tomcat" serialization="hessian2" />
jdk1.7测试数据
单个POJO | 0.482ms |
POJO集合 (100) | 3.201ms |
1K String | 0.413ms |
100K String | 6.893ms |
1M String | 59.805ms |
J、WebService协议、servlet(tomcat容器)、SOAP序列化
<dubbo:protocol name="webservice" port="20885" server="tomcat" />
jdk1.7测试数据
单个POJO | 0.598ms |
POJO集合 (100) | 0.731ms |
1K String | 11.603ms |
100K String | 71.991ms |
1M String | 81.596ms |
H、http协议、servlet(tomcat容器)、json序列化
<dubbo:protocol name="http" port="20885" server="tomcat" serialization="json"/>
jdk1.7测试数据
单个POJO | 0.586ms |
POJO集合 (100) | 2.179ms |
1K String | 0.722ms |
100K String | 6.982ms |
1M String | 59.848ms |
4、性能对比
多线程测试
1、由于测试机器配置较低,为了避免达到CPU瓶颈,测试设定服务消费方Consumer并发10个线程,每个线程连续对远程方法执行60秒钟,超时时间设置为2000ms,要求所有事务都能正确返回没有异常。
性能分析
影响性能测试结果的因素太多了,本文只是做了非常局限的测试,测试用例覆盖率不够,测试环境和条件制约较大,因此本文的测试结果绝对是仅供参考。不能完全信任本文的测试数据和结论。
通过上述的对比测试分析可以看出:
1.内部应用之间的小尺寸的对象和字符串调用的场景推荐使用dubbo+netty+fst的组合较优。fst的性能要由于hessian2。
2.rmi协议在传输大尺寸字符串对象的时候表现更优,这超出了我们一般的认知。
3.mina框架不推荐使用,则测试中的表现非常差,深层次的原因还没有深究,大量的调用超时失败,dubbo的测试报告也指出它存在一些问题,因此该框架不建议使用。
4.kryo序列化组件的性能表现较差,这与其它的测试报告的出入较大,具体原因需要深层次的探究。
5.有部分测试失败,具体原因有待考究。
6.jdk1.6 和 jdk1.7对性能测试结果差异较大,jdk1.7测试性能好于1.6. 推荐使用jdk1.7. 以dubbo协议,默认的传输组件和序列化组件为例,jdk1.7的环境下性能提升接近于90%。