当前位置:首页 > 服务端 > 基于dubbo框架下的RPC通讯协议性能测试

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

2022年09月16日 16:58:12服务端6

一、前言

  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、服务接口相关代码: 

package ibusiness;

import java.util.List;

import model.*;

public interface IBusinessOrder { 
    public String SendStr(String str); 

    public List<OrderInfo> LoadOrders(List<OrderInfo> orders); 

    public OrderInfo LoadOrder(OrderInfo order);
}


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

package business;

import ibusiness.IBusinessOrder;

import java.util.List;

import model.*;

public class BusinessOrder implements IBusinessOrder {
    public String SendStr(String str) {
        return str;
    }

    public List<OrderInfo> LoadOrders(List<OrderInfo> orders) {
        return orders;
    }

    public OrderInfo LoadOrder(OrderInfo order) {
        return order;
    }
}


 

五、单线程测试

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

  2、服务消费方测试代码

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.alibaba.dubbo.rpc.service.EchoService;
import common.Common;

import ibusiness.*;
import model.*;

public class Program {
    public static void main(String[] args) throws Exception {

        ApplicationContext ctx = new FileSystemXmlApplicationContext("src//applicationContext.xml");
        IBusinessOrder orderBusiness = (IBusinessOrder) ctx.getBean("orderBusiness");

//        EchoService echoService = (EchoService) orderBusiness;
//        String status = echoService.$echo("OK").toString();
//        if (!status.equals("OK")) {
//            System.out.println("orderBusiness out of service!");
//            return;
//        } else {
//            System.out.println("orderBusiness in service !");
//        }

        long startMili, endMili;
        int loop = 100;

        // 单个pojo
        try {
            OrderInfo order = Common.BuildOrder();
            orderBusiness.LoadOrder(order); // 防止首次连接的开销

            startMili = System.currentTimeMillis();
            OrderInfo returnOrder = null;
            for (int i = 0; i < loop; i++) {
                returnOrder = orderBusiness.LoadOrder(order);
            }
            endMili = System.currentTimeMillis();
            System.out.println("单个pojo 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒 ,返回对象BillNumber:" + returnOrder.getBillNumber());
        } catch (Exception ex) {
            System.out.println("单个pojo 测试失败!");
            //ex.printStackTrace();
        }

        // pojo集合 (100)
        try {
            List<OrderInfo> orderList = Common.BuildOrderList();
            startMili = System.currentTimeMillis();
            List<OrderInfo> returnOrderList = null;
            for (int i = 0; i < loop; i++) {
                returnOrderList = orderBusiness.LoadOrders(orderList);
            }
            endMili = System.currentTimeMillis();
            System.out.println("pojo集合 (100) 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒 ,返回记录数:" + returnOrderList.size());
        } catch (Exception ex) {
            System.out.println("pojo集合 (100) 测试失败!");
        }

        // 1K String
        try {
            String str1k = Common.Build1KString();
            startMili = System.currentTimeMillis();
            String returnStr1k = null;
            for (int i = 0; i < loop; i++) {
                returnStr1k = orderBusiness.SendStr(str1k);
            }
            endMili = System.currentTimeMillis();
            System.out.println("1K String 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒,返回字符长度:" + returnStr1k.length());
        } catch (Exception ex) {
            System.out.println("1K String 测试失败!");
        }

        // 100K String
        try {
            String str100K = Common.Build100KString();
            startMili = System.currentTimeMillis();
            String returnStr100k = null;
            for (int i = 0; i < loop; i++) {
                returnStr100k = orderBusiness.SendStr(str100K);
            }
            endMili = System.currentTimeMillis();
            System.out.println("100K String 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒,返回字符长度:" + returnStr100k.length());
        } catch (Exception ex) {
            System.out.println("100K String 测试失败!");
        }

        // 1M String
        try {
            String str1M = Common.Build1MString();
            startMili = System.currentTimeMillis();
            String returnStr1M = null;
            for (int i = 0; i < loop; i++) {
                returnStr1M = orderBusiness.SendStr(str1M);
            }
            endMili = System.currentTimeMillis();
            System.out.println("1M String 平均传输耗时为:" + ((endMili - startMili) / (float) loop) + "毫秒,返回字符长度:" + returnStr1M.length());
        } catch (Exception ex) {
            System.out.println("1M String 测试失败!");
        }

        System.out.println("all test done!");
    } 
}


  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协议下的默认序列化方式,推荐使用。

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


作者:huangmr0610
来源链接:https://blog.csdn.net/huangjin0507/article/details/52199669

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/server/41865.html

标签: Dubbo
分享给朋友:

“基于dubbo框架下的RPC通讯协议性能测试” 的相关文章

dubbo监控报错Error creating bean with name 'uriBrokerService'

dubbo监控报错Error creating bean with name 'uriBrokerService'

在jdk1.8下面会出现此错误   解决方法: 1、更换服务器jdk版本。(会影响其他项目环境) 2、修改dubbo-admin tomcat默认jdk版本。 3、修改dubbo-admin项目依赖(dependency)从新打包。 进入h...

Spring Boot Dubbo applications.properties 配置清单

Spring Boot Dubbo applications.properties 配置清单

摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 与其纠结,不如行动学习。Innovate ,And out execute ! 』 本文提纲 一、前言 二、applications.properti...

详解SpringMVC注解方式集成Dubbo

由于最近项目需要SpringMVC集成Dubbo,本文大概记录下详细集成过程: 一、首先项目中Maven引入Jar包 <!-- dubbo相关 --> <dependency> <gr...

Dubbo整合Nacos

Dubbo整合Nacos

Dubbo项目将Nacos作为其注册中心和配置中心 Nacos提供了四个主要功能 服务发现和服务运行状况检查(服务治理):Nacos使服务易于注册自己并通过DNS或HTTP接口发现其他服务。Nacos还提供服务的实时运行状况检查,以防...

SpringCloud采用Dubbo远程调用(SpringCloud Alibaba)

SpringCloud采用Dubbo远程调用(SpringCloud Alibaba)

系统架构:      这里只演示以下组件,其他组件的使用和SpringCloud一样     application-1 :应用1,模拟应用,提供http接口服务。     service-1 :微服务1,模拟微服务,提供dubbo接口服务。     se...

dubbo + nacos

dubbo + nacos 文章目录 dubbo + nacos 一、下载nacos并启动 1.下载地址 2.启动 3.登录...

Dubbo常用标签

Dubbo中常用有7个标签。 分为三个类别:公用标签,服务提供者标签,服务消费者标签 公用标签 <dubbo:application/>和  <dubbo:registry/> A、配置应用信息 <du...

dubbo 启动报 服务注册失败Failed to register dubbo

java.lang.IllegalStateException: Failed to register dubbo://192.168.187.1:20880/com.ghg.dubbo.api.GreetingService?anyhost=true&...

Duboo入门示例(Idea开发环境)

Duboo入门示例(Idea开发环境)

在学习Dubbo分布式框架时的官方入门例子,很有代表性。简单清晰。 有关Dubbo的概念、概述和简单的配置文件,可以看官方文档的简述 会很快对Duboo有个整体的概念。 准备工作: 下载示例,点击这里下载,建议用gi...

dubbo,zookeeper,eureka之间的关系与区别

CAP原则 先来解释下分布式系统中的CAP原则:指的是在一个分布式系统中,C - Consistency(一致性)、 A - Availability(可用性)、P - Partition tolerance(分区容错性),三者不可兼得。 其中,P - Partiti...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。