Gatling的Simulation类定义了“谁”(虚拟用户)、“以何种行为”(场景)、“按什么节奏”(注入策略)去访问“哪个系统”(协议配置)。标准结构包含四个部分,setUp、inject和protocols是用于组装并启动负载测试的主要方法。
Simulation类
Simulation类按照以下结构,完成场景定义和负载模型的绑定:
scala
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class YourSimulation extends Simulation { // 继承Simulation类
// 第一部分:定义HTTP协议配置 (如基础URL、公共头信息)[citation:9]
val httpProtocol = http
.baseUrl("http://yourtestsystem.zmtests.com")
.acceptHeader("application/json")
// 第二部分:定义用户场景(即单个用户的行为链)
val scn = scenario("您的业务场景")
.exec(http("请求名称")
.get("/api/endpoint")
.check(status.is(200)))
.pause(1 second)
// 第三部分(主要):使用setUp、inject、protocols组装并启动测试
setUp(
scn.inject(...) // 在此处定义如何注入用户
).protocols(httpProtocol) // 在此处绑定协议配置
}
主要方法
setUp方法
setUp方法是测试的启动器,它接受一个或多个绑定了注入策略的场景作为参数。它的主要作用是将定义好的用户行为场景和负载模型关联起来,形成一个可执行的测试计划。
inject方法
inject方法应用于场景对象(如scn),用于定义虚拟用户以何种方式和节奏被注入到测试中。支持两种负载模型:
开放模型:关注用户到达速率。如,constantUsersPerSec(20) during (10 minutes)表示每秒尝试启动20个用户,无论系统当前响应如何。
封闭模型:关注系统内的并发用户数。如,constantConcurrentUsers(50) during (10 minutes)能精确保证系统中始终有50个活跃用户。
可以通过组合多种注入步骤来模拟复杂的压力曲线:
scala
scn.inject(
nothingFor(4 seconds), // 开始时暂停4秒[citation:5]
rampUsers(10) during (5 seconds), // 5秒内逐步启动10个用户
constantUsersPerSec(20) during (1 minute), // 保持每秒20个用户的到达率1分钟
rampConcurrentUsers(10) to 100 during (10 minutes) // 10分钟内将并发用户从10逐步增加到100[citation:8]
)
protocols 方法
protocols方法在setUp之后调用,用于将一个或多个协议配置(通常是HTTP协议)绑定到整个测试设置上。这意味着所有在该setUp中注入的用户,都将使用这里指定的协议配置(如基础URL、超时设置、头信息等)来执行测试场景。
应用技巧
在复杂测试场景中,这三个方法可以通过链式调用组合出强大的测试方法:
分阶段压力测试:在inject中组合多种模式,模拟热身、增压、峰谷等真实场景。
精确时长控制:结合inject中的持续注入和setUp后的.maxDuration(10 minutes),保证测试严格运行指定时间。
设置性能断言:在setUp链的最后使用.assertions,为响应时间、成功率等设置验收标准。
完整示例
下面的代码展示了如何将概念整合到一个模拟真实用户访问模式的测试中:
scala
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class AdvancedExampleSimulation extends Simulation {
val httpProtocol = http
.baseUrl("https://api.zmtests.com")
.shareConnections // 共享连接池[citation:6]
.disableAutoReferer // 根据需求禁用自动Referer头[citation:6]
// 定义一个会循环执行的复杂场景[citation:8]
val userJourney = scenario("完整用户旅程")
.forever() {
exec(http("访问首页").get("/"))
.pause(2, 5) // 随机等待,模拟思考时间[citation:8]
.exec(http("查询数据").get("/api/data"))
.pause(1)
.exec(http("提交订单").post("/api/order")
.body(StringBody("""{"item": "product"}""")).asJson[citation:6]
.check(jsonPath("$.orderId").saveAs("id")))
.pause(3)
}
// 组合使用主要方法:setUp装配场景,inject定义分阶段负载,protocols绑定配置
setUp(
userJourney.inject(
// 阶段1: 30秒内从0逐步增加到10个并发用户(热身)
rampConcurrentUsers(0) to 10 during (30 seconds)[citation:8],
// 阶段2: 保持10个并发用户2分钟(稳定期)
constantConcurrentUsers(10) during (2 minutes)[citation:8],
// 阶段3: 1分钟内从10个并发用户增加到50个(压力期)
rampConcurrentUsers(10) to 50 during (1 minute)[citation:8],
// 阶段4: 保持50个并发用户3分钟(峰值期)
constantConcurrentUsers(50) during (3 minutes)[citation:8]
)
).protocols(httpProtocol)
.maxDuration(7 minutes) // 总测试时长不超过7分钟[citation:8]
.assertions( // 设置性能通过标准
global.responseTime.max.lt(2000), // 全局最大响应时间小于2秒
global.failedRequests.percent.lt(1.0) // 请求失败率低于1%[citation:8]
)
}
setUp是装配器,inject是节奏控制器,protocols是环境设定器。这三者是分工和协作的。