如果需要压测Dubbo服务,则需使用Dubbo插件和JMeter生成JMeter脚本,再将脚本上传到PTS控制台进行压测。本文介绍如何使用JMeter模式压测Dubbo服务。

前提条件

已安装JMeter 5.x版本

背景信息

Dubbo是一款由阿里巴巴开发,后捐献给Apache社区的高性能Java RPC框架,主要用于内部系统之间的服务调用。本案例中使用的Dubbo插件为jmeter-plugins-for-apache-dubbo。使用 泛化调用 执行服务调用。泛化调用的好处是不需要引入服务的API JAR包,只需配置接口名、方法名、参数类型和值,即可调用任意Dubbo服务。具体操作,请参见Dubbo的泛化调用

步骤一:安装Dubbo插件

  1. 下载Dubbo插件最新版JAR包:jmeter-plugins-dubbo-2.7.3-jar-with-dependencies.jar
  2. 任选一种方式安装Dubbo插件。
    • 安装到JMeter安装目录的lib/ext/子目录下,再启动JMeter。启动JMeter时自动加载插件。
      cp jmeter-plugins-dubbo-2.7.3-jar-with-dependencies.jar "${JMETER_HOME:?}"/lib/ext/
    • 安装到任意目录,再启动JMeter。
      mkdir lib/
      cp jmeter-plugins-dubbo-2.7.3-jar-with-dependencies.jar lib/
      jmeter -Jsearch_paths=lib/
      说明lib/ 替换为实际安装路径。

步骤二:编辑JMeter脚本

  1. 打开JMeter,在Test Plan区域右键单击Thread Group,并选择Add > Sample > Dubbo

    您还可以右键单击Thread Group,选择Add > Listener > View Results Tree,添加View Results Tree监听器,方便本地调试测试脚本。

  2. Dubbo Sample对话框中配置注册中心地址、服务接口名(Java interface类名)、方法名、参数类型和参数值等信息。
    pg_dubbo_sample
    • 配置注册中心,通常使用ZooKeeper。
      • Protocol选择为zookeeper,则Address填写ZooKeeper地址。
      • 若生产环境通常包含多个ZooKeeper节点,可填写多个ZooKeeper地址并用英文逗号(,)隔开。
      • 若针对单台服务器进行测试,则将Protocol选择noneAddress填写Dubbo服务地址。
    • 按需调整服务调用配置,如分组Group、版本Version、调用超时时间Timeout(默认为1秒)等。
    • 配置Dubbo服务的完整Java接口类名和方法名。
    • 配置每个参数的参数类型和参数值。
      • 参数类型:基本类型(如boolean, int等)直接写类型名,其他类型写完整Java类名。
      • 参数值:基本类型和字符串直接写参数值,复杂类型用JSON表示填写。

    例如本示例中将Hello方法的参数类型配置为 java.lang.String,参数值配置为阿里云PTS

  3. 测试执行。
    参数值填写原始字符串(没有双引号),Hello方法的返回结果也是字符串类型,使用JSON表示(有双引号)。结果如下图所示。pg_test_result_success

步骤三:阿里云PTS压测Dubbo服务

调试成功后,需要在PTS控制台选择JMeter原生压测模式并上传修改好的脚本和Dubbo插件JAR包进行压测。具体操作,请参见JMeter压测

jmeter dubbo
说明 若使用阿里云VPC内网压测,需确保地域、VPC、安全组3项部署Dubbo服务的信息设置正确,否则将导致网络不通无法压测。施压来源交换机仅用于PTS发起压力,可以与部署Dubbo服务主机在不同地域。

常见问题

保存脚本后测试执行,可看到执行结果显示成功,实际上Dubbo服务调用失败了,错误码code为1,如下图所示。pg_test_result
查看jmeter.log日志可看到报错如下:
 Caused by: java.lang.NoSuchMethodException: io.github.hanyong.snip.dubbo_demo.api.Hello.hello()
         at java.lang.Class.getMethod(Class.java:1786)
         at org.apache.dubbo.common.utils.ReflectUtils.findMethodByMethodSignature(ReflectUtils.java:903)
         at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:72)

报错提示找不到无参数的hello方法。由于脚本中未为hello配置参数,所以报错。

解决方法:

针对此类问题,可以添加断言来检查服务是否成功。泛化调用的结果以JSON形式返回,可以添加断言检查返回的JSON数据,以更准确的校验服务执行是否成功。

  1. 在JMeter的Test Plan区域右键单击Dubbo Sample,并选择Add > Assertions > JSR223 Assertion
    说明 添加断言默认使用groovy脚本。

    若测试服务的返回结果没有code字段,则可以使用返回结果包含code字段则表示调用失败的断言。编写groovy脚本代码如下:

     String respStr = null;
     Object resp = null;
     try {
         respStr = SampleResult.getResponseDataAsString();
         resp = com.alibaba.fastjson.JSON.parse(respStr);
     } catch (Throwable ex) {
         // pass
         log.error("error", ex);
     }
     if (resp == null) {
         AssertionResult.setFailure(true);
         AssertionResult.setFailureMessage("RESPONSE IS NOT JSON: " + respStr);
     } else {
         // TODO根据实际业务校验请求是否成功。
         // 简单检查:Dubbo泛化调用失败时,返回JSON包含code和detailMessage字段。
         if (resp instanceof java.util.Map && resp.get("code") != null) {
             AssertionResult.setFailure(true);
             AssertionResult.setFailureMessage("code=" + resp.get("code") + " detailMessage=" + resp.get("detailMessage"));
         } else {
             AssertionResult.setFailure(false);
         }
     }
  2. 再次测试执行,断言检查并提示了报错信息。
    pg_test_result_false
  3. Dubbo Sample对话框中配置每个参数的参数类型和参数值。

更多信息

使用Dubbo插件遇到的相关问题,请参见Dubbo常见问题