确定 95% 的请求所用时间不超过 1 秒,如果超过则自动停止测试
Posted
技术标签:
【中文标题】确定 95% 的请求所用时间不超过 1 秒,如果超过则自动停止测试【英文标题】:Determine that 95% of all the requests took no longer than 1 second and automatically stop the test if they did 【发布时间】:2021-12-04 14:22:33 【问题描述】:我想通过不断增加负载来运行压力测试,直到响应时间变得不可接受。我需要检查的条件是 95% 的请求所用时间不超过 1 秒。
-
我可以在运行时动态确定吗?如果可以,如何确定?
达到此条件后如何停止测试?
我查看了 AutoStop Listener 插件,但它似乎没有我检查这种情况所需的东西。
【问题讨论】:
【参考方案1】:最简单的是Taurus 框架,它提供灵活而强大的Pass/Fail Criteria 子系统
示例 Taurus YAML 文件:
execution:
- scenario: simple
scenarios:
simple:
script: /path/to/your/test.jmx
reporting:
- module: passfail
criteria:
- p95.0>1s, stop as failed
如果所有请求的 95% 超过 1 秒,Taurus 将停止测试并返回非零值exit status code,这是一种脚本/CI 友好的方法。
在 JMeter 中也可以使用一些 JSR223 Scripting,您可以定期读取 .jtl 结果文件、计算百分位数、检查预期值等。
【讨论】:
谢谢迪米特里!我一定会看看 Taurus,看看它是如何工作的,以及它如何帮助我。对于另一种解决方案,“定期读取 .jtl 结果文件”,如果 JMeter 在脚本运行时仍在写入文件,这些结果是否仍然可以获取? 是的,为什么不呢。数据会定期刷新到文件中,如果您想始终获得“新鲜”结果,您可以通过user.properties file or-J
command-line argument 将jmeter.save.saveservice.autoflush
JMeter Property 设置为true
【参考方案2】:
如果一个采样器超过 1 秒,则停止测试,请使用 Duration Assertion 和 1000 毫秒
测试每个响应是否在给定的时间内收到
如果断言失败,您可以停止测试:
在Thread group 中选择Action to be taken after a sampler error
下的停止测试/立即停止测试
确定发生采样器错误时会发生什么,无论是因为样本本身失败还是断言失败
【讨论】:
谢谢,但我有兴趣以某种方式在运行时评估所有采样器,以便我可以确定其中 95% 的采样器在 1 秒以上或以下,并根据该结果停止或继续考试。您提出的解决方案似乎不适合我的需要。【参考方案3】:更新了答案以修复代码中的错误并改进日志记录
这可能是另一种解决方案。
-
初始化属性。
添加SetUp Thread Group。将JSR223 Sampler 添加到设置线程组。
然后添加以下代码来初始化属性。
props.put("total_requests","0")
props.put("total_requests_exceeding_limit","0")
-
在顶层添加JSR223 Post Processor。
这将确保该元素应用于测试计划中的所有采样器
-
将以下参数添加到 JSR223 后处理器
$__P(stop_test_exceeding_percentile_error,true) $__P(percentage_limit,95) $__P(response_time_limit_in_seconds,1)
-
将以下脚本添加到 JSR223 后处理器。
long rampupTime=60000
long requestCountToStartChecking=50
long startTimeInMillis=vars.get("TESTSTART.MS").toLong()
long currentTimeInMillis = new Date().getTime()
long currentTestDurationInMillis=currentTimeInMillis-startTimeInMillis
log.info("currentTestDurationInMillis $currentTestDurationInMillis")
if(args[0].toBoolean() && currentTestDurationInMillis> rampupTime )
def total_requests_exceeding_limit=0
def percentageOfRequestExceedingLimit=0
int percentile_limit=args[1].toInteger()
int response_time_limit_in_seconds=args[2].toInteger()
long response_time_limit_in_milliseconds=response_time_limit_in_seconds*1000
def totalRequests = props.get("total_requests").toInteger() + 1
props.put("total_requests",totalRequests.toString())
if(prev.getTime() > response_time_limit_in_milliseconds)
total_requests_exceeding_limit= props.get("total_requests_exceeding_limit").toInteger() + 1
percentageOfRequestExceedingLimit = ((total_requests_exceeding_limit/totalRequests)* 100).round()
if (percentageOfRequestExceedingLimit> percentile_limit && totalRequests>requestCountToStartChecking)
log.info("Requests execeeding $response_time_limit_in_milliseconds has reached $percentageOfRequestExceedingLimit")
log.info("Stopping the test")
prev.setStopTest(true)
log.info("Stopped the test")
props.put("total_requests_exceeding_limit",total_requests_exceeding_limit.toString())
else
total_requests_exceeding_limit= props.get("total_requests_exceeding_limit").toInteger()
percentageOfRequestExceedingLimit = ( (total_requests_exceeding_limit/totalRequests)* 100).round()
log.info("totalRequests $totalRequests total_requests_exceeding_limit $total_requests_exceeding_limit percentageOfRequestExceedingLimit $percentageOfRequestExceedingLimit ")
else
prev.setIgnore()
-
脚本将在加速期间忽略采样器。此时应在脚本中设置加速期
可以通过属性/参数配置响应时间阈值、响应百分比限制等
在预定义数量的请求后从加速时间开始检查百分比,以避免在第一个响应时间大于配置值时立即停止测试。
可以进一步改进脚本以等待响应百分比超过限制的预定义时间段。
需要处理同步问题。您可以使用线程间通信插件来确保不同线程不会读取相同的值。
【讨论】:
你写的太棒了!我尝试了您的解决方案,但它似乎没有按预期工作。在 GUI 模式下,我创建了一个包含 2000 个线程、2 小时脚本持续时间、整个脚本持续时间的 2 小时启动时间和随机控制器下的 2 个采样器来测试脚本功能的场景。日志中打印的值与汇总报告中显示的值之间存在差异。汇总报告显示 95% 的线超过 1000 毫秒,而日志中的值甚至没有接近 95%。 让我检查一下并回复您。 我们需要在加速阶段忽略结果。此外,请求计数以开始检查移动到嵌套 if 块的百分比。改进了日志记录以在当前请求未超过限制时显示 total_requests_exceeding_limit 和 total_requests_exceeding_limit。以上是关于确定 95% 的请求所用时间不超过 1 秒,如果超过则自动停止测试的主要内容,如果未能解决你的问题,请参考以下文章