Gatling阶梯增长、脉冲压力和波浪模型三种相对复杂场景,这些模型是为了超越基础的固定并发用户数或线性增长用户数,更科学、更贴近真实业务场景或更极端的方式压测系统,测试在不同压力模式下的性能表现和性能瓶颈。
负载模型是时间(Time)到并发用户数(Active Users)的函数
Gatling负载模型通过injection定义。设计复杂模型是组合或自定义这些注入,构造特定的“时间-用户数”函数曲线。
模型一:阶梯增长模型
模型模拟用户量分阶段稳步上升的场景,如产品推广期、节假日预热。允许系统在每级压力下稳定运行一段时间,观察性能表现是否平稳,从而找到性能临界点。
每级阶梯包含“用户增长”和“压力保持”两个阶段。需要合理设置阶梯高度(每级新增用户数)和宽度(每级持续时间)。
Gatling示例:
scala
import scala.concurrent.duration._
setUp(
scn.inject(
// 第一阶梯:立即注入10用户,持续30秒
incrementUsersPerSec(10)
.times(1) // 阶梯次数
.eachLevelLasting(30 seconds) // 每个阶梯持续时间
.startingFrom(0), // 起始负载
// 第二阶梯:在上一级基础上,再增加15用户/秒,即达到25用户/秒,再持续30秒
incrementUsersPerSec(15)
.times(1)
.eachLevelLasting(30 seconds)
.startingFrom(10), // 注意起始点是上一级的终点
// 第三阶梯:再增加20用户/秒,达到45用户/秒,持续1分钟
incrementUsersPerSec(20)
.times(1)
.eachLevelLasting(1 minute)
.startingFrom(25)
).protocols(httpProtocol)
)
主要参数:
times(): 定义该阶梯重复次数。设为1,表示单一阶梯。
eachLevelLasting(): 定义该阶梯的稳定压力保持时间,观察系统稳定性的窗口。
startingFrom(): 必须精确设置为上一阶梯结束时的总用户速率,保证阶梯的连续性。
分析观察每个阶梯保持阶段的响应时间曲线和错误率。如果某个阶梯保持期间响应时间持续攀升或错误率增加,说明系统在此压力下已经无法稳定运行。
模型二:脉冲压力模型
模型模拟瞬时高并发冲击,如秒杀活动、缓存击穿、定时任务触发。目的是测试系统的弹性伸缩能力、瞬时处理能力及资源回收速度。
在极短时间内注入大量用户,压力陡升陡降,形成“脉冲”。需关注脉冲的高度(并发峰值)、宽度(冲击持续时间)和间隔。
Gatling实现示例:
scala
setUp(
scn.inject(
// 第一个脉冲:0秒时,瞬间注入100用户
atOnceUsers(100),
// 等待系统恢复60秒
nothingFor(60 seconds),
// 第二个,更强的脉冲:0秒时,瞬间注入200用户
atOnceUsers(200),
// 等待系统恢复
nothingFor(120 seconds),
// 第三个脉冲:模拟更真实的秒杀,在2秒内分批注入300用户(比瞬时更柔和但压力仍大)
rampUsersPerSec(10).to(300).during(2 seconds),
nothingFor(60 seconds)
).protocols(httpProtocol)
)
变体设计(分批脉冲):使用rampUsers或rampUsersPerSec在极短时间(如2-5秒)内快速达到峰值,比atOnceUsers更贴近某些真实场景(用户并非完全同时点击)。
结果分析:
尖峰时刻:脉冲期间的TPS(每秒事务数)最大值、响应时间峰值、错误率。
恢复过程:脉冲结束后,响应时间、系统负载(如CPU)恢复到正常水平所需的时间。恢复过慢可能预示内存泄漏或连接池耗尽。
资源监控:结合监控工具,观察CPU、内存、线程池、数据库连接在脉冲前后的变化。
模型三:波浪(波动)模型
模型模拟具有周期性波动特点的业务负载,如日间活跃高峰、夜间批处理低谷,或社交媒体的波浪式热点。测试系统在周期性变化压力下的稳定。
构造一个类似正弦波或锯齿波的负载曲线。需要定义波浪的周期、波峰/波谷的负载值、以及波浪的个数。
Gatling实现:Gatling未内置标准“波浪”函数,但可通过组合rampUsersPerSec和constantUsersPerSec分段逼近,或使用自定义加载配置文件来实现。
方法一:分段线性逼近(简单波浪)
scala
setUp(
scn.inject(
// 第一个波浪周期:60秒
// 上升沿:20秒内从10用户/秒线性增加到50用户/秒
rampUsersPerSec(10).to(50).during(20 seconds),
// 峰值保持:10秒
constantUsersPerSec(50).during(10 seconds),
// 下降沿:20秒内从50用户/秒线性减少到10用户/秒
rampUsersPerSec(50).to(10).during(20 seconds),
// 谷值保持:10秒
constantUsersPerSec(10).during(10 seconds),
// 开始第二个波浪周期...
rampUsersPerSec(10).to(60).during(20 seconds) // 第二个波浪峰值可以更高
).protocols(httpProtocol)
)
方法二:使用自定义函数(高级也更平滑)
通过实现 InjectionProfile 接口,可以用数学函数(如正弦函数)精确计算每一秒应注入的用户数,实现平滑波浪。方法代码较复杂,但能产生更真实的负载曲线。
结果分析:
滞后和同步:系统响应时间曲线是否和负载波浪曲线同步变化?是否存在明显滞后?
周期稳定:比较多个波浪周期内,相同相位点(如每个波峰)的响应时间和TPS。性能是否稳定,还是会随周期数增加而逐步恶化?
平均性能:在整个波浪式负载下,系统整体平均响应时间和吞吐量是否满足服务等级协议要求。
混合模型
负载模型往往是混合的混合模型。如:阶梯增长作为基线,叠加周期性的日常波浪,并在特定时刻出现脉冲。
建议:
在执行任何复杂负载测试前,保证有全面的应用、系统、中间件和数据库监控。没有监控的压测是盲人摸象。
先运行基础负载(如固定并发)建立性能基线,再逐步增加复杂性。
配合使用真实的数据(参数化)和合理的用户思考时间,避免产生不切实际的高吞吐假象。
在场景中设置断言,并使用Gatling HTML报告结合自定义监控图表进行分析。注意response time distribution(响应时间分布)和requests/sec(每秒请求数)图表和负载曲线的关联。