name: gatling-load-testing description: 用于Gatling模拟开发、负载测试执行和性能分析的专家技能。使用Scala DSL编写Gatling模拟,配置注入配置文件和馈送器,定义断言,分析HTML报告,并与Gatling Enterprise集成。 allowed-tools: Bash(*) Read Write Edit Glob Grep WebFetch metadata: author: babysitter-sdk version: “1.0.0” category: load-testing backlog-id: SK-006
Gatling负载测试
您是 gatling-load-testing - 一个专门用于Gatling负载测试开发和性能分析的技能。此技能利用Gatling强大的Scala DSL,提供构建全面负载测试套件的专家能力。
概述
此技能支持AI驱动的负载测试操作,包括:
- 使用Scala DSL编写Gatling模拟
- 配置注入配置文件(逐步增加、稳定、峰值、压力)
- 设计用于测试数据管理的馈送器
- 定义断言和响应时间百分位数
- 分析Gatling HTML报告
- 会话处理和关联
- Gatling Enterprise集成
先决条件
- Java 11+ 或 Java 17+(推荐)
- Scala 2.13+ 或 Gatling Bundle
- Maven或Gradle用于构建管理
- 可选:Gatling Enterprise许可证用于高级功能
能力
1. Gatling模拟开发
编写全面的Gatling模拟:
package simulations
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class ApiLoadSimulation extends Simulation {
// HTTP协议配置
val httpProtocol = http
.baseUrl("https://api.example.com")
.acceptHeader("application/json")
.contentTypeHeader("application/json")
.userAgentHeader("Gatling/LoadTest")
.shareConnections
.maxConnectionsPerHost(10)
// 测试数据馈送器
val userFeeder = csv("users.csv").circular
val searchFeeder = jsonFile("searches.json").random
// 请求链
val authenticate = exec(
http("身份验证")
.post("/auth/login")
.body(StringBody("""{"username":"${username}","password":"${password}"}"""))
.check(
status.is(200),
jsonPath("$.token").saveAs("authToken"),
responseTimeInMillis.lte(500)
)
)
val searchProducts = exec(
http("搜索产品")
.get("/products/search")
.queryParam("q", "${searchTerm}")
.header("Authorization", "Bearer ${authToken}")
.check(
status.is(200),
jsonPath("$.results[*]").count.gte(1),
responseTimeInMillis.lte(1000)
)
)
val viewProduct = exec(
http("查看产品")
.get("/products/${productId}")
.header("Authorization", "Bearer ${authToken}")
.check(
status.is(200),
jsonPath("$.id").is("${productId}"),
responseTimeInMillis.lte(300)
)
)
// 场景定义
val userJourney = scenario("用户旅程")
.feed(userFeeder)
.exec(authenticate)
.pause(1, 3)
.feed(searchFeeder)
.exec(searchProducts)
.pause(500.milliseconds, 2.seconds)
.repeat(3) {
exec(viewProduct)
.pause(1, 2)
}
// 负载配置文件
setUp(
userJourney.inject(
rampUsers(100).during(60.seconds),
constantUsersPerSec(50).during(300.seconds),
rampUsersPerSec(50).to(100).during(120.seconds)
)
).protocols(httpProtocol)
.assertions(
global.responseTime.percentile3.lt(1000),
global.successfulRequests.percent.gte(99),
forAll.failedRequests.percent.lt(1)
)
}
2. 注入配置文件
配置各种负载模式:
// 逐步增加负载模式
setUp(
scenario.inject(
rampUsers(1000).during(10.minutes)
)
)
// 带预热阶段的恒定负载
setUp(
scenario.inject(
nothingFor(5.seconds),
atOnceUsers(10),
rampUsers(100).during(1.minute),
constantUsersPerSec(50).during(5.minutes)
)
)
// 压力测试模式
setUp(
scenario.inject(
incrementUsersPerSec(10)
.times(5)
.eachLevelLasting(2.minutes)
.separatedByRampsLasting(30.seconds)
.startingFrom(10)
)
)
// 峰值测试模式
setUp(
scenario.inject(
constantUsersPerSec(20).during(2.minutes),
stressPeakUsers(500).during(30.seconds),
constantUsersPerSec(20).during(2.minutes)
)
)
// 浸泡/耐力测试
setUp(
scenario.inject(
rampUsersPerSec(1).to(30).during(5.minutes),
constantUsersPerSec(30).during(4.hours)
)
)
3. 馈送器和测试数据
有效管理测试数据:
// CSV馈送器
val csvFeeder = csv("data/users.csv").circular
// JSON馈送器
val jsonFeeder = jsonFile("data/products.json").random
// JDBC馈送器
val jdbcFeeder = jdbcFeeder(
"jdbc:postgresql://localhost:5432/testdb",
"postgres", "password",
"SELECT id, email FROM users WHERE active = true"
)
// 自定义馈送器
val customFeeder = Iterator.continually(Map(
"orderId" -> java.util.UUID.randomUUID().toString,
"timestamp" -> System.currentTimeMillis(),
"amount" -> (100 + scala.util.Random.nextInt(900))
))
// 带转换的批量馈送器
val transformedFeeder = csv("data/raw.csv")
.transform { case (key, value) =>
if (key == "amount") (value.toDouble * 1.1).toString else value
}
.batch(100)
.random
4. 会话处理和关联
处理动态值和会话状态:
// 提取和重用值
exec(
http("获取CSRF令牌")
.get("/form")
.check(
css("input[name='csrf']", "value").saveAs("csrfToken")
)
)
.exec(
http("提交表单")
.post("/submit")
.formParam("csrf", "${csrfToken}")
.formParam("data", "${userData}")
)
// JSON路径提取
exec(
http("获取订单")
.get("/orders/${orderId}")
.check(
jsonPath("$.items[*].id").findAll.saveAs("itemIds"),
jsonPath("$.total").saveAs("orderTotal")
)
)
.foreach("${itemIds}", "itemId") {
exec(
http("获取商品详情")
.get("/items/${itemId}")
)
}
// 条件执行
exec(session => {
if (session("userType").as[String] == "premium") {
session.set("rateLimit", 1000)
} else {
session.set("rateLimit", 100)
}
})
.doIf("${userType}", "premium") {
exec(premiumFeatures)
}
5. 断言和阈值
定义全面的断言:
setUp(scenario.inject(/* ... */))
.protocols(httpProtocol)
.assertions(
// 全局断言
global.responseTime.max.lt(5000),
global.responseTime.mean.lt(500),
global.responseTime.percentile1.lt(200), // P50
global.responseTime.percentile2.lt(500), // P75
global.responseTime.percentile3.lt(1000), // P95
global.responseTime.percentile4.lt(2000), // P99
// 成功率断言
global.successfulRequests.percent.gte(99.5),
global.failedRequests.count.lt(100),
// 特定请求断言
details("身份验证").responseTime.percentile3.lt(500),
details("搜索产品").successfulRequests.percent.gte(99),
// 吞吐量断言
global.requestsPerSec.gte(1000)
)
6. 报告分析
分析Gatling HTML报告:
// 报告配置
.protocols(httpProtocol)
.pauses(constantPauses)
// 自定义报告命名
System.setProperty("gatling.core.outputDirectoryBaseName", "api-load-test")
System.setProperty("gatling.charting.indicators.lowerBound", "800")
System.setProperty("gatling.charting.indicators.higherBound", "1200")
关键指标分析:
- 响应时间分布:P50、P75、P95、P99
- 随时间变化的活跃用户:并发级别
- 每秒请求数:吞吐量趋势
- 随时间变化的响应时间百分位数:性能退化
- 错误:失败模式和错误代码
MCP服务器集成
此技能可以利用以下MCP服务器:
| 服务器 | 描述 | 使用场景 |
|---|---|---|
| locust-mcp | 负载测试MCP | 替代负载测试执行 |
| playwright-mcp | 浏览器自动化 | 基于UI的负载测试场景 |
最佳实践
模拟设计
- 真实场景 - 模拟实际用户行为
- 思考时间 - 在操作之间包含真实的暂停
- 数据变化 - 使用多样化的测试数据
- 会话隔离 - 避免用户之间的共享状态
性能
- 连接池 - 使用
shareConnections - 馈送器优化 - 使用适当的馈送器策略
- 资源管理 - 监控Gatling JVM资源
- 分布式执行 - 跨多个注入器扩展
断言
- 多个百分位数 - 不要仅依赖平均值
- 错误阈值 - 设置可接受的失败率
- 基线比较 - 与已知的良好运行进行比较
- 业务SLO - 与实际SLO对齐
流程集成
此技能与以下流程集成:
load-testing-framework-setup.js- 初始Gatling设置load-test-execution.js- 测试执行和编排stress-testing-analysis.js- 压力测试场景设计
输出格式
执行操作时,提供结构化输出:
{
"operation": "run-simulation",
"status": "completed",
"simulation": {
"name": "ApiLoadSimulation",
"duration": "300s",
"totalUsers": 5000
},
"results": {
"requestCount": 150000,
"errorCount": 45,
"errorRate": "0.03%",
"responseTime": {
"mean": 245,
"p50": 180,
"p75": 320,
"p95": 890,
"p99": 1450,
"max": 4200
},
"throughput": 500.5
},
"assertions": {
"passed": 8,
"failed": 0
},
"reportPath": "target/gatling/apisimulation-20260124/index.html"
}
错误处理
常见问题
| 错误 | 原因 | 解决方案 |
|---|---|---|
Connection refused |
目标不可用 | 验证目标URL和网络 |
Connection timeout |
目标缓慢 | 增加超时时间,检查目标容量 |
OOM on injector |
用户过多 | 增加堆内存,分布负载 |
Feeder exhausted |
测试数据不足 | 使用 .circular 或 .random |
Session value not found |
缺少提取 | 验证检查表达式 |
约束
- 在测试前验证目标系统可以处理负载
- 与运维团队协调进行类似生产的测试
- 在测试期间监控注入器资源
- 使用适当的测试数据(非生产数据)
- 在分布式设置中考虑网络延迟