压测工具选型:wrk、JMeter、Locust、GoReplay 对比与选择策略

做交易系统压测这么多年,我经常被问到同一个问题:到底该用哪个压测工具?

说实话,没有银弹。每个工具都有自己的脾气。我见过团队用JMeter压出漂亮数据,上线却崩了。也见过有人用wrk跑了几分钟就自信满满,结果漏掉了核心业务逻辑。

今天我把四个主流工具掰开揉碎讲清楚。你听完就知道,什么场景该选谁。

一、先看一张全景图

下面这张图,是我自己总结的选型逻辑。你把它存下来,以后选工具时拿出来对照。

压测工具选型决策树 压测目标是什么? 单接口/简单场景 复杂业务/全链路 wrk(高性能) Locust(可编程) JMeter(全功能) GoReplay(流量复制) CPU/内存基准 简单GET/POST 自定义协议 动态参数 复杂业务流程 断言/报告 线上流量回放 回归验证 核心原则:工具服务于场景,不要为了用工具而用工具

二、逐个拆解:四个工具的真实面貌

1. wrk —— 轻量级性能标杆

wrk 是我个人最常用的快速验证工具。它基于 C 语言 + Lua 脚本,能轻松压出几十万 QPS。

核心优势:

  • 资源消耗极低 —— 一台 4C8G 的机器就能压满千兆网卡
  • 启动快 —— 10 秒内完成配置并开始施压
  • 结果直观 —— 延迟分布、吞吐量一目了然

但 wrk 有个致命短板:它只能模拟简单的请求-响应模式。我在项目中遇到过,用 wrk 压一个下单接口,结果发现它没法处理登录态、没法维护 session。说白了,它就是个「大力出奇迹」的工具,适合测网络层和中间件。

# 一个典型的 wrk 压测命令
wrk -t12 -c400 -d30s --latency http://localhost:8080/api/order

# 带 Lua 脚本的自定义请求
wrk -t4 -c200 -d60s -s custom.lua http://localhost:8080

我的建议:用 wrk 做第一轮快速摸底。如果发现系统扛不住,先别急着调优,换个工具做全链路验证。

2. JMeter —— 企业级压测瑞士军刀

JMeter 我用了快十年。它最大的优点是什么都能干。从 HTTP、JDBC、JMS 到自定义协议,插件生态极其丰富。

我记得有一次帮一家券商做压测,业务场景涉及「登录→查询行情→下单→撤单→查询持仓」五个步骤。用 JMeter 的线程组 + 控制器 + 断言,半小时就搭好了完整链路。

JMeter 的典型应用场景:

  • 多步骤业务流程压测(比如交易系统的下单链路)
  • 需要参数化、关联、断言验证的场景
  • 生成详细报告(聚合报告、图表、HTML 报告)
  • 分布式压测(多台机器协同施压)

但 JMeter 也有坑。它的 GUI 模式本身就很吃资源。我曾经见过有人用 GUI 模式压 500 并发,结果 JMeter 自己先 OOM 了。记住:压测时一定要用 CLI 模式

# JMeter CLI 模式压测命令
jmeter -n -t test_plan.jmx -l results.jtl -e -o report_dir

避坑指南:我曾经在压测时发现 JMeter 的聚合报告里「异常率」为 0%,但业务方却说数据不对。后来排查发现,JMeter 默认只检查 HTTP 状态码,没检查响应体里的业务错误码。所以一定要加断言,验证业务逻辑。

3. Locust —— 程序员友好的压测工具

Locust 是用 Python 写的。它的设计理念很特别:把压测脚本写成代码。你想想看,对于熟悉 Python 的团队来说,这简直是福音。

我个人习惯用 Locust 做自定义协议压测。比如 WebSocket 场景、自定义 TCP 协议、或者需要动态计算签名的接口。这些场景下,JMeter 的配置会变得很复杂,而 Locust 几行代码就搞定了。

from locust import HttpUser, task, between

class TradingUser(HttpUser):
    wait_time = between(1, 3)
    
    def on_start(self):
        # 登录并获取 token
        resp = self.client.post("/login", json={"user": "test", "pwd": "123"})
        self.token = resp.json()["token"]
    
    @task(3)
    def place_order(self):
        self.client.post("/order", 
            json={"symbol": "BTC/USDT", "side": "buy", "qty": 0.1},
            headers={"Authorization": f"Bearer {self.token}"}
        )
    
    @task(1)
    def cancel_order(self):
        # 取消订单逻辑
        pass

我的经验:Locust 的 Web UI 模式很方便,可以实时调整并发数。但要注意,Web 模式本身会消耗一些资源。大规模压测时,建议用 --headless 模式。

4. GoReplay —— 流量复制与回放利器

GoReplay 和其他三个工具完全不同。它不生成虚拟请求,而是录制真实流量然后回放。

为什么需要它?因为很多时候,我们构造的压测场景和真实流量差距很大。用户的行为模式、参数分布、并发特征,这些在测试环境很难模拟。GoReplay 可以直接从线上抓流量,然后打到预发环境或压测环境。

# 录制线上流量
gor --input-raw :80 --output-file requests.gor

# 回放流量到测试环境
gor --input-file requests.gor --output-http "http://test-server:8080"

GoReplay 的典型用法:

  • 回归验证:把线上流量回放到新版本,对比响应差异
  • 容量评估:用真实流量倍数放大,测试系统极限
  • 混沌工程:结合流量回放做故障注入

避坑指南:我曾经用 GoReplay 回放流量时,发现测试环境数据库被写入了大量脏数据。原因是回放时没有做参数脱敏和幂等处理。记住:回放流量一定要做数据隔离,比如改写用户 ID、订单号等关键字段。

三、选型策略:到底怎么选?

我总结了一个简单的选型矩阵,你直接套用就行:

场景 推荐工具 理由
快速验证单接口性能 wrk 启动快、资源省、结果直观
复杂业务流程压测 JMeter 功能全面、断言丰富、报告完善
自定义协议/动态参数 Locust 代码灵活、Python 生态、易于扩展
线上流量回放验证 GoReplay 真实流量、无侵入、对比分析
全链路压测(混合场景) JMeter + GoReplay JMeter 构造基础流量,GoReplay 补充真实流量

我的建议:不要只依赖一个工具。我自己的工具箱里,wrk 做快速验证,JMeter 做全链路压测,Locust 处理特殊场景,GoReplay 做回归验证。四个工具配合使用,才能覆盖所有场景。

四、最后说两句

选工具这件事,说白了就是匹配场景。你想想看,用 wrk 去压复杂业务,就像用螺丝刀去砍树。用 JMeter 去压简单接口,又像用挖掘机去挖蚂蚁洞。

工具只是手段,理解你的系统、你的业务、你的瓶颈,才是压测的核心。我见过太多人纠结于「哪个工具最好」,却忽略了压测本身的目的——发现系统弱点,保障稳定性。

嗯,今天就聊到这里。记住:没有最好的工具,只有最合适的组合


专注资料整理