Gatling的group和rendezVous(集合点)是两个用于组织测试思路和控制并发行为的高级功能。解决的问题方面完全不同:group用于报告的组织和聚合,提升结果的可读性;rendezVous用于虚拟用户(VU)的同步,制造精确的并发压力。
一、group:思路分组和报告聚合
group的重要作用是将一系列相关的操作打包,并在最后报告中将这些操作的标准聚合计算,作为一个独立的业务事务呈现。不改变虚拟用户脚本的执行思路和时序,只改变报告的生成方式。
1. 设计
业务语义化:将低级的HTTP请求(如/api/login, /api/addToCart)提升为高级的业务操作(如“用户登录流程”、“添加购物车流程”),使性能报告对业务方和产品经理更友好。
标准聚合:计算被分组的所有请求的累计响应时间、请求数、成功率等,让你能直观考虑某个完整业务流程的性能。
结构清晰:支持嵌套分组,可以创建出 业务流程 -> 子流程 -> 具体操作 的清晰报告树。
2. 工作原理示例
当一个操作被包裹在group块中时,Gatling会在内部为该组分配一个唯一的途径名。执行时,组内每个请求的标准除了会计入自身的名称下,还会向上聚合到所属的组途径中。
scala
import io.gatling.core.Predef._
import io.gatling.http.Predef._
class GroupExampleSimulation extends Simulation {
val httpProtocol = http.baseUrl("https://your-api.com")
val scn = scenario("分组示例情形")
// 第一层分组:用户认证流程
.group("01_Auth_Process") {
exec(
http("POST /login")
.post("/login")
.body(StringBody("""{"username":"test","password":"pass"}"""))
.check(status.is(200))
)
}
.pause(1)
// 第二层分组:购物流程(内嵌子分组)
.group("02_Shopping_Process") {
// 子分组:浏览商品
.group("02a_Browse") {
exec(http("GET /products").get("/products"))
.exec(http("GET /product/1").get("/product/1"))
}
// 子分组:下单
.group("02b_Checkout") {
exec(
http("POST /order")
.post("/order")
.body(StringBody("""{"productId":1}"""))
)
}
}
setUp(
scn.inject(atOnceUsers(1))
).protocols(httpProtocol)
}
3. 报告中的体现
执行上述脚本后,在Gatling的HTML报告 “详细信息 -> 按组统计” 页面:
点击02_Shopping_Process,你看到的是内部所有请求(/products, /product/1, /order)标准的总和。这是分析复杂业务流程整体性能的重点。
二、rendezVous:虚拟用户同步(集合点)
rendezVous用于强制让所有到达该点的虚拟用户等待,直到达到指定数量后,再同时释放它们,以制造一个瞬时的高并发请求。它是模拟“秒杀”、“抢购”等情形的重点工具。
1. 重要设计意图
制造突发并发:普通的递增注入(如rampUsers)用户是陆续到达的,而rendezVous可以制造出在同一毫秒内有大量请求同时冲击系统的极端情形。
测试系统峰值处理能力和临界点:用于发现系统在瞬时高压下的性能拐点、资源耗尽、锁竞争或队列溢出等问题。
2. 工作原理参数
rendezVous 接受一个整型参数 users,表示需要集合的用户数。
scala
// 语法
.rendezVous(users: Int)
重要特性:
作用域:rendezVous是scenario级别的。不同scenario中的rendezVous互不影响。
一次性:一个集合点在被触发释放后,对于后续到达的虚拟用户将不再起作用(除非该用户再次执行到该集合点,在循环中可能发生)。
等待超时:Gatling没有为rendezVous设置默认等待超时。如果始终等不到足够的用户,未释放的用户将永久阻塞。这是必须在情形设计中考虑的风险点。
3. 示例
基础方式:模拟1000人同时点击“提交订单”。
scala
val scn = scenario("秒杀情形")
.exec(...) // 登录、浏览等前置操作
.pause(2)
.rendezVous(1000) // 集合1000个用户
.exec( // 集合点之后的操作会并发执行
http("提交秒杀请求")
.post("/seckill")
)
循环集合方式:模拟多轮抢购。
scala
val scn = scenario("多轮抢购")
.repeat(3) { // 进行3轮
exec(...) // 每轮开始前可能有的操作
.rendezVous(500) // 每轮都集合500人
.exec(http("抢购").get("/buy"))
.pause(5) // 轮次间隔
}
和分组结合:在报告中清晰地标识出并发操作阶段。
scala
val scn = scenario("组合使用")
.group("完整秒杀事务") {
exec(http("进入页面").get("/seckill_page"))
.rendezVous(2000) // 集合点放在分组内
.exec(http("点击抢购").post("/seckill_submit")) // 这个请求将并发执行
}