Gatling压测时如何设置所有虚拟用户共用的可动态更新全局变量
问题根因
你之前的方案不生效是因为Gatling DSL属于构建期逻辑:所有在请求定义里直接传入的固定参数,都会在Simulation初始化阶段就被解析固化,不会在每次请求运行时重新读取。你代码里.header("LIMIT", GLOBAL_LIMIT)在压测启动时就把当时的"49"存成了请求头的固定值,后续修改GLOBAL_LIMIT变量自然不会对已经构建完成的请求逻辑生效。
实现方案
需要同时满足两个要求:
- 全局共享变量要保证多线程可见性,避免并发读写的一致性问题
- 请求头的取值改为动态表达式,每次请求发送前实时读取最新的全局值
单节点压测可以直接用JDK自带的原子类实现,修改后的代码如下:
import java.util.concurrent.atomic.AtomicReference import io.gatling.core.Predef._ import io.gatling.http.Predef._ import scala.concurrent.duration._ class MySimulation extends Simulation { // 用原子引用存储全局共享值,保证多线程可见性 private val GLOBAL_LIMIT = new AtomicReference[String]("49") def myRequest: HttpRequestBuilder = http("My request") .get("/") // 传入动态表达式,每次请求运行时实时读取当前最新值 .header("LIMIT", _ => GLOBAL_LIMIT.get()) .check(status.is(200)) def myScenario: ScenarioBuilder = scenario("Poll") .forever( pace(1.second) .exec(myRequest) ) def changeLimit(limit: String): ScenarioBuilder = scenario("Change limit") .exec(session => { GLOBAL_LIMIT.set(limit) session }) setUp( myScenario.inject( constantUsersPerSec(1) during 30.seconds ), changeLimit("59").inject( nothingFor(10.seconds), atOnceUsers(1) ) ).protocols(http.baseUrl("http://localhost:8081")) }
注意事项
如果是使用Gatling Enterprise的分布式集群压测,上述基于JVM内原子类的方案只能在单节点生效,多节点同步全局值需要额外引入分布式缓存组件来实现,单节点压测无需额外调整。
内容的提问来源于stack exchange,提问作者Lukasz Wyporek
相关产品推荐
相关产品推荐

