第三章-性能测试之JMeter自定义-后置处理器二开

性能系列文章目录

欢迎大家关注「海拉鲁知识大陆」 多交流不迷路

第三章-性能测试之JMeter自定义-后置处理器二开

一、背景

基于使用JMeter脚本的做自动化测试过程中,我们测试脚本也需要健壮性的考虑,重试机制是一种容错设计模式,当操作失败时(例如网络请求超时、数据库连接失败等),增加合理的重试机制可以提高我们脚本的可用性、稳定性和真实性。

一个脚本的重试机制通常包含以下几个关键要素:

  • 重试触发条件:何种异常或错误状态下需要进行重试
  • 重试次数:最大允许重试的次数
  • 重试间隔:两次重试之间的时间间隔

方式1:

二、原有组件实现重试

基于Jmeter脚本原有的组件的情况,我们整理大体思路如下:

  1. 初始化标志位状态、参数化最大次数(方便修改)
  2. 使用While控制器判断标志位状态实现重试请求
  3. 使用JSR223后置处理程序重试断言(包括是否需要解密等)、重试最大次数等逻辑实现控制赋值标志位状态
    在这里插入图片描述
    预处理器代码实现如下
import groovy.json.JsonSlurper;
import cn.hrfax.securityNew.GatewayAesUtils;

String samplerName = ctx.getCurrentSampler().getName();
String threadNum = ctx.getThreadNum();
String response_data = prev.getResponseDataAsString();
String code = prev.getResponseCode();
String result1 = "\"msg\":\"成功\""; //为正常请求响应中请求成功标签,需要根据每个请求响应不同进行修改
int maxRetries = Integer.parseInt(vars.get("maxRetries")); // 最大重试次数
int currentRetry = Integer.parseInt(vars.get("retryCount")); // 获取当前重试次数
boolean isFailed = false;

// 条件1: 响应码非200
if (!code.equals("200")) {
 isFailed = true;
 vars.put("status","pending");
}
// 条件2: 响应格式不正确,有没有data和sign
if (!isFailed) {
 def responseObj = new JsonSlurper().parseText(response_data);
 if (responseObj.containsKey("data") && responseObj.containsKey("sign")){
 isFailed = false;
 }else{
 isFailed = true;
 vars.put("status","pending");
 }
}
// 条件3: 断言内容失败
if (!isFailed) {
 String dec_public_key = vars.get("DEC_PUBILC_KEY");
 def decryptData = GatewayAesUtils.decrypt(response_data,dec_public_key);// 解密响应
 if(!decryptData.contains(result1)){
 isFailed = true;
 vars.put("status","pending");
 } else {
 // 断言成功,重置计数器
 isFailed = false;
 vars.put("status","active");
 vars.put("retryCount", "0");
 } 
}
// 若失败且未达最大重试次数
if (isFailed && currentRetry < maxRetries) {
 currentRetry++;
 vars.put("retryCount", String.valueOf(currentRetry)); // 更新计数器
 vars.put("status","pending"); 
 log.info("Retry重试 # " + currentRetry + " for failed request"+" ${samplerName}");
} else {
// 重试成功或已达上限,重置计数器
 vars.put("status","active");
 vars.put("retryCount", "0");
}

那么以上 针对于单个接口进行重试控制貌似问题不大,当我们存在需要连续且多个接口需要重试,第1个While脚本最后处理志标准位赋值为成功,初始化是依托于取样器的运行,导致不能进入第2个While而跳过接口,虽然可以使用2个不同的标志位进行交替While判断使用来避免、但稳定性中全流程脚本接口需要大量重试,处理起来真是苦不堪而且脚本看起来冗余又繁重,本着性能脚本也需要简洁和优雅原则,急需二开一个后置处理器来完成实现请求重试机制。

那么它来了!

方式2:

三、后置处理器二开实现重试

在这里插入图片描述

  • 重试条件-参数说明
Max Number of Retries: 最大重试次数
Response Part: 响应断言选择部分,支持Response code, data, headers, message可选
Error Pattern: 断言内容,如果响应断言部分匹配到断言内容,则不需要重试
  • 解密设置-参数说明
Data Decrypt: 选择ResponseData是否解密
Decrypt Pub: 解密使用的Pubilc Key
  • 延时设置-参数说明
Pause (milliseconds): 在重试采样器之前暂停多长时间
Backoff: 可修改每次重试后的初始暂停,以减慢速度避免过载
Jitter Factor (positive decimal):时间抖动因子,添加到暂停中的随机变化量(默认值:0,即抖动关闭)。例如,值为0.1时,计算出的延迟将加上暂停的10%。
Respect "Retry-After": 是否遵从响应头“Retry After”字段,在重试之前是否遵从HTTP响应标头“Retry After”(默认值:False)。

将jmeter-retrier-1.0放至Jmeter安装目录中\lib\ext目录下重启即可使用

1.重试使用效果如下(后置重试处理器是重启sampler覆盖修改原来SampleResult的方式,即在结果树和聚合报告中是展示是最新一次请求的结果,可在打印日志可查看重试情况)
在这里插入图片描述
2.无需重试以及响应解密效果如下
在这里插入图片描述

四、自定义后置处理器-二次开发核心代码说明:

开发环境准备,引入核心jar,打包使用等这里不再赘述见自定义开发函数篇,直接进入核心代码部分
在这里插入图片描述
1.选择一个包并编写三个文件:

   [组件名称].java-----RetryPostProcessor.java
   [组件名称]BeanInfo.java-----RetryPostProcessorBeanInfo.java
   [组件名称]Resources.properties-----RetryPostProcessorResources.properties

2.RetryPostProcessor.java必须实现TestBean接口。
3.RetryPostProcessorBeanInfo.BeanInfo.java应该扩展org.apache.jmeter.testbeans.BeanInfoSupport
4.实现具体处理逻辑。

代码实现情况如下:

  • [组件名称]BeanInfo.java 表示PostProcessor的界面,如本例中的RetryPostProcessorBeanInfo;

创建一个零参数构造函数,我们在其中调用super(RetryPostProcessor.class); 其中

/**为每个属性设置属性
 * NOT_UNDEFINED
 * 该属性不会保留为null。
 * DEFAULT
 * 如果NOT_UNDEFINED为true ,则必须给出默认值。
 * NOT_EXPRESSION
 * 如果为true ,则不会为函数解析该值。
 * NOT_OTHER
 * 这不是一个自由形式的输入字段——必须提供一个值列表。
 * TAGS
 * 使用String[]作为值,这将设置可接受值的预定义列表,JMeter 将创建一个下拉选择。
 */

在这里插入图片描述

  • [组件名称].java 表示插件的处理逻辑,如本例中的RetryPostProcessor.java;

这块将扩展AbstractTestElement并实现PostProcessor,(不需要迭代的不用实现)TestBean是一个标记接口,因此没有要实现的方法。扩展AbstractTestElement将使我们的组件成为测试计划中的后置处理器。重写process()方法实现我们重试逻辑
其中封装必要的实现方法,重试条件、暂停间隔时间、取样器结果修改、ResponsePart枚举、BackoffType枚举等
在这里插入图片描述

  • [组件名称]Resources.properties表示界面显示的文字,如本例中RetryPostProcessorResources.properties,其中:
/**定义界面所有字符串资源
 * displayName
 * 这将为将出现在菜单中的元素提供一个名称。
 * json_data.displayName
 * 我们创建了一个名为csv_data的属性分组,因此我们必须为分组提供一个标签
 * filename.displayName
 * 文件名输入元素的标签。
 * filename.shortDescription(当鼠标定位到GUI输入框名称提示性文字)
 * 类似工具提示的帮助文本简介。
 * variableNames.displayName
 * 变量名称输入元素的标签。
 * variableNames.shortDescription
 * variableNames输入元素的工具提示。
 */

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林克爱塞尔达

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值