
简介Gatling 3.0.0 是一款面向现代 Web 应用的性能测试工具适合开发者与测试工程师用来模拟高并发用户负载验证系统在压力下的响应时间、吞吐量与资源利用率。其脚本基于 Scala 的 DSL 语法编写可读性与可维护性较强并支持场景录制回放、检查点设置与执行速率配置便于构建贴近真实的用户行为模型。资源包共 114 个文件以 97 个 jar 依赖库为主体辅以 6 个 scala 脚本、3 个 conf 配置、2 个 bat 与 2 个 sh 启动脚本以及 csv 数据样例和 xml 等文件压缩包约 57.17MB开箱即可运行测试并生成图表化报告。目前已有 237 人学习下载。借助 Highcharts 图表可直观查看每秒请求数、平均响应时间与百分位分布配合命令行工具与持续集成能力帮助读者快速定位性能瓶颈、沉淀可复用的压测脚本与排错思路。1. Gatling 3.0.0 拆包一份能直接跑起来的压测工具包压测这件事最怕的不是压不出问题而是压出来的数字自己都不信。用 JMeter 图形界面点几下就能发压但脚本一多、并发一高GUI 本身就成了瓶颈报告还得靠插件拼。Gatling 3.0.0 这个版本走的是另一条路Scala DSL 写脚本、异步非阻塞模型发压、压完直接吐一份带百分位和响应分布图的 HTML 报告。它解决的核心问题就一个——让压测脚本像代码一样进版本库、可 review、可 CI 跑而不是躺在某个人的桌面文件夹里。适合谁已经会用命令行、愿意花半天学一套 DSL 的后端和测试从业者只想点鼠标出个并发数的这套东西前期投入不划算。下面按「它是什么 → 怎么装怎么跑 → 脚本怎么写 → 坑在哪 → 怎么验证」的顺序拆。2. 环境落地从解压到第一条压测命令Gatling 3.0.0 是绿色包解压即用但它对 JDK 版本有硬要求——这个版本跑在 Scala 2.12 上需要 JDK 8JDK 11 及以上会在启动阶段直接抛错。很多人第一次翻车就翻在这里机器上默认是 JDK 17gatling.sh一执行就报Unsupported class file major version还以为是包坏了。2.1 目录结构与启动脚本解压后先别急着跑花两分钟认清目录后面改配置、放脚本、找报告都靠它。路径作用是否常改bin/gatling.shLinux/macOS 启动入口否bin/gatling.batWindows 启动入口否conf/gatling.conf全局配置编码、报告、数据写入偶尔conf/logback.xml日志级别排错时改user-files/simulations/放 Scala 压测脚本高频user-files/resources/放请求体、CSV 参数文件高频user-files/bodies/放二进制请求体按需results/每次运行的报告输出只读启动脚本干的事其实很简单拼 classpath、找user-files/simulations下的编译产物、调io.gatling.app.Gatling主类。所以脚本放错目录、或者文件名和类名对不上都会表现为「找不到 simulation」。2.2 JDK 与内存参数先确认 JDK 版本再决定要不要动内存。Gatling 默认堆不大几千并发下容易 GC 抖动压出来的 P99 会虚高。# 确认 JDK 版本必须是 8 java -version # 临时指定 JDK 8 启动机器上多版本共存时 export JAVA_HOME/path/to/jdk8 export PATH$JAVA_HOME/bin:$PATH # 调大堆和直接内存再启动 JAVA_OPTS-Xms2g -Xmx2g -XX:UseG1GC ./bin/gatling.sh-Xms和-Xmx设成一样避免运行期堆伸缩带来的停顿UseG1GC在 3.0.0 这个年代已经是压测场景的稳妥选择。直接内存不用手动设Gatling 的 Netty 底层会按需申请但如果机器内存紧张记得留出余量——压测机自己 OOM 了报告里的错误率就没有参考价值。启动后如果看到交互式菜单列出可选 simulation说明环境通了如果直接报错退出先看results/同级有没有生成日志再看conf/logback.xml把级别调到 DEBUG 重跑一次。2.3 用官方示例验证链路包里自带几个示例 simulation第一次跑建议先跑自带的确认「启动 → 发压 → 出报告」整条链路没问题再换自己的脚本。# 交互式启动按提示选择 BasicSimulation ./bin/gatling.sh # 或者直接指定 simulation 类名适合 CI 里非交互执行 ./bin/gatling.sh -s computerdatabase.BasicSimulation跑完终端会打印报告路径形如results/basicsimulation-时间戳/index.html。打开看三块全局的请求数/成功率、响应时间分位数50/75/95/99、以及按请求拆分的响应时间分布。这一步的意义是建立基线——后面自己写的脚本跑出来数字离谱时你能判断是脚本问题还是环境问题。常见做法是把这个示例报告留一份作为「环境正常」的对照。3. 脚本编写Scala DSL 的四个核心构件Gatling 脚本本质是一个继承Simulation的 Scala 类里面用链式 DSL 描述「谁、在多久内、发什么请求、怎么断言」。3.0.0 的 DSL 和后续版本有差异网上抄来的新版本写法直接扔进来会编译不过这点要有心理准备。3.1 场景、注入模型与协议配置一个最小可用的脚本包含三部分HTTP 协议配置、场景定义、注入策略。注入模型决定了并发曲线长什么样选错了压出来的数字没有业务意义。import io.gatling.core.Predef._ import io.gatling.http.Predef._ import scala.concurrent.duration._ class OrderSimulation extends Simulation { // 协议层baseUrl、公共头、超时 val httpConf http .baseURL(http://127.0.0.1:8080) .acceptHeader(application/json) .connection(keep-alive) .requestTimeout(10.seconds) // 场景一个虚拟用户的行为链 val scn scenario(下单链路) .exec(http(首页).get(/)) .pause(1) .exec(http(查商品).get(/api/item/1).check(status.is(200))) // 注入3.0.0 用 setUp 注入步骤 setUp( scn.inject( rampUsers(50) over (30.seconds), // 30 秒内线性加到 50 用户 constantUsersPerSec(5) during (60.seconds) // 之后稳定每秒 5 个新用户 ) ).protocols(httpConf) .assertions(global.responseTime.percentile3.lt(800)) }rampUsers是「总用户数在时间窗内爬坡」constantUsersPerSec是「每秒新增用户速率恒定」两者语义不同别混用。percentile3对应 P95断言写在这里压测不达标时进程会以非零码退出CI 里能直接卡住。requestTimeout一定要设默认值偏长遇到慢接口会把整个压测拖成「假低并发」。3.2 检查点、参数化与请求体只发请求不校验等于只测了「服务没挂」。检查点check负责从响应里提取值、做断言参数化负责让每个虚拟用户发不同的数据。import io.gatling.core.Predef._ import io.gatling.http.Predef._ class LoginSimulation extends Simulation { val httpConf http.baseURL(http://127.0.0.1:8080) // 从 CSV 读账号circular 表示循环复用 val users csv(users.csv).circular val scn scenario(登录并下单) .feed(users) .exec( http(登录) .post(/api/login) .body(StringBody({user:${username},pwd:${password}})).asJSON .check(status.is(200)) .check(jsonPath($.token).saveAs(token)) // 提取 token 供后续用 ) .exec( http(下单) .post(/api/order) .header(Authorization, Bearer ${token}) .body(StringBody({itemId:1,qty:1})).asJSON .check(status.in(200, 201)) ) setUp(scn.inject(atOnceUsers(20))).protocols(httpConf) }feed把 CSV 的一行注入会话变量${username}在字符串里做插值saveAs(token)把提取值存进会话后续请求用${token}引用。asJSON会顺带设Content-Type漏了它服务端可能按表单解析返回 415。CSV 文件放user-files/resources/编码用 UTF-8带 BOM 的话第一列字段名会带上不可见字符表现为「变量取不到值」——这个坑很隐蔽。3.3 用 Maven 工程管理脚本绿色包适合试水真要在团队里用脚本得进版本库、能编译、能打包。3.0.0 官方提供 Maven 原型把脚本变成标准 Java 工程的一部分。!-- pom.xml 关键片段 -- properties gatling.version3.0.0/gatling.version scala.version2.12/scala.version /properties dependencies dependency groupIdio.gatling.highcharts/groupId artifactIdgatling-charts-highcharts/artifactId version${gatling.version}/version scopetest/scope /dependency /dependencies build plugins plugin groupIdio.gatling/groupId artifactIdgatling-maven-plugin/artifactId version3.0.0/version configuration simulationClasssimulations.OrderSimulation/simulationClass /configuration /plugin /plugins /build脚本放src/test/scala/simulations/mvn gatling:test触发压测报告落在target/gatling/。simulationClass写全限定类名包名和目录结构必须一致否则插件找不到类。这套结构的好处是依赖版本锁死、CI 里一条命令跑完坏处是首次拉依赖比较慢内网环境要配好镜像。4. 避坑与排查五个真实翻车现场4.1 启动即报 Unsupported class file major version现象执行gatling.sh立刻退出日志里出现Unsupported class file major version 55之类的字样。原因机器默认 JDK 是 11 或更高而 3.0.0 编译目标是 JDK 8。解决显式export JAVA_HOME指向 JDK 8再启动多版本共存时别改全局默认用脚本里临时设环境变量的方式避免影响其他工具。4.2 报告里响应时间漂亮但业务侧说服务被打挂现象Gatling 报告成功率 100%、P99 很低但同一时段服务监控显示线程池打满。原因connection(keep-alive)加连接复用压测机和服务端之间连接数远小于虚拟用户数服务端看到的并发被低估同时requestTimeout设得太长慢请求被算成「成功但慢」。解决核对服务端连接数与虚拟用户数的比例必要时在协议层关掉连接复用做对照把超时收紧到业务可接受上限让超时请求计入失败而不是拉高均值。4.3 CSV 参数化取不到值现象请求体里出现字面量${username}或者服务端报参数为空。原因CSV 文件不在user-files/resources/下、文件名大小写不符、或者文件带 BOM 导致首列字段名异常。解决确认路径和文件名完全一致用十六进制工具看一眼文件头有没有EF BB BF有就转成无 BOM 的 UTF-8feed放在exec之前顺序错了变量还没注入就发请求了。4.4 断言不生效压测不达标也返回 0现象P95 明显超过阈值但命令退出码是 0CI 没拦住。原因assertions写在了setUp(...)链之外或者用了 3.0.0 不支持的断言 API从新版本文档抄来的写法。解决断言必须挂在setUp(...).protocols(...).assertions(...)这条链上percentile3是 P95percentile4是 P99别记反改完先故意把阈值调到不可能达到的值确认进程真的以非零码退出再调回正常值。4.5 高并发下压测机自己先崩现象并发上到几千Gatling 进程 OOM 或 GC 停顿严重报告里出现大量连接超时。原因默认堆太小加上每个虚拟用户的会话对象都占内存压测机成了瓶颈。解决JAVA_OPTS里把-Xms/-Xmx调到物理内存的合理比例留出系统余量换 G1并发再高就上分布式多台压测机分片别指望单机扛一切。判断是不是压测机瓶颈的方法看压测机 CPU 和 GC 日志如果压测机先饱和报告数字全部作废。5. 验证与进阶让压测结果经得起追问压测报告最容易被质疑的一点是「你这个数字是怎么来的」。要让结果站得住得做两件事一是用受控实验验证工具本身没骗你二是把压测纳入可重复的流程。先做工具自证。拿一个已知性能的本地接口比如一个只做字符串拼接的端点用固定并发跑三轮看三轮的 P95 波动是否在可接受范围再人为在服务端加 100ms 延迟确认报告里的 P50 相应上移约 100ms。这两步做完你对这套工具在当前环境下的测量误差就有了底数后面看到异常数字能快速判断是业务问题还是测量问题。再做流程固化。把mvn gatling:test挂到 CI 的固定阶段每次发版前跑同一套脚本、同一套注入模型报告归档对比。对比时只看三个指标P95、错误率、吞吐量其余指标波动大、参考价值有限。注入模型不要每次改改了就没有可比性要试新模型单独开一条流水线。验证项做法通过标准工具测量准确性已知延迟接口对照报告分位数偏移与人为延迟一致结果可重复性同脚本连跑三轮P95 波动在 ±10% 内断言有效性故意设不可达阈值进程非零退出压测机余量观察压测机 CPU/GC压测机不先饱和还有一个容易忽略的点报告里的「响应时间」是从发出请求到收完响应的全链路时间包含网络和序列化不等于服务端处理时间。跟研发对数字时先说清口径否则容易各说各话。我一般会在报告旁边附一句「本报告为端到端时间服务端耗时请对照 APM」省掉很多来回。从那以后我每次压测前都强制走一遍「JDK 版本确认 示例脚本跑通 断言故意失败验证」这三步宁可多花十分钟也不让一份数字可疑的报告流到决策桌上。希望帮到你。本文还有配套的精品资源点击获取