为何Gatling在单个场景结束后终止模拟而非等待全部完成?
嘿,这个问题我之前帮人排查过好几次,核心是Gatling里throttle和forever()的配合逻辑容易踩坑,我给你拆解清楚:
为什么模拟会在10秒后提前停止?
问题出在throttle的作用逻辑上:它不只是控制请求速率,还会直接定义场景的生命周期时长。
你给scn1配置了holdFor(10 seconds),这意味着Gatling会严格执行这个流量控制阶段10秒——哪怕你在场景里写了forever()循环,一旦10秒的hold阶段结束,Gatling就会认为这个场景的“流量计划”完成了,直接终止scn1的那个用户。
而Gatling的默认行为是:当所有被注入的用户都完成了他们的场景任务后,整个模拟就会终止。虽然scn2的用户还在运行,但scn1的用户提前终止后,会触发整个模拟的提前结束。
怎么解决才能让模拟运行20秒直到所有场景完成?
给你三个实用的解决方案,按需选择:
方案1:给整个模拟设置全局最大时长
最简单的方式是在setUp末尾添加maxDuration(20 seconds),强制让模拟运行满20秒再终止,不管单个场景是否提前结束:
setUp( scn("scn1").inject(atOnceUsers(1)) .throttle( jumpToRps(1), holdFor(10 seconds) ), scn("scn2").inject(atOnceUsers(1)) .throttle(jumpToRps(1), holdFor(20 seconds)) ).protocols(http.baseURLs(url)) .maxDuration(20 seconds) // 这行是关键
方案2:让所有场景的throttle时长对齐最长场景
如果你希望scn1在10秒后停止发请求,但模拟继续等待scn2完成,可以调整scn1的throttle配置,让它的总时长和scn2一致:
scn("scn1").inject(atOnceUsers(1)) .throttle( jumpToRps(1), holdFor(10 seconds), // 前10秒按1RPS发请求 jumpToRps(0), holdFor(10 seconds) // 后10秒停止请求,保持场景存活 )
这样scn1的用户会在20秒后才正式完成,整个模拟就会和scn2一起结束。
方案3:用during()替代forever()+throttle的组合
如果你的需求本来就是让场景在指定时长内循环发请求,其实可以直接用during()来实现,逻辑更清晰,也不会踩throttle的坑:
// 重构场景定义,直接传入运行时长 val scn = (name: String, duration: FiniteDuration) => scenario(name) .during(duration) { exec(request) } setUp( scn("scn1", 10 seconds).inject(atOnceUsers(1)) .throttle(jumpToRps(1)), scn("scn2", 20 seconds).inject(atOnceUsers(1)) .throttle(jumpToRps(1)) ).protocols(http.baseURLs(url))
这种方式下,每个场景会严格在指定时长内循环执行请求,时间到了自动结束,整个模拟会等待所有场景的用户都完成后才终止。
内容的提问来源于stack exchange,提问作者user219882
相关产品推荐
相关产品推荐

