全部产品
云市场

JMeter 压测 Dubbo 服务

更新时间:2019-12-11 20:43:08

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

背景信息

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

前提条件

已安装 JMeter 5.x 版本

步骤一:安装 Dubbo 插件

  1. 下载 Dubbo 插件最新版 JAR 包:jmeter-plugins-dubbo-2.7.3-jar-with-dependencies.jar

  2. 任选一种方式安装 Dubbo 插件。

    • 安装到 JMeter 安装目录的 lib/ext/ 子目录下,再启动 JMeter。启动 JMeter 时自动加载插件。

      1. cp jmeter-plugins-dubbo-2.7.3-jar-with-dependencies.jar "${JMETER_HOME:?}"/lib/ext/
    • 安装到任意目录,再启动 JMeter。

      1. mkdir lib/
      2. cp jmeter-plugins-dubbo-2.7.3-jar-with-dependencies.jar lib/
      3. jmeter -Jsearch_paths=lib/

      说明:lib/ 替换为实际安装路径。

步骤二:编辑 JMeter 脚本

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

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

  2. Dubbo Sample 对话框中配置注册中心地址、服务接口名(Java interface 类名)、方法名、参数类型和参数值等信息。20-dubbo-sample.png

    • 配置注册中心,通常使用 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 表示(有双引号)。结果如下图所示。

    51-result-string.png

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

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

upload script

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

步骤一:导入 JMeter 脚本

  1. 登录 PTS 控制台,在概览页单击 JMeter 原生压测,或者在左侧导航栏选择 创建压测 > JMeter 压测
  2. 发起 JMeter 压测页面,输入场景名称。
  3. 场景配置页签下,单击+上传文件,添加 JMeter 脚本、JAR 文件(即放置在 JMeter 的安装目录…/lib/ext 下的相关 JAR 文件)和其他数据文件。

    注意:上传的同名文件将覆盖之前上传的文件。如需对比文件,可在该文件的操作列,获取 MD5 值,与您本地文件的 MD5 值进行对比,确认文件是否变更。

    上传文件

    使用限制

    • JMX 脚本文件:文件大小不超过 2MB。可上传多个 JMX 脚本文件,但是压测仅能使用一个 JMX 脚本。发起压测前勾选一个使用。
    • JAR 文件:文件大小不超过 10MB。上传之前,请在本地 JMeter 环境调试 JAR 文件,确保调试通过。
    • CSV 和 ZIP 数据文件:文件大小不超过 60 MB。ZIP 内打包的文件必须是以 .csv 结尾的单个文件。

      注意

      • 准备 CSV 文件时,请不要直接修改 .xlsx 文件的后缀。推荐使用 EXCEL、Numbers 等软件导出,程序生成可以使用 Apache commons-csv。
      • 如果 JMX 脚本中关联了数据文件,务必将 CSV Data Set Config 中的 Filename 改为文件名本身,不要带路径(如下图所示)。否则会读取不到数据文件。同理,如果使用了 __CSVRe 函数或者在 JAR 中有指定文件,均需使用文件名。数据文件定义
  4. 如上传了多个 JMX 文件,勾选一个 JMX 文件作为发起该压测场景使用的 JMeter 脚本。
  5. (可选)为 CSV 文件勾选切分文件,可以保证该文件的数据在每个施压机不重复。不勾选该项,每个施压机上使用同一份数据。详见 JMeter 使用 CSV 参数文件
  6. 选择 JMeter 版本 和 Java 版本。
    • JMeter 版本:支持 Apache JMeter 5.0、4.0 和 3.3。
    • Java 版本:支持 Java 8。

步骤二:施压配置

单击施压配置页签,并完成施压配置。施压配置

配置项说明:

  • 压力来源:可选为国内和阿里云 VPC 内网。
    • 选择国内时,发起压测的节点来自全国各地,根据压测的量级来分配对应的节点资源(IP)。
    • 选择阿里云 VPC 内网时,您需要继续选择地域、VPC-ID、安全组、虚拟交换机等信息,压力来源来自您选择的阿里云 VPC 网络施压机。

      注意:

      • 选择地域后,VPC 信息栏下方会显示当前地域下施压源的可用区,确保选择的交换机与施压源在同一可用区内。若您的交换机不在当前地域的可用区内,请单击创建交换机去创建交换机。
      • 确保选择的交换机的空闲 IP 大于等于施压 IP 数。
  • 并发数:指同时发送压测请求的用户数量。并发数受您购买的资源包限制。
  • 指定 IP 数:指定施压引擎的数量,此项为可选项。引擎数增加会带来计费的增加,计费并发 = 引擎数 * 500,且最大引擎数不超过 100。
    • 增加引擎数会带来计费的增加,请关注施压配置页面右侧的预估消耗 VUM 数。
    • 可设置的最大引擎数受资源包限制,具体可参见指定IP数的帮助提示。
  • 压测时长:指压测总时长,包括预热时间。
  • 预热时间:指压测流量到达已配置的并发数的时间。在这个时间内,并发数递增,直到最大并发数。
  • 循环次数:指每个并发的循环执行次数。

    注意循环次数达到设置值,或压测时长达到设置值,压测都会停止。

步骤三(可选):添加监控

如果您有云监控或 ARMS 监控实例,通过添加监控的方式,您可以在压测及报告中便捷地查看相应的监控数据。具体操作及监控数据的查看步骤,参见以下文档:

步骤四:启动压测

完成基本配置之后,在发起 JMeter 压测页面右上角,单击保存去压测,发起压测。稍等数秒,操作页会进入压测态。页面概览如下。 保存去压测

压测过程中,您可以监控压测数据,进行如下操作:

  • 详情页签下,单击单个链路的右侧图标 91788_2,查看其 TPS、成功率、响应时间、流量等实时数据。
  • 选择 JMeter 日志页签,可根据施压机、日志级别、时间范围或施压线程筛选日志,并查看日志详情。
  • 单击页面右上角的查看采样日志,可根据压测 Sampler、响应状态、施压机等筛选日志,查看日志详情。

场景说明:

指标 说明
VUM PTS 的计费单位
压测计时 压测执行的时长,包括预热阶段的时间
场景并发 当前施压的并发值,如果在预热阶段则未达到配置并发,预热结束后即为配置的并发值
场景 TPS(s) 压测周期内,当前场景的平均 TPS 值。TPS = 场景压测期间的全部请求数 / 压测时长。
RT Avg (ms) 压测周期内,所有请求的平均响应时间 (区分成功与失败)
成功率(%) 所有请求的整体请求成功(无断言时 2XX、3XX 的比例;有断言时为断言成功的比例)情况

步骤五:查看压测报告

在压测停止之后,系统会自动收集压测过程中的数据,形成压测报告,展现 JMeter 压测场景和具体指令的压测动态信息。详情请参见JMeter 压测报告

常见问题

保存脚本后测试执行,可看到执行结果显示成功,实际上 Dubbo 服务调用失败了,错误码 code 为 1,如下图所示。怎么处理?

30-invoke-fail.png

查看 jmeter.log 日志可看到报错如下:

  1. Caused by: java.lang.NoSuchMethodException: io.github.hanyong.snip.dubbo_demo.api.Hello.hello()
  2. at java.lang.Class.getMethod(Class.java:1786)
  3. at org.apache.dubbo.common.utils.ReflectUtils.findMethodByMethodSignature(ReflectUtils.java:903)
  4. 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 脚本代码如下:

    1. String respStr = null;
    2. Object resp = null;
    3. try {
    4. respStr = SampleResult.getResponseDataAsString();
    5. resp = com.alibaba.fastjson.JSON.parse(respStr);
    6. } catch (Throwable ex) {
    7. // pass
    8. log.error("error", ex);
    9. }
    10. if (resp == null) {
    11. AssertionResult.setFailure(true);
    12. AssertionResult.setFailureMessage("RESPONSE IS NOT JSON: " + respStr);
    13. } else {
    14. // TODO 根据实际业务校验请求是否成功.
    15. // 简单检查: dubbo 泛化调用失败时, 返回 JSON 包含 code 和 detailMessage 字段.
    16. if (resp instanceof java.util.Map && resp.get("code") != null) {
    17. AssertionResult.setFailure(true);
    18. AssertionResult.setFailureMessage("code=" + resp.get("code") + " detailMessage=" + resp.get("detailMessage"));
    19. } else {
    20. AssertionResult.setFailure(false);
    21. }
    22. }
  2. 再次测试执行,断言检查并提示了报错信息。

    41-invoke-fail.png

  3. Dubbo Sample 对话框中配置每个参数的参数类型和参数值。

更多信息

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