文档章节

基于dubbo框架下的RPC通讯协议性能测试

济远
 济远
发布于 2017/02/16 10:32
字数 2300
阅读 7
收藏 0
点赞 0
评论 0

一、前言

  Dubbo RPC服务框架支持丰富的传输协议、序列化方式等通讯相关的配置和扩展。dubbo执行一次RPC请求的过程大致如下:消费者(Consumer)向注册中心(Registry)执行RPC请求,注册中心分配服务URL并路由到具体服务提供方(Provider),消费者和服务提供方建立网络连接,服务提供方在本地创建连接池对象并提供远程服务,对于长连接类型协议(如dubbo协议)将保持连接,减少握手认证,调用过程中可以避免频繁建立和断开连接导致的性能开销,保持长连接需要有心跳包的发送,所以对于非频繁调用的服务保持连接同样会有消耗。更多关于dubbo详细介绍请参照官方文档(http://alibaba.github.io/dubbo-doc-static/Home-zh.htm)。

  1、支持常见的传输协议:RMI、Dubbo、Hessain、WebService、Http等,其中Dubbo和RMI协议基于TCP实现,Hessian和WebService基于HTTP实现。

  2、传输框架:Netty、Mina、以及基于servlet等方式。

  3、序列化方式:Hessian2、dubbo、JSON(fastjson 实现)、JAVA、SOAP 等。

  本文主要基于dubbo框架下的通讯协议进行性能测试对比。

 

二、测试方案

  基于dubbo 2.5.3框架,使用zookeeper作为dubbo服务注册中心,分别以单线程和多线程的方式测试以下方案:

  Protocol       Transporter       Serialization     Remark
A  dubbo 协议  netty  hessian2  
B  dubbo 协议  netty  dubbo  
C  dubbo 协议  netty  java  
D  RMI 协议  netty  java  
E  RMI 协议  netty  hessian2  
F  Hessian 协议  servlet  hessian2  Hessian,基于tomcat容器     
G  WebService 协议    servlet  SOAP  CXF,基于tomcat容器  

 

三、传输测试数据

1、单POJO对象,嵌套复杂集合类型

2、POJO集合,包含100个单POJO对象

3、1K字符串

4、100K字符串

5、1M字符串 

 

四、服务接口和实现

  1、服务接口相关代码: 

 1 package ibusiness;
 2 
 3 import java.util.List;
 4 
 5 import model.*;
 6 
 7 public interface IBusinessOrder { 
 8     public String SendStr(String str); 
 9 
10     public List<OrderInfo> LoadOrders(List<OrderInfo> orders); 
11 
12     public OrderInfo LoadOrder(OrderInfo order);
13 }

  2、服务实现相关代码,测试数据在服务器端不做任何处理原样返回:

技术分享

 1 package business;
 2 
 3 import ibusiness.IBusinessOrder;
 4 
 5 import java.util.List;
 6 
 7 import model.*;
 8 
 9 public class BusinessOrder implements IBusinessOrder {
10     public String SendStr(String str) {
11         return str;
12     }
13 
14     public List<OrderInfo> LoadOrders(List<OrderInfo> orders) {
15         return orders;
16     }
17 
18     public OrderInfo LoadOrder(OrderInfo order) {
19         return order;
20     }
21 }

View Code

 

五、单线程测试

  1、测试仅记录rpc调用时间,测试数据的读取组装以及首次建立连接等相关耗时时间不作统计,循环执行100次取平均值。  

  2、服务消费方测试代码

技术分享

  1 import java.util.List;
  2 
  3 import org.springframework.context.ApplicationContext;
  4 import org.springframework.context.support.FileSystemXmlApplicationContext;
  5 
  6 import com.alibaba.dubbo.rpc.service.EchoService;
  7 import common.Common;
  8 
  9 import ibusiness.*;
 10 import model.*;
 11 
 12 public class Program {
 13     public static void main(String[] args) throws Exception {
 14 
 15         ApplicationContext ctx = new FileSystemXmlApplicationContext("src//applicationContext.xml");
 16         IBusinessOrder orderBusiness = (IBusinessOrder) ctx.getBean("orderBusiness");
 17 
 18 //        EchoService echoService = (EchoService) orderBusiness;
 19 //        String status = echoService.$echo("OK").toString();
 20 //        if (!status.equals("OK")) {
 21 //            System.out.println("orderBusiness out of service!");
 22 //            return;
 23 //        } else {
 24 //            System.out.println("orderBusiness in service !");
 25 //        }
 26 
 27         long startMili, endMili;
 28         int loop = 100;
 29 
 30         // 单个pojo
 31         try {
 32             OrderInfo order = Common.BuildOrder();
 33             orderBusiness.LoadOrder(order); // 防止首次连接的开销
 34 
 35             startMili = System.currentTimeMillis();
 36             OrderInfo returnOrder = null;
 37             for (int i = 0; i < loop; i++) {
 38                 returnOrder = orderBusiness.LoadOrder(order);
 39             }
 40             endMili = System.currentTimeMillis();
 41             System.out.println("单个pojo 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒 ,返回对象BillNumber:" + returnOrder.getBillNumber());
 42         } catch (Exception ex) {
 43             System.out.println("单个pojo 测试失败!");
 44             //ex.printStackTrace();
 45         }
 46 
 47         // pojo集合 (100)
 48         try {
 49             List<OrderInfo> orderList = Common.BuildOrderList();
 50             startMili = System.currentTimeMillis();
 51             List<OrderInfo> returnOrderList = null;
 52             for (int i = 0; i < loop; i++) {
 53                 returnOrderList = orderBusiness.LoadOrders(orderList);
 54             }
 55             endMili = System.currentTimeMillis();
 56             System.out.println("pojo集合 (100) 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒 ,返回记录数:" + returnOrderList.size());
 57         } catch (Exception ex) {
 58             System.out.println("pojo集合 (100) 测试失败!");
 59         }
 60 
 61         // 1K String
 62         try {
 63             String str1k = Common.Build1KString();
 64             startMili = System.currentTimeMillis();
 65             String returnStr1k = null;
 66             for (int i = 0; i < loop; i++) {
 67                 returnStr1k = orderBusiness.SendStr(str1k);
 68             }
 69             endMili = System.currentTimeMillis();
 70             System.out.println("1K String 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒,返回字符长度:" + returnStr1k.length());
 71         } catch (Exception ex) {
 72             System.out.println("1K String 测试失败!");
 73         }
 74 
 75         // 100K String
 76         try {
 77             String str100K = Common.Build100KString();
 78             startMili = System.currentTimeMillis();
 79             String returnStr100k = null;
 80             for (int i = 0; i < loop; i++) {
 81                 returnStr100k = orderBusiness.SendStr(str100K);
 82             }
 83             endMili = System.currentTimeMillis();
 84             System.out.println("100K String 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒,返回字符长度:" + returnStr100k.length());
 85         } catch (Exception ex) {
 86             System.out.println("100K String 测试失败!");
 87         }
 88 
 89         // 1M String
 90         try {
 91             String str1M = Common.Build1MString();
 92             startMili = System.currentTimeMillis();
 93             String returnStr1M = null;
 94             for (int i = 0; i < loop; i++) {
 95                 returnStr1M = orderBusiness.SendStr(str1M);
 96             }
 97             endMili = System.currentTimeMillis();
 98             System.out.println("1M String 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒,返回字符长度:" + returnStr1M.length());
 99         } catch (Exception ex) {
100             System.out.println("1M String 测试失败!");
101         }
102 
103         System.out.println("all test done!");
104     } 
105 }

View Code

  3、测试数据耗时记录

A、dubbo 协议、netty 传输、hessian2 序列化

<dubbo:protocol name="dubbo" server="netty" port="30001" serialization="hessian2"  />

单个POJO 0.958毫秒
POJO集合 (100) 1.438毫秒
1K String 0.68毫秒
100K String 4.262毫秒
1M String 32.473毫秒 

 

B、dubbo 协议、netty 传输、dubbo 序列化

<dubbo:protocol name="dubbo" server="netty" port="30001" serialization="dubbo" /> 

单个POJO 1.45毫秒
POJO集合 (100) 3.42毫秒
1K String 0.94毫秒
100K String 4.35毫秒
1M String 27.92毫秒

 

C、dubbo 协议、netty 传输、java 序列化

<dubbo:protocol name="dubbo" server="netty" port="30001" serialization="java" /> 

单个POJO 1.91毫秒
POJO集合 (100) 4.48毫秒
1K String 1.0毫秒
100K String 3.3毫秒
1M String 18.09毫秒

 

D、RMI 协议、netty 传输、java 序列化 

<dubbo:protocol name="rmi" server="netty" port="1099" serialization="java" />   

单个POJO 1.63毫秒
POJO集合 (100) 5.15毫秒
1K String 0.77毫秒
100K String 2.15毫秒
1M String 15.21毫秒

 

E、RMI 协议、netty 传输、hessian2 序列化 

<dubbo:protocol name="rmi" server="netty" port="1099" serialization="hessian2"  /> 

单个POJO 1.63毫秒
POJO集合 (100) 5.12毫秒
1K String 0.76毫秒
100K String 2.13毫秒
1M String 15.11毫秒

 

F、Hessian协议、servlet(tomcat容器)、hessian2 序列化 

<dubbo:protocol name="hessian" port="8080" server="servlet" serialization="hessian2" /> 

单个POJO 1.6毫秒
POJO集合 (100) 5.98毫秒
1K String 1.88毫秒
100K String 5.52毫秒
1M String 39.87毫秒

 

G、WebService协议、servlet(tomcat容器)、SOAP序列化

<dubbo:protocol name="webservice" port="8080" server="servlet" /> 

单个POJO 7.4毫秒
POJO集合 (100) 34.39毫秒
1K String 6.0毫秒
100K String 7.43毫秒
1M String 34.61毫秒

 

  4、性能对比

 

 

六、多线程测试

  1、由于测试机器配置较低,为了避免达到CPU瓶颈,测试设定服务消费方Consumer并发10个线程,每个线程连续对远程方法执行5次调用,服务提供方设置允许最大连接数100个,同时5个连接并行执行,超时时间设置为5000ms,要求所有事务都能正确返回没有异常,统计包含首次建立连接的消耗时间。

  2、服务消费方测试代码

 

  3、测试数据耗时记录

A、dubbo 协议、netty 传输、hessian2 序列化

<dubbo:protocol name="dubbo" server="netty" port="30001" serialization="hessian2"  /> 

单个POJO 1165毫秒
POJO集合 (100) 1311毫秒
1K String 1149毫秒
100K String 1273毫秒
1M String 2141毫秒

 

B、dubbo 协议、netty 传输、dubbo 序列化

<dubbo:protocol name="dubbo" server="netty" port="30001" serialization="dubbo" /> 

单个POJO 1220毫秒
POJO集合 (100) 1437毫秒
1K String 1145毫秒
100K String 1253毫秒
1M String 2065毫秒

 

C、dubbo 协议、netty 传输、java 序列化

<dubbo:protocol name="dubbo" server="netty" port="30001" serialization="java" /> 

单个POJO 1188毫秒
POJO集合 (100) 1401毫秒
1K String 1123毫秒
100K String 1227毫秒
1M String 1884毫秒

 

D、RMI 协议、netty 传输、java 序列化 

<dubbo:protocol name="rmi" server="netty" port="1099" serialization="java" />   

单个POJO 1751毫秒
POJO集合 (100) 1569毫秒
1K String 1766毫秒
100K String 1356毫秒
1M String 1741毫秒

 

E、RMI 协议、netty 传输、hessian2 序列化 

<dubbo:protocol name="rmi" server="netty" port="1099" serialization="hessian2"  /> 

单个POJO 1759毫秒
POJO集合 (100) 1968毫秒
1K String 1239毫秒
100K String 1339毫秒
1M String 1736毫秒

 

F、Hessian协议、servlet、hessian2 序列化 

<dubbo:protocol name="hessian" port="8080" server="servlet" serialization="hessian2" /> 

单个POJO 1341毫秒
POJO集合 (100) 2223毫秒
1K String 1800毫秒
100K String 1916毫秒
1M String 2445毫秒

 

G、WebService协议、servlet、SOAP序列化

<dubbo:protocol name="webservice" port="8080" server="servlet" /> 

单个POJO 1975毫秒
POJO集合 (100) 2768毫秒
1K String 1894毫秒
100K String 2098毫秒
1M String 2887毫秒

 

  4、性能对比

 

 

七、性能分析

  测试过程中尽管考虑了非常多的影响因素,但仍然有很多局限性,包括连接数限制、并发量、线程池策略、Cache、IO、硬件性能瓶颈等等因素,而且各自的适用场景不同,测试结果仅供参考

  从单线程测试结果可以看出,dubbo协议采用NIO复用单一长连接更适合满足高并发小数据量的rpc调用,而在大数据量下的传输性能并不好,建议使用rmi协议,多线程测试中dubbo协议对小数据量的rpc调用同样保持优势,在大数据量的传输中由于长连接的原因对比rmi协议传输耗时差距并不明显,这点同样验证了上述观点。关于数据的序列化方式选择需要考虑序列化和反序列化的效率问题,传输内容的大小,以及格式的兼容性约束,其中hessian2作为duobb协议下的默认序列化方式,推荐使用。

  如果有描述错误或者不当的地方欢迎指正。

本文转载自:

共有 人打赏支持
济远
粉丝 0
博文 13
码字总数 13858
作品 0
南京
程序员
分布式RPC服务框架--rpcx

rpcx是一个类似阿里巴巴 Dubbo 和微博 Motan 的分布式的RPC服务框架,基于Golang net/rpc实现。 与gRPC比较,完胜gRPC, 更不用说其它的"老"的RPC框架了。 谈起分布式的RPC框架,比较出名的是...

匿名 ⋅ 2017/01/31 ⋅ 7

当当网开源 Dubbox,扩展 Dubbo 服务框架支持REST风格远程调用

当当网近日开源了Dubbox项目,可为Dubbo服务框架提供多项扩展功能,包括REST风格远程调用、Kryo/FST序列化等等。 当当网架构部和技术委员会架构师沈理向InfoQ中文站介绍了Dubbox项目,开发背...

空云万里晴 ⋅ 2014/10/23 ⋅ 13

dubbox学习

Dubbo是一个被国内很多互联网公司广泛使用的开源分布式服务框架,即使从国际视野来看应该也是一个非常全面的SOA基础框架。作为一个重要的技术研究课题,在当当网我们根据自身的需求,为Dubbo...

HI曲奇饼干 ⋅ 2016/01/21 ⋅ 2

Dubbo 扩展 - Dubbox

Dubbo是一个被国内很多互联网公司广泛使用的开源分布式服务框架,即使从国际视野来看应该也是一个非常全面的SOA基础框架。作为一个重要的技术研究课题,在当当网我们根据自身的需求,为Dubbo...

匿名 ⋅ 2014/10/23 ⋅ 11

dubbo典型协议、传输组件、序列化方式组合性能对比测试

前言 Dubbo作为一个扩展能力极强的分布式服务框架,在实现rpc特性的时候,给传输协议、传输框架和序列化方式提供了多种扩展实现,供开发者根据实际场景进行选择。 1、支持常见的传输协议:R...

杨武兵 ⋅ 2016/06/13 ⋅ 6

dubbo快速入门

1、web架构演变过程 单一应用架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。 此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。 垂直应用...

毅屺 ⋅ 2016/01/21 ⋅ 0

分布式服务框架原理(一)设计和实现

分布式服务框架设计 分布式服务框架一般可以分为以下几个部分, (1)RPC基础层: 包括底层通信框架,如NIO框架、通信协议,序列化和反序列化协议, 以及在这几部分上的封装,屏蔽底层通信细...

吞吞吐吐的 ⋅ 2017/10/04 ⋅ 0

Dubbo 低调重启维护,焕发新春的它要走向何处

几个月前,开源社区发生了一件大事,那个曾经风靡国内 Java 开发者的开源 RPC 服务框架 —— Dubbo,低调宣布将重新得到官方维护与支持。 对于 Dubbo 框架,大部分 Java 开发者都不会感到陌生...

oschina ⋅ 2017/12/13 ⋅ 51

阿里巴巴Dubbo实现的源码分析

Dubbo概述 Dubbo是阿里巴巴开源出来的一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及作为SOA服务治理的方案。它的核心功能包括: #remoting:远程通讯基础,提供对...

candies ⋅ 2014/02/22 ⋅ 0

java 分布式子系统之间通讯

问题: java 分布式子系统之间通讯采用何种技术实现? 个人思考: 目前个人掌握大方向有四种: (1)基于RPC实现,例webservice 、java平台的rmi等,据了解性能不是很好。 (2)基于JMS标准的...

cccyb ⋅ 2015/08/25 ⋅ 3

没有更多内容

加载失败,请刷新页面

加载更多

下一页

个人博客的运营模式能否学习TMALL天猫质量为上?

心情随笔|个人博客的运营模式能否学习TMALL天猫质量为上? 中国的互联网已经发展了很多年了,记得在十年前,个人博客十分流行,大量的人都在写博客,而且质量还不错,很多高质量的文章都是在...

原创小博客 ⋅ 今天 ⋅ 0

JavaScript零基础入门——(十一)JavaScript的DOM操作

JavaScript零基础入门——(十一)JavaScript的DOM操作 大家好,欢迎回到我们的JavaScript零基础入门。最近有些同学问我说,我讲的的比书上的精简不少。其实呢,我主要讲的是我在开发中经常会...

JandenMa ⋅ 今天 ⋅ 0

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 今天 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 今天 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 今天 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 今天 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部