确定 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 秒,如果超过则自动停止测试的主要内容,如果未能解决你的问题,请参考以下文章

如果卡住 90 秒,如何从函数返回? [复制]

最大执行时间超过 30 秒 Laravel 4 错误

10 秒 到 2秒 超简单的Vue项目首屏优化实践

Hbase对时,时差范围的确定

如何确保某些代码每 1 秒运行不超过 1 次?

超过 Instagram API 请求限制