【问题标题】:Determine that 95% of all the requests took no longer than 1 second and automatically stop the test if they did确定 95% 的请求所用时间不超过 1 秒,如果超过则自动停止测试
【发布时间】:2021-12-04 14:22:33
【问题描述】:

我想通过不断增加负载来运行压力测试,直到响应时间变得不可接受。我需要检查的条件是 95% 的请求所用时间不超过 1 秒。

  1. 我可以在运行时动态确定吗?如果可以,如何确定?
  2. 达到此条件后如何停止测试?

我查看了 AutoStop Listener 插件,但它似乎没有我检查这种情况所需的东西。

【问题讨论】:

    标签: performance jmeter listener jmeter-5.0 stress-testing


    【解决方案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 argumentjmeter.save.saveservice.autoflush JMeter Property 设置为true
    【解决方案2】:

    如果一个采样器超过 1 秒,则停止测试,请使用 Duration Assertion 和 1000 毫秒

    测试每个响应是否在给定的时间内收到

    如果断言失败,您可以停止测试:

    Thread group 中选择Action to be taken after a sampler error 下的停止测试/立即停止测试

    确定发生采样器错误时会发生什么,无论是因为样本本身失败还是断言失败

    【讨论】:

    • 谢谢,但我有兴趣以某种方式在运行时评估所有采样器,以便我可以确定其中 95% 的采样器在 1 秒以上或以下,并根据该结果停止或继续考试。您提出的解决方案似乎不适合我的需要。
    【解决方案3】:

    更新了答案以修复代码中的错误并改进日志记录

    这可能是另一种解决方案。

    1. 初始化属性。 添加SetUp Thread Group。将JSR223 Sampler 添加到设置线程组。 然后添加以下代码来初始化属性。
    props.put("total_requests","0")
    props.put("total_requests_exceeding_limit","0")
    
    1. 在顶层添加JSR223 Post Processor

    这将确保该元素应用于测试计划中的所有采样器

    1. 将以下参数添加到 JSR223 后处理器
    ${__P(stop_test_exceeding_percentile_error,true)}  ${__P(percentage_limit,95)} ${__P(response_time_limit_in_seconds,1)}
    
    
    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()
    }
    
    
    1. 脚本将在加速期间忽略采样器。此时应在脚本中设置加速期
    2. 可以通过属性/参数配置响应时间阈值、响应百分比限制等
    3. 在预定义数量的请求后从加速时间开始检查百分比,以避免在第一个响应时间大于配置值时立即停止测试。
    4. 可以进一步改进脚本以等待响应百分比超过限制的预定义时间段。
    5. 需要处理同步问题。您可以使用线程间通信插件来确保不同线程不会读取相同的值。

    【讨论】:

    • 你写的太棒了!我尝试了您的解决方案,但它似乎没有按预期工作。在 GUI 模式下,我创建了一个包含 2000 个线程、2 小时脚本持续时间、整个脚本持续时间的 2 小时启动时间和随机控制器下的 2 个采样器来测试脚本功能的场景。日志中打印的值与汇总报告中显示的值之间存在差异。汇总报告显示 95% 的线超过 1000 毫秒,而日志中的值甚至没有接近 95%。
    • 让我检查一下并回复您。
    • 我们需要在加速阶段忽略结果。此外,请求计数以开始检查移动到嵌套 if 块的百分比。改进了日志记录以在当前请求未超过限制时显示 total_requests_exceeding_limit 和 total_requests_exceeding_limit。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2021-08-25
    • 2020-01-14
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多