第3章 压测工具入门:JMeter基础使用

做性能测试这么多年,我见过不少团队拿着JMeter却只会点“开始”和“停止”。说实话,这工具远比你想象的强大。今天咱们就从最基础的部分开始,把JMeter的底子打扎实。

3.1 JMeter是什么?为什么选它?

JMeter是Apache基金会下的开源压测工具。它最初是为Web应用设计的,后来扩展到了数据库、FTP、消息队列等各种协议。我个人习惯用它做HTTP接口的吞吐测试,因为它的插件生态实在太丰富了。

你可能会问:“市面上压测工具那么多,为什么偏要学JMeter?”

三个理由:

  • 免费开源 —— 没有授权费用,团队随便用
  • 跨平台 —— Windows、Linux、macOS都能跑
  • 扩展性强 —— 官方插件+第三方插件,几乎什么协议都能测
我的建议: 刚开始别急着装插件。先把JMeter自带的HTTP取样器玩熟,后面再按需扩展。我在项目中见过有人一上来装了30多个插件,结果大部分根本用不上。

3.2 安装与启动

JMeter依赖Java环境。先确认你的机器上有JDK 8或更高版本:

java -version

然后去Apache官网下载JMeter的二进制包。解压后,进入bin目录:

  • Windows:双击 jmeter.bat
  • Linux/Mac:运行 sh jmeter.sh

启动后你会看到一个空白的测试计划界面。嗯,这就是我们接下来要操作的主战场。

注意: 启动时如果报内存不足,可以修改 jmeter.bat 或 jmeter.sh 里的 HEAP 参数。我曾经在压测一个高并发项目时,默认的512MB堆内存直接OOM,后来改成了 -Xms2g -Xmx4g 才稳住。

3.3 创建线程组 —— 模拟用户行为

线程组是JMeter里最核心的概念。说白了,它就是用来定义“有多少个虚拟用户”以及“这些用户怎么跑”的。

右键点击“测试计划” → 添加 → 线程(用户) → 线程组。你会看到这样的配置面板:

参数 说明 我的常用值
线程数 虚拟用户的数量 先设10,逐步增加到100、500
Ramp-Up时间(秒) 所有线程启动完毕需要的时间 线程数 × 0.1,比如100线程就设10秒
循环次数 每个线程执行多少次请求 勾选“永远”,配合调度器控制时长
调度器 设定测试的持续时间 压测一般跑5~10分钟

举个例子:我要模拟100个用户,在10秒内全部启动,然后持续压测5分钟。配置就是:线程数=100,Ramp-Up=10,循环次数勾选“永远”,调度器里填持续时间=300秒。

避坑指南: 我曾经犯过一个低级错误 —— Ramp-Up时间设得太短。100个线程在1秒内同时启动,结果服务器直接挂了,但这不是服务器的真实瓶颈,而是启动风暴。后来我改成10秒平滑启动,数据才正常。

3.4 配置取样器 —— 定义要压测的请求

线程组只是定义了“谁在跑”,取样器才是定义“跑什么”。

右键点击线程组 → 添加 → 取样器 → HTTP请求。配置项如下:

  • 协议: http 或 https
  • 服务器名称或IP: 目标地址,比如 api.example.com
  • 端口号: 默认80(http)或443(https)
  • 方法: GET、POST、PUT、DELETE等
  • 路径: 接口路径,比如 /api/v1/users
  • 参数: 可以添加请求参数或Body数据

举个例子,我要压测一个登录接口:

协议:https
服务器:api.example.com
端口:443
方法:POST
路径:/api/v1/login
Body:{"username":"test","password":"123456"}

这里有个小技巧:如果接口需要Token或Session,可以添加一个“HTTP信息头管理器”,在里面设置 Authorization: Bearer xxx。我在项目中经常用这种方式模拟已登录用户的请求。

3.5 添加监听器 —— 看结果

没有监听器,压测就是盲打。JMeter提供了多种监听器,我常用的就三个:

  • 查看结果树: 调试用,能看到每个请求的请求头和响应体
  • 聚合报告: 核心报表,包含吞吐量、平均响应时间、错误率等
  • 图形结果: 可视化趋势,适合观察性能变化

右键点击线程组 → 添加 → 监听器 → 聚合报告。跑完压测后,你会看到类似这样的数据:

指标 含义 健康值参考
#样本 总请求数 越多越好
平均值 平均响应时间(ms) < 500ms
中位数 50%的请求在这个时间内完成 < 500ms
90%百分位 90%的请求在这个时间内完成 < 1000ms
最小值 最快响应时间 越低越好
最大值 最慢响应时间 警惕异常值
吞吐量 每秒处理的请求数(TPS) 越高越好
错误率 失败请求占比 < 1%
我的习惯: 压测时我会同时打开“聚合报告”和“图形结果”。聚合报告看最终数据,图形结果看实时趋势。有一次压测,聚合报告显示平均响应时间只有200ms,但图形结果却显示最后2分钟响应时间飙升到了2秒。如果只看聚合报告,我差点漏掉这个性能拐点。

3.6 聚合报告解读 —— 看懂数据背后的故事

聚合报告是JMeter里最重要的报表。但很多人只会看“平均值”,这其实是个陷阱。

举个例子:

#样本:10000
平均值:500ms
中位数:200ms
90%百分位:1500ms
99%百分位:5000ms
吞吐量:200 TPS
错误率:2%

平均值500ms看起来还行,但90%百分位是1500ms,99%百分位是5000ms。这说明什么?说明大部分请求很快(中位数200ms),但有一小部分请求慢得离谱。这种“长尾延迟”在性能优化中非常常见。

我一般这样解读:

  • 平均值 + 中位数: 如果两者接近,说明性能稳定;如果平均值远大于中位数,说明存在慢请求拖后腿
  • 90%/99%百分位: 关注尾部延迟,这是用户体验的关键
  • 吞吐量: 结合线程数看,如果线程数增加但吞吐量不涨,说明系统已经达到瓶颈
  • 错误率: 超过1%就要排查原因,可能是超时、服务器拒绝连接、参数错误等
注意: 聚合报告里的“吞吐量”单位是“请求/秒”,但有些场景下你需要换算成“事务/秒”。比如一个页面加载包含10个接口请求,那TPS就是吞吐量除以10。我在项目中吃过这个亏,汇报时把吞吐量当成了TPS,结果被领导质疑数据造假。

3.7 一个完整的压测流程

说了这么多,咱们来走一遍完整的流程。假设我要压测一个用户列表接口:

  1. 启动JMeter,创建测试计划
  2. 添加线程组:线程数=50,Ramp-Up=5秒,循环次数=永远,持续时间=300秒
  3. 添加HTTP请求默认值:协议=http,服务器=localhost,端口=8080
  4. 添加HTTP请求:路径=/api/users,方法=GET
  5. 添加HTTP信息头管理器:Content-Type=application/json
  6. 添加聚合报告和图形结果
  7. 点击绿色“启动”按钮
  8. 观察图形结果,等待测试结束
  9. 查看聚合报告,记录关键指标

就这么简单。但实际项目中,你还需要考虑参数化(用CSV文件传入不同用户数据)、断言(验证响应是否正确)、定时器(模拟用户思考时间)等高级功能。这些我们后面章节会详细讲。

3.8 JMeter核心组件关系图

下面这张图展示了JMeter各组件之间的协作关系。我建议你把它保存下来,每次搭建压测脚本时对照着看:

JMeter核心组件协作关系 测试计划 线程组 配置元件 取样器 监听器 逻辑控制器 定时器 断言 组件协作说明 1. 测试计划包含线程组,线程组管理虚拟用户 2. 取样器发送请求,配置元件提供参数,定时器控制节奏 3. 监听器收集结果,断言验证响应,逻辑控制器控制流程

3.9 常见问题与避坑

最后分享几个我在项目中踩过的坑:

  • 监听器不要放在线程组外面: 否则只能看到汇总数据,看不到每个线程组的独立表现
  • 压测时关掉“查看结果树”: 它会记录每个请求的完整数据,非常耗内存。我一般只在调试时打开,正式压测时关掉
  • 分布式压测时注意时间同步: 如果多台机器时间不一致,聚合报告里的时间戳会乱掉。我曾经因为这个排查了整整一天
  • CSV参数化文件路径用绝对路径: 相对路径在分布式压测时容易找不到文件

好了,JMeter的基础使用就讲到这里。你可以在本地搭一个简单的Web服务,然后按照上面的步骤跑一遍。只有亲手操作过,这些概念才能真正变成你自己的东西。