Dubbo做爲一個擴展能力極強的分佈式服務框架,在實現rpc特性的時候,給傳輸協議、傳輸框架和序列化方式提供了多種擴展實現,供開發者根據實際場景進行選擇。html
一、支持常見的傳輸協議:RMI、Dubbo、Hessain、WebService、Http等,其中Dubbo和RMI協議基於TCP實現,Hessian和WebService基於HTTP實現。java
二、傳輸框架:Netty、Mina、grizzly以及基於servlet等方式。git
三、序列化方式:Hessian二、dubbo、JSON( fastjson 實現)、JAVA、SOAP、kryo和fst 等。github
本文主要基於dubbox框架下的通信協議進行性能測試對比。web
文章模板參考了:http://www.cnblogs.com/lengfo/p/4293399.html?utm_source=tuicool&utm_medium=referral,在該文的基礎上作了一些調整,測試數據是本人親自測試的實際結果。json
基於dubbox 2.8.4框架,使用zookeeper做爲註冊中心,分別以單線程和多線程的方式測試如下組合。windows
分組名 | 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,消費者和生產者都是在本機上。tomcat
機器的配置以下:服務器
內存12G;多線程
CPU是intel i5 2.5ghz 4核;
操做系統Windows visita6.1;
jdk1.6.0.25和jdk1.7.0_79;
JVM配置是默認值,最大堆64M,
一、單POJO對象,嵌套複雜集合類型
二、POJO集合,包含100個單POJO對象
三、1K字符串
四、100K字符串
五、1M字符串
一、服務接口相關代碼:
public interface DemoService { public Object sendRequest(Object requestObject); }
二、服務實現相關代碼,測試數據在服務器端不作任何處理原樣返回:
public class DemoServiceImpl implements DemoService{ ResponseObject responseObject = new ResponseObject(100); public Object sendRequest(Object request) { return request; } }
三、測試框架介紹
本文是基於dubbo自帶的benchmark性能測試框架進行測試的,對該框架作了簡單的調整和修改,框架代碼見:https://github.com/dangdangdotcom/dubbox/tree/master/dubbo-test/dubbo-test-benchmark
一、測試僅記錄rpc調用時間,測試數據的讀取組裝以及首次創建鏈接等相關耗時時間不做統計,循環執行60秒鐘取平均響應時間值。
二、服務消費方測試代碼
輸入複雜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; }
三、測試數據耗時記錄
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 |
四、性能對比
一、因爲測試機器配置較低,爲了不達到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%。