You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gatling跨场景存储并复用返回值问题求助

解决Gatling跨场景共享存储值的问题

你的问题核心在于两点:全局变量的线程不安全问题,以及Feeder提前初始化导致无法获取后续生成的ID。咱们一步步拆解解决方案:

原代码的问题分析

  1. 线程安全隐患:你用了普通的var l: List[String]来存ID,Gatling是多线程运行场景的,多个用户同时修改这个列表会导致数据混乱,甚至抛出并发修改异常。
  2. Feeder初始化时机:ids = l.map(...)是在场景启动前就执行了,此时l是空列表,所以这个Feeder的迭代器根本没有数据,Get场景自然拿不到ID,报"id not found"。
  3. 另外注意:代码里的中文引号(“id”)要改成英文双引号("id"),不然会编译报错。

解决方案:用线程安全队列+动态Feeder

我们可以用线程安全的队列来存储ID,同时自定义一个动态Feeder,实时从队列中获取最新的ID,完美解决跨场景共享的问题:

import java.util.concurrent.atomic.AtomicReference
import scala.collection.mutable.Queue

// 用AtomicReference包裹线程安全的队列,支持多生产者(Install场景)和多消费者(Get场景)
val sharedIdQueue = new AtomicReference[Queue[String]](Queue.empty)

val install = scenario("Install")
  .during(Configuration.duration) {
    group("installTest") {
      exec(testChain.installApplication())
        .exec(session => {
          // 从当前Session中取出ID并修剪
          val newId = session("id").as[String].trim
          // 原子性地将ID加入队列,避免并发问题
          sharedIdQueue.updateAndGet(queue => queue.enqueue(newId))
          session
        })
    }
  }

val get = scenario("Get")
  .during(Configuration.duration) {
    group("getTest") {
      // 自定义动态Feeder:每次获取Feed时,从队列中取出ID
      feed(() => {
        var targetId: Option[String] = None
        // 如果队列为空,短暂等待后重试,避免空转消耗资源
        while (targetId.isEmpty) {
          // 原子性地取出队列头部的ID,并更新队列(移除已取出的元素)
          targetId = sharedIdQueue.getAndUpdate(queue => queue.drop(1)).headOption
          if (targetId.isEmpty) Thread.sleep(100)
        }
        // 返回Feeder需要的Map格式
        Map("id" -> targetId.get)
      })
      .exec(session => {
        println(session("id").as[String])
        session
      })
    }
  }

setUp(
  warmupScenario.inject(constantConcurrentUsers(1) during(1))
    .andThen(install.inject(nothingFor(10 seconds), rampUsers(Configuration.users) during (Configuration.ramp seconds)))
    .andThen(get.inject(nothingFor(Configuration.duration seconds), rampUsers(Configuration.users) during (Configuration.ramp seconds)))
)
.assertions(details("installTest").successfulRequests.percent.gte(Configuration.passPercentage))
.protocols(HTTP_PROTOCOL)

方案说明

  • 线程安全存储:AtomicReference[Queue[String]]保证了多线程环境下,Install场景的多个用户可以安全地往队列里添加ID,Get场景的用户也能安全地取出ID。
  • 动态Feeder:自定义的Feeder是一个函数(() => Map[String, String]),每次调用时都会实时从队列中获取最新的ID,彻底解决了Feeder提前初始化的问题。如果队列为空,会短暂等待后重试,确保能拿到ID再继续执行。
  • 避免空转:加入Thread.sleep(100)是为了避免队列为空时,Feeder循环空转消耗CPU资源,你可以根据实际场景调整等待时间。

内容的提问来源于stack exchange,提问作者santosh jk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 02:44:08