前言

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、性能对比

dubbo 是基层协议转发 dubbo传输协议和序列化协议_netty


多线程测试

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%。