当前位置: 首页 > 测试知识 > 基于Scala DSL的Gatling脚本开发_从零开始构建首个负载测试模型
基于Scala DSL的Gatling脚本开发_从零开始构建首个负载测试模型
2025-12-02 作者cwb 浏览次数18

构建基于Scala DSL的Gatling负载测试脚本是一个系统工程,涉及环境搭建、脚本设计、模拟执行和结果分析。


主要概念架构

在编写第一行代码前,需理解两个重要的概念:

Gatling架构:Gatling采用异步、非阻塞的架构。每个虚拟用户是一个Actor,通过消息传递驱动,单个机器即可模拟数千并发用户,资源消耗远低于传统线程阻塞式工具(如JMeter)。

Scala DSL:DSL(领域特定语言)让测试脚本声明式且可读。你描述的是“用户会做什么”,而非“如何逐步执行”。主要结构按照 场景 -> 注入策略 -> 模拟 的逻辑链。


环境配置

安装Java:确保已安装JDK 8或11(LTS版本),并设置JAVA_HOME。


bash

java -version


构建工具(二选一):

sbt(推荐):Scala原生构建工具,生态兼容性最佳。创建 build.sbt:


scala

name := "gatling-project"

version := "1.0"

scalaVersion := "2.13.12" // Gatling 3.9+推荐

enablePlugins(GatlingPlugin)

libraryDependencies += "io.gatling.highcharts" % "gatling-charts-highcharts" % "3.9.5" % "test,it"

libraryDependencies += "io.gatling" % "gatling-test-framework" % "3.9.5" % "test,it"


Maven:在pom.xml中配置gatling-maven-plugin。

IDE配置:使用IntelliJ IDEA安装Scala插件,保证能识别DSL语法和提供自动补全。

负载测试模型

以一个API登录并查询数据的流程为例


第1层:定义协议

定义所有请求共用的基础测试配置。


scala

import io.gatling.core.Predef._

import io.gatling.http.Predef._

import scala.concurrent.duration._


class BasicSimulation extends Simulation {


  // 1. 定义HTTP协议配置

  val httpProtocol = http

    .baseUrl("https://your-api.com") // 基础URL

    .acceptHeader("application/json")

    .contentTypeHeader("application/json")

    .userAgentHeader("Gatling/3.9")

    .disableCaching // 对于负载测试,通常禁用缓存

    .shareConnections // 共享连接池,提升效率


专业提示:disableCaching和shareConnections是性能测试的配置,保证测试施压更贴近真实场景。


第2层:定义场景行为(Scenario)

场景是用户行为的模拟,由一系列链式调用组成。


scala

  // 2. 定义场景(用户行为流)

  val scn = scenario("用户登录并查询数据流程")

    // 第一步:登录,提取并保存token

    .exec(

      http("用户登录")

        .post("/api/auth/login")

        .body(StringBody("""{"username":"test_user","password":"pass123"}"""))

        .check( // 断言和提取器

          status.is(200),

          jsonPath("$.data.token").saveAs("authToken") // 关键:提取token供后续使用

        )

    )

    .pause(1.second) // 模拟用户思考时间


    // 第二步:携带token查询数据

    .exec(

      http("查询个人资料")

        .get("/api/user/profile")

        .header("Authorization", "Bearer ${authToken}") // 使用已保存的变量

        .check(

          status.is(200),

          jsonPath("$.data.userId").saveAs("userId")

        )

    )

    .pause(2.seconds)


    // 第三步:基于上一步结果进行更复杂查询

    .exec(

      http("查询订单列表")

        .get("/api/orders")

        .queryParam("userId", "${userId}")

        .check(

          status.is(200),

          // 验证响应体数组非空

          jsonPath("$.data.orders").exists

        )

    )



check:Gatling断言和提取。除了状态码,jsonPath、css、regex等提取器用于关联-这是测试有状态API(如登录)的必备技能。

saveAs:将提取的值存入会话(Session) 变量,变量作用域为当前虚拟用户的生命周期。

pause:必须加入思考时间,来模拟真实用户操作间隔。


第3层:设计负载模型

这是将“用户行为”转化为“并发压力”。


scala

  // 3. 设计负载模型(压力注入策略)

  setUp(

    scn.inject(

      // 阶段一:用2分钟线性增长到20个并发用户

      rampUsersPerSec(0) to 20 during (2.minutes),

      // 阶段二:保持20并发用户持续运行5分钟

      constantUsersPerSec(20) during (5.minutes),

      // 阶段三:在1分钟内线性增长到100并发用户的峰值

      rampUsersPerSec(20) to 100 during (1.minute),

      // 阶段四:保持峰值压力2分钟

      constantUsersPerSec(100) during (2.minutes)

      // 阶段五:可在此后添加阶梯下降等更复杂模型

    ).protocols(httpProtocol)

  ).maxDuration(10.minutes) // 全局测试超时时间

}



负载模型分析:

rampUsersPerSec:斜坡式增长,平滑加压,避免对系统产生“启动冲击”,常用于预热阶段。

constantUsersPerSec:恒定压力,用于稳定性测试和容量验证。

组合使用:真实的负载模型应是多阶段混合的,来模拟业务高峰、日常运行等不同场景。


优化实践

数据驱动测试:使用Feeder分离测试数据和逻辑。


scala

val userFeeder = csv("data/users.csv").circular // 循环使用数据

val scn = scenario("DataDriven")

  .feed(userFeeder)

  .exec(http("Login")

    .post("/login")

    .body(StringBody("""{"username":"${username}","password":"${password}"}"""))

  )


断言和性能指标验证:在setUp层添加全局断言。


scala

setUp(scn.inject(...))

  .assertions(

    // 全局95%响应时间必须小于500ms

    global.responseTime.percentile(95).lt(500),

    // 所有请求成功率必须大于99.5%

    global.successfulRequests.percent.gt(99.5)

  )



报告结果分析:

执行:sbt gatling:test 或通过Gatling官方打包的recorder录制。

生成的HTML报告位于target/gatling/<simulation-name>-<timestamp>/,关注:

响应时间分布图:观察中位数、95分位数。

活跃用户数和请求数/秒图表:验证负载模型是否按预期施加。

错误统计:定位失败请求的根本原因。


避坑指南

避免脚本硬编码:URL、断言阈值等应配置化。

处理关联:对于动态值(如CSRF Token),使用正则或JSONPath精确提取,避免过度泛化。

理解虚拟用户生命周期:每个用户独立执行Scenario,Session变量不共享。

监控施压机:使用top或nmon监控CPU、内存和网络。


学习路径

官方资源:Gatling官方文档是必读手册,特别是关于Checks和Session API的部分。研究Gatling FrontLine(企业级监控)、集成InfluxDB+Grafana进行实时看板展示,以及使用Gatling的Java API进行定制化的测试逻辑开发。

文章标签: 软件负载测试 负载测试 压力测试 并发压力测试 软件测试 第三方软件测试
咨询软件测试