Gatling多用户场景下会话变量被覆盖的解决方法咨询
问题描述
我是Gatling新手,官方文档参考价值有限。当前场景为多用户各自执行独立场景,场景内请求会将响应结果保存为Session变量,供后续请求作为参数使用。但多用户并发运行时,Session变量会被互相覆盖——例如用户#2完成上传后保存的pkey会覆盖用户#1的pkey,导致用户#1后续请求使用错误的pkey。我原本设想通过全局计数器为每个用户的Session变量添加后缀,但不知如何实现,希望获取更优的解决办法。
代码示例
用户定义
user("singleUpload") .behavior { feed(applicationCredentials) .exec(USingleUpload.singleUpload)
场景定义
val singleUpload = exec(RUpload.post) .exec(RShare.get) .exec(RDownload.get) .doIfEquals("${attachmentSingleUpload}", "attachment.jpg") { exec(RThumbnailDownload.get) } .doIfEquals("${attachmentSingleUpload}", "attachment.png") { exec(RThumbnailDownload.get) } .exec(RDelete.delete)
请求定义
val attachment = ("attachment", "${attachmentSingleUpload}") val post = http("RUpload") .post("/attachment/upload/") .queryParam("share", "true") .formUpload("attachment", s"attachments/${attachment._2}") .header("x-api-key", "${apiKey}") .header("x-app-id", "${appId}") .check(status.is(200)) .check(jsonPath("$..pkey").exists.saveAs("pkey"))
val get = http("RShare") .get("/attachment/share") .queryParam("pkey", "${pkey}") .header("x-api-key", "${apiKey}") .header("x-app-id", "${appId}") .check(status.is(200)) .check(jsonPath("$..skey").exists.saveAs("skey"))
解决办法
首先明确:Gatling的每个虚拟用户都拥有完全独立的Session,正常情况下绝不会出现跨用户的变量覆盖。你遇到的问题大概率是代码逻辑误用了全局变量或共享状态,而非Session本身的设计问题。
1. 排查并修正全局变量问题
你的代码中定义了全局的attachment变量,其中attachment._2引用了Session变量${attachmentSingleUpload},但用字符串插值s"attachments/${attachment._2}"时,这个插值是在编译阶段完成的,而非运行时从每个用户的Session中取值。这会导致所有用户使用同一个固定值,进而引发后续的变量覆盖错觉(实际是请求参数错误导致的响应异常)。
修正方案:直接在请求中引用Session变量,去掉全局attachment变量:
val post = http("RUpload") .post("/attachment/upload/") .queryParam("share", "true") // 直接使用Session中的attachmentSingleUpload变量,运行时动态取值 .formUpload("attachment", "attachments/${attachmentSingleUpload}") .header("x-api-key", "${apiKey}") .header("x-app-id", "${appId}") .check(status.is(200)) .check(jsonPath("$..pkey").exists.saveAs("pkey"))
2. 确认Session隔离机制
Gatling的虚拟用户Session完全隔离,每个用户的pkey、skey等变量都存储在自己的Session中,不会被其他用户修改。如果仍出现异常,检查代码中是否使用了全局可变状态(比如用var定义的全局变量存储用户数据),这是唯一可能导致跨用户变量覆盖的原因。
3. 无需全局计数器的优化结论
根本不需要为Session变量添加后缀。只要遵循以下原则,就能彻底解决问题:
- 所有用户专属数据都通过Session传递,用
${变量名}的方式引用 - 避免使用全局可变变量存储用户请求相关的数据
- 确保Feed数据源(比如
applicationCredentials)是每个用户独立消费的,每个用户获取到的apiKey、appId等参数正确且唯一
内容的提问来源于stack exchange,提问作者drrock

