第三章:压测工具选型——选对工具,事半功倍
做性能压测这么多年,我经常被问到:“到底该用哪个工具?”说实话,没有完美的工具,只有最适合你场景的。今天我就把 JMeter、Locust、wrk、ab、Gatling 这几款主流工具掰开揉碎讲清楚。
核心观点:工具选型取决于三个维度——业务场景、技术栈、团队能力。没有银弹,只有权衡。
3.1 五款主流工具速览
先上一张对比表,让你对它们有个整体印象。
| 工具 | 协议支持 | 语言/脚本 | 并发模型 | 分布式 | 学习成本 |
|---|---|---|---|---|---|
| JMeter | HTTP、JDBC、JMS、FTP 等 | GUI 配置 + Groovy/Java | 线程池 | 支持 | 中等 |
| Locust | HTTP、HTTP/2、WebSocket | Python | 协程(gevent) | 支持 | 低 |
| wrk | HTTP/1.1 | C + Lua | 多线程 + epoll | 不支持 | 高 |
| ab | HTTP/1.0、HTTP/1.1 | 命令行参数 | 单/多进程 | 不支持 | 极低 |
| Gatling | HTTP、WebSocket、SSE | Scala(基于 DSL) | 异步非阻塞(Akka) | 支持 | 较高 |
这张表的信息量很大。我一个个拆开讲。
3.2 JMeter —— 老牌全能王
说到压测,JMeter 是绕不开的。它就像瑞士军刀,什么都能干。HTTP、数据库、消息队列,甚至自定义协议,它都能搞定。
我个人习惯用它来做复杂的业务场景编排。比如一个电商下单流程,需要先登录、加购物车、提交订单、支付,每一步之间还有参数依赖。用 JMeter 的 GUI 拖拖拽拽就能配出来。
避坑提醒:我曾经在压测一个高并发接口时,发现 JMeter 本身成了瓶颈。后来把 GUI 模式换成非 GUI 模式跑,压测机从 4 核 8G 换成 8 核 16G,问题解决了。
跑非 GUI 模式的命令很简单:
jmeter -n -t test.jmx -l result.jtl -e -o report/
参数说明:-n 非 GUI 模式,-t 指定脚本,-l 保存原始结果,-e 自动生成 HTML 报告。
3.3 Locust —— Pythoner 的菜
如果你团队全是 Python 开发者,那 Locust 会是你的首选。它用协程代替线程,单机就能模拟成千上万的并发用户。
写个简单的压测脚本:
from locust import HttpUser, task, between
class WebsiteUser(HttpUser):
wait_time = between(1, 5)
@task(3)
def index(self):
self.client.get("/")
@task(1)
def search(self):
self.client.post("/search", json={"q": "test"})
@task(3) 的意思是访问首页的频率是搜索的 3 倍。这种用代码定义用户行为的方式,非常灵活。
我记得有一次要模拟 5000 个用户同时登录,用 JMeter 跑了 3 台从机才撑住,换成 Locust 后一台机器就够了。原因很简单——协程的开销远小于线程。
3.4 wrk —— 纯性能拷问器
wrk 的特点就一个字:快。它是用 C 写的,基于多线程和 epoll 事件驱动,单机就能打出几十万的 QPS。
用法很简单:
wrk -t12 -c400 -d30s http://target.com/api
意思是开 12 个线程,维持 400 个连接,持续压 30 秒。输出结果清晰明了。
但 wrk 有个硬伤——不支持自定义协议。它只能压 HTTP/1.1。你要压 WebSocket 或 gRPC,它无能为力。
不过你要是想快速评估一台服务器的原始吞吐能力,wrk 是最佳选择。
3.5 ab —— 轻量级狙击手
ab(Apache Bench)是 Apache 自带的压测工具。比 wrk 还简单,一条命令搞定:
ab -n 10000 -c 100 http://target.com/
发 10000 个请求,100 个并发。但它只能压 HTTP,且不支持 HTTPS(需要编译时开启 SSL 支持)。
我一般只在开发环境快速验证时用它。比如代码改了个循环逻辑,本地跑一下 ab 看有没有明显变慢。一旦进入正式压测阶段,我肯定换工具。
3.6 Gatling —— 高性能 DSL 选手
Gatling 用 Scala 的 DSL 编写压测脚本,底层是 Akka 的异步非阻塞模型。它的代码可读性很强:
class BasicSimulation extends Simulation {
val httpConf = http.baseUrl("https://target.com")
val scn = scenario("Basic")
.exec(http("request").get("/"))
.pause(2)
setUp(scn.inject(atOnceUsers(100)).protocols(httpConf))
}
看着是不是像自然语言?这就是 DSL 的魅力。而且它的 HTML 报告做得极其漂亮,曲线、响应时间分布、吞吐量,一目了然。
但 Gatling 的门槛在于 Scala。如果你团队没人熟悉 Scala,学习曲线会比较陡。我遇到过团队买了一堆 Gatling 的培训课程,最后还是用回 JMeter 的情况。
3.7 怎么选?我的决策逻辑
我画了一张图,帮助你快速定位。
简单来说:
- 做复杂的业务压测(多协议、多步骤、参数关联)→ JMeter
- 团队擅长 Python → Locust
- 只想看单机原始性能 → wrk 或 ab
- 追求高颜值报告和代码维护 → Gatling
3.8 实测经验:不同工具的压测数据差异
我拿一个简单的 REST API(返回 JSON)在同样一台 4 核 8G 机器上做对比。结果很有意思。
| 工具 | 最大 QPS | 平均延迟 (ms) | CPU 占用率 | 压测机自身瓶颈 |
|---|---|---|---|---|
| JMeter(GUI) | 8,200 | 12.1 | 65% | JVM GC |
| JMeter(非 GUI) | 18,500 | 5.4 | 40% | 基本无 |
| Locust | 15,300 | 6.5 | 35% | Python GIL |
| wrk | 42,000 | 2.3 | 20% | 几乎无 |
| ab | 12,000 | 8.3 | 30% | 单进程 |
| Gatling | 22,000 | 4.5 | 35% | Akka 调度 |
看到没?JMeter 用 GUI 和非 GUI 模式跑,性能差距一倍以上。所以实战中千万别开着 GUI 就跑高并发压测。
重要提醒:wrk 虽然单机性能最强,但它压的是“纯请求”,不包含任何业务逻辑。如果你的接口里有数据库查询、缓存访问,wrk 打出来的 QPS 并不能代表真实用户场景。这一点一定要注意区分。
3.9 总结一下我的选型建议
- 快速诊断:用 ab 或 wrk,一两分钟看响应
- 功能压测:用 JMeter,场景编排能力强
- 持续集成:用 Locust 或 Gatling,代码即脚本
- 极限性能:用 wrk,压出服务器天花板
你想想看,如果只是验证一个 API 的吞吐量,你拿 JMeter 搭半天脚本,是不是有点杀鸡用牛刀?反过来,如果你要模拟复杂的用户行为,用 ab 一条命令就太粗糙了。
选工具就像选螺丝刀。一字螺丝刀能拧螺丝,十字螺丝刀也能拧。但拧十字螺丝时,用一字刀就容易滑丝。道理是一样的。