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

如何在Gatling的Scala多仿真文件间共享Session变量?

Gatling跨仿真文件复用OrderId的解决方案

核心结论

Gatling中通过session => session.setAll()设置的Session完全无法跨仿真文件访问——每个仿真文件运行时拥有独立的JVM上下文,Session是单个虚拟用户的私有临时数据,仿真之间完全隔离,不存在跨文件共享的机制。

可行解决方案

1. 预生成订单数据并通过CSV复用(优化你尝试过的方案)

  • 步骤1:单独生成订单数据
    写一个独立的Scala程序或Gatling单场景仿真,仅调用一次订单API生成OrderId和OrderUri,将结果写入CSV文件,格式如下:
    orderId,orderUri
    O12345,/api/orders/O12345
    
  • 步骤2:在目标仿真中读取CSV
    在需要复用数据的仿真文件中,使用Gatling的Feeder读取CSV,确保所有虚拟用户复用预生成的数据:
    val orderFeeder = csv("pre_generated_orders.csv").circular // 循环复用,适合允许重复使用订单的场景
    // 若订单只能用一次,改用.queue
    
    val scn = scenario("Reuse Order")
      .feed(orderFeeder)
      .exec(http("Use Order")
        .get("${orderUri}")
        .header("Order-Id", "${orderId}"))
    
  • 适用场景:分布式压测、需要多组订单数据、数据需持久化的场景。

2. Scala全局单例对象存储(仅适合本地单机压测)

  • 步骤1:创建全局单例
    在项目中定义一个线程安全的单例对象,用于存储生成的订单数据:
    object SharedOrderData {
      @volatile private var _orderId: String = ""
      @volatile private var _orderUri: String = ""
    
      def setOrderData(id: String, uri: String): Unit = {
        _orderId = id
        _orderUri = uri
      }
    
      def orderId: String = _orderId
      def orderUri: String = _orderUri
    }
    
  • 步骤2:第一个仿真写入数据
    在生成订单的仿真中,确保仅执行一次API调用并写入单例:
    class GenerateOrderSimulation extends Simulation {
      val scn = scenario("Generate Order")
        .exec(http("Create Order")
          .post("/api/orders")
          .check(jsonPath("$.orderId").saveAs("orderId"),
                 jsonPath("$.orderUri").saveAs("orderUri")))
        .exec(session => {
          SharedOrderData.setOrderData(session("orderId").as[String], session("orderUri").as[String])
          session
        })
        .oncePerScenario // 确保整个仿真仅执行一次订单生成逻辑
    
      setUp(scn.inject(atOnceUsers(1)))
    }
    
  • 步骤3:第二个仿真读取数据
    在复用数据的仿真中,直接从单例读取并设置到Session:
    class ReuseOrderSimulation extends Simulation {
      val scn = scenario("Reuse Order")
        .exec(session => session.setAll("orderId" -> SharedOrderData.orderId, "orderUri" -> SharedOrderData.orderUri))
        .exec(http("Use Order")
          .get("${orderUri}")
          .header("Order-Id", "${orderId}"))
    
      setUp(scn.inject(rampUsers(100) during (10 seconds)))
    }
    
  • 注意:此方案仅适用于本地单机压测,分布式集群环境下单例对象无法跨节点共享。

3. 仿真启动前预生成数据(用before钩子)

在需要复用数据的仿真中,重写before方法,在仿真启动前调用一次订单API生成数据,避免依赖其他仿真:

class ReuseOrderSimulation extends Simulation {
  private var orderId: String = _
  private var orderUri: String = _

  override def before {
    // 用普通HTTP客户端(如Apache HttpClient)调用订单API,不要用Gatling DSL(before是仿真启动前的初始化逻辑)
    val httpClient = HttpClientBuilder.create().build()
    val request = new HttpPost("http://your-api-host/api/orders")
    val response = httpClient.execute(request)
    val responseBody = EntityUtils.toString(response.getEntity)
    // 解析JSON获取数据(可使用Jackson等库)
    orderId = // 解析responseBody得到orderId
    orderUri = // 解析responseBody得到orderUri
  }

  val scn = scenario("Reuse Order")
    .exec(session => session.setAll("orderId" -> orderId, "orderUri" -> orderUri))
    .exec(http("Use Order")
      .get("${orderUri}")
      .header("Order-Id", "${orderId}"))

  setUp(scn.inject(atOnceUsers(50)))
}
  • 适用场景:无需依赖其他仿真,单独运行即可复用订单数据的本地压测场景。

方案选型建议

  • 分布式压测:优先选CSV文件复用,将CSV放在共享存储目录供所有节点读取。
  • 本地单机压测:选全局单例或before钩子,实现简单且性能损耗低。
  • 订单不可重复使用:用CSV的.queue模式,确保每个订单仅被一个虚拟用户使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:12:21