Dubbo 服务性能压测(with JMeter)
Dubbo 服务性能压测(with JMeter)
最近在做Dubbo服务与Prometheus的监控集成,为了测试监控组件对Dubbo RPC 调用的性能影响,就需要对添加前后做性能测试。虽然之前给组内搭建了统一的Dubbo 服务测试平台,但是并不是用于性能测试。
说起性能测试,大家可能会有很多选择,wrk、JMeter等等。但是相信大家一般都是用于测试HTTP接口,对于这种Dubbo框架的这种私有协议 dubbo://
,这些工具没有提供原生的支持。第一个想法就是通过Dubbo 的泛化调用来自己写一个客户端,然后统计测试结果,但是这样一是不优雅,二是有可能重复造轮子,浪费时间。经过一番google之后,果然得到了想要的答案。
今天要介绍的,就是一款来自于Dubbo 社区的JMeter 插件 jmeter-plugins-for-apache-dubbo ,使用这款插件,就可以让JMeter 对Dubbo 服务的测试。
本文假定读者使用jmeter进行过简单的性能测试,并且安装了 jmeter
Step 1:安装Dubbo 插件
-
克隆项目:
git clone https://github.com/thubbo/jmeter-plugins-for-apache-dubbo.git
-
打包项目,构建 JMeter 插件:
mvn clean install
或者你可以直接跳过上面两步,下载 jmeter-plugins-dubbo-2.7.3-jar-with-dependencies.jar
-
将插件添加到
${JMETER_HOME}\lib\ext
(安装完之后重启jmeter)
Step 2:编写JMeter 脚本
1、创建Dubbo Sample
在 【测试计划】 区域右键单击 【线程组】 ,并选择 【添加】 > 【取样器】 > Dubbo Sample
在 Dubbo Sample 对话框中配置注册中心地址、服务接口名(Java interface 类名)、方法名、参数类型和参数值等信息。
配置步骤如下:
-
配置注册中心,通常使用 ZooKeeper。(配置完成之后,点击上面
Get Provider List
按钮获取注册的服务列表)-
若
Protocol 选择为
zookeeper
,则
Address 填写 ZooKeeper 地址。 -
若生产环境通常包含多个 ZooKeeper 节点,可填写多个 ZooKeeper 地址并用英文逗号(,)隔开。
-
若针对单台服务器进行测试,则将
Protocol 选择
none
,
Address 填写 Dubbo 服务地址。
-
-
按需调整服务调用配置,如分组 Group、版本 Version、调用超时时间 Timeout(默认为 1 秒)等。
-
配置 Dubbo 服务的完整 Java 接口类名和方法名。
-
配置每个参数的参数类型和参数值。
-
参数类型:基本类型(如 boolean, int 等)直接写类型名,其他类型写 完整 Java 类名 (注意哦,是完整类名)。
-
参数值:基本类型和字符串直接写参数值, 复杂类型用 JSON 表示填写 。
-
为了方便本地调试测试脚本,可以添加结构监听器,右键单击 【线程组】 ,选择 【添加】 > 【监听器】 > 【察看结果树】 ,添加 察看结果树 监听器。
Step 3:测试执行
在**【线程组】 上右击,点击 【验证】**,执行单次请求,来测试工具与服务的联通性。
在**【察看结果树】 选项卡中可以看到 【响应数据】**返回如预期,说明可以正常执行 Dubbo 调用了。
Step 4:添加断言
有时候你会看到执行结果显示成功,但是实际上Dubbo 服务调用失败了,或者业务处理失败,返回结果中包含了错误码。比如下面两张图。
RPC 调用失败。
业务处理失败。
解决方法:
针对此类问题,可以添加断言来检查服务是否成功。泛化调用的结果以 JSON 形式返回,可以添加断言检查返回的 JSON 数据,以更准确的校验服务执行是否成功。
具体步骤就是,在 jmeter的 【测试计划】 区域右键单击 Dubbo Sample ,并选择 【添加】 > 【断言】 > 【JSR233 Assertion】 。
这里我给出我的groovy 测试脚本代码:
String respStr = null; Map resp = null; try { respStr = SampleResult.getResponseDataAsString(); resp = (Map) 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 { // 简单检查: dubbo 泛化调用失败时, 返回 JSON 包含 code 和 detailMessage 字段. if (resp.get("code") != null && resp.get("detailMessage")) { AssertionResult.setFailure(true); AssertionResult.setFailureMessage("rpc exception, code=" + resp.get("code") + " detailMessage=" + resp.get("detailMessage")); } else if(!"SUCCESS".equals((String)resp.get("code"))) { // TODO 根据你自己的实际业务,校验请求是否成功. AssertionResult.setFailure(true); AssertionResult.setFailureMessage("请求失败, code=" + resp.get("code")); } else { AssertionResult.setFailure(false); } }
让我们看看,添加了断言之后,再验证的结果。
可以看到,断言起到了业务校验的作用,并且提示了报错信息。
至于如何编写脚本的其他部分,就要考虑你要模拟的场景来设置了,属于如何使用JMeter的部分,所以这里就不过多叙述。
更多常见问题
关于该插件的更多常见问题,请参考该插件的github wiki中的 FAQ 。