Apache JMeter - User's Manual
GUI 配置层:坑在哪里
坑 1:关联(Correlation)配置繁琐
比如典型的场景:登录返回 token,下一个请求要用这个 token。
正常写代码:
token = login()
response = api(token)
JMeter GUI 配置:
1. 添加 HTTP Request(登录)
2. 添加 JSON Extractor:
- Names: token
- JSON Path: $.data.token
- Default Values: NOT_FOUND
3. 添加 HTTP Header Manager:
- Header: Authorization = ${token}
4. 添加第二个 HTTP Request(业务接口)
五个组件要配,一不小心变量名拼错、JSON Path 写错,排查起来很费劲。
坑 2:参数化(CSV Data Set Config)
CSV 文件有中文/特殊字符时编码容易出问题,循环次数和线程数配合关系容易搞混。
CSV 文件:users.csv
变量名:userId,password,amount
Delimiter:,
Recycle on EOF:True / False(到底是循环用还是停?)
这个配置理解错一个,线程组就跑出完全不同的行为。
坑 3:组件叠加后的执行顺序
JMeter 的执行顺序是:
1. 配置元件(Config Element)先执行
2. 前置处理器
3. 定时器(每个 Sampler 前执行)
4. Sampler(发请求)
5. 后置处理器
6. 断言
7. 监听器
GUI 界面上组件是平铺排列的,但执行顺序是上述逻辑顺序,新手很容易搞混。比如想在断言里引用一个后置处理器提取的变量,但执行顺序不对,变量还没生成就开始断言了。
坑 4:版本管理困难
.jmx 文件是 XML,Git merge 时冲突基本无法自动合并,只能人工对照两份文件取舍。团队三个人同时改脚本,最后合版本靠"谁记得改了啥"。
代码层(JSR223 / BeanShell):难在哪里
难 1:JMeter API 不直观
// JMeter 里写 Groovy 获取响应内容
def response = prev.getResponseDataAsString() // prev 是前一个 Sampler 的 Response
def json = new groovy.json.JsonSlurper().parseText(response)
def token = json.data.token
// 引用到下一个请求
vars.put("token", token) // vars 是 JMeter 变量容器
prev、vars、ctx 这些变量是 JMeter 上下文注入的,不查文档根本不知道存在。写错了没有 IDE 提示,纯靠经验。
难 2:Groovy 性能陷阱
JMeter 里写 Groovy 容易踩性能坑:
// 慢:每次解析 JSON
def json = new groovy.json.JsonSlurper().parseText(prev.getResponseDataAsString())
// 快:复用解析器(但新手不知道)
static def slurper = new groovy.json.JsonSlurper()
def json = slurper.parseText(prev.getResponseDataAsString())
JMeter 本身就对性能敏感,Groovy 写得不讲究反而成为压测瓶颈。
难 3:异常处理缺失
JMeter 的 Groovy 脚本异常默认直接抛到日志,Sampler 标记失败但原因不直观:
// 不会让 JMeter 报错的写法(try-catch 吞掉)
try {
def json = new groovy.json.JsonSlurper().parseText(prev.getResponseDataAsString())
vars.put("token", json.data.token)
} catch (Exception e) {
// 吞掉异常,但 sampler 还是成功状态,埋雷
}
// 正确写法要手动标记失败
try {
def json = new groovy.json.JsonSlurper().parseText(prev.getResponseDataAsString())
vars.put("token", json.data.token)
} catch (Exception e) {
prev.setSuccessful(false) // 显式标记失败
prev.setResponseData("JSON解析失败: " + e.message)
}
总结:什么时候用什么方式
| 场景 | 推荐方式 |
|---|---|
| 简单 HTTP 请求,单线程 | GUI 配置,够用 |
| 关联多、参数多、逻辑复杂 | GUI 搭框架 + JSR223 Groovy 写核心逻辑 |
| 高并发压测(性能敏感) | 尽量少用 Groovy,GUI 能搞定的别用脚本 |
| gRPC/Dubbo 等协议 | 自定义 Java Sampler(打包成 jar) |
| 团队协作 | 脚本模块化,.jmx 拆分管理,Git 建分支 |
核心原则:JMeter 是配置工具,不是编程工具。能用配置解决的问题别用代码,代码层是补足协议盲区用的,不是用来写复杂逻辑的。