如果需要压测 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 常见问题