给网站做压测,绕不开工具选择。ab 简单,但单线程、能力有限,稍微大一点的机器就跑不满了;JMeter 功能全,但要装 Java、学 GUI,偏重。wrk 正好卡在中间:命令行、多线程、基于事件驱动,单机就能压出很高的并发,输出还带延迟分布,是很多运维和开发做 HTTP 压测的首选。
这篇文章讲清楚 wrk 怎么用:怎么安装、参数各是什么含义、结果怎么读、怎么用脚本发 POST 请求、和 ab 有什么区别、以及那个最容易被忽略的坑——压测客户端自己先成了瓶颈。文中数值为经验量级,以你实际环境为准。
一、wrk 为什么值得用
wrk 的核心特点是多线程 + 事件驱动(epoll/kqueue)。它可以开多个线程,每个线程内部用非阻塞 IO 处理大量连接,因此单机就能发起很高的并发,比 ab 这种"一个线程一个连接"的模式强得多。
主要优势:
- 能压出高并发,适合现代多核服务器。
- 自带延迟分布统计(配合
--latency),能看到 P50/P90/P99。 - 支持 Lua 脚本,可以自定义请求方法、Body、Header、动态参数。
- 命令行轻量,容易脚本化和自动化。
适合场景:HTTP/HTTPS 接口压测、找单机 QPS 上限、验证性能优化效果、上线前容量评估。
二、安装
wrk 在部分发行版默认源里没有,两套做法。
# Debian / Ubuntu:部分版本源里有 wrk,可先尝试
sudo apt update && sudo apt install -y wrk
# RHEL / CentOS / Rocky / AlmaLinux:一般需要从源码编译
sudo dnf install -y git gcc make openssl-devel
# CentOS 7
sudo yum install -y git gcc make openssl-devel
# 源码编译(两套发行版通用)
git clone https://github.com/wg/wrk
cd wrk
make
sudo cp wrk /usr/local/bin/
wrk --version # 验证安装
编译依赖 OpenSSL 开发包(HTTPS 支持)。如果 make 报找不到 ssl,检查 openssl-devel(RHEL 系)或 libssl-dev(Debian 系)是否装好。
三、常用参数
wrk [选项]
| 参数 | 含义 | 建议 |
|---|---|---|
-t |
线程数 | 一般设为 CPU 核数或核数×1~2 |
-c |
并发连接数 | 要测的并发量,需大于等于线程数 |
-d |
持续时长 | 至少 30s,稳态建议 1~3 分钟 |
--latency |
打印延迟分布 | 强烈建议加上 |
-s |
指定 Lua 脚本 | 发 POST、带参数时用 |
-H |
添加请求头 | 如 -H "Authorization: Bearer x" |
--timeout |
请求超时 | 默认 2s,可调 |
-R |
每连接每秒请求数 | 限速用(部分版本支持) |
一个常规调用:
# 4 线程、100 并发、持续 30 秒、输出延迟分布
wrk -t4 -c100 -d30s --latency http://127.0.0.1:8080/
调参经验:-t 不要超过压测机核数太多;-c 要明显大于 -t 才有意义(否则线程空转);-d 太短测的是预热阶段,没有参考价值。
四、结果怎么读
典型输出:
Running 30s test @ http://127.0.0.1:8080/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 12.34ms 3.21ms 120.00ms 87.50%
Req/Sec 850.00 120.00 980.00 75.00%
Latency Distribution
50% 11.00ms
75% 13.00ms
90% 16.00ms
99% 25.00ms
102000 requests in 30.00s, 25.50MB read
Socket errors: connect 0, read 5, write 0, timeout 0
Requests/sec: 3200.00
Transfer/sec: 870.00KB
逐项解读:
- Requests/sec:这是 QPS,最核心的吞吐指标。
- Transfer/sec:吞吐带宽,判断是否撞带宽瓶颈。
- Latency Avg / Stdev / Max:平均、标准差、最大响应时间。Stdev 相对 Avg 很大,说明响应时间不稳定。
- Latency Distribution:延迟分位数。P99 是最该关注的——它代表最慢那 1% 用户的体验。平均值好看但 P99 很差,说明有长尾问题。
- Socket errors:连接、读、写错误和超时。任何非零都要查。
connect错误多可能是端口耗尽或服务端拒绝;timeout多说明服务端处理不过来或网络差。 - requests in ... s:总请求数和总时长,用来核对。
五、用 Lua 脚本发 POST 与动态参数
默认 wrk 发 GET。要发 POST、带 JSON Body,用脚本:
-- post.lua
wrk.method = "POST"
wrk.body = '{"id":1,"name":"test"}'
wrk.headers["Content-Type"] = "application/json"
wrk.headers["Authorization"] = "Bearer your-token"
wrk -t4 -c100 -d30s --latency -s post.lua http://127.0.0.1:8080/api/create
要每次请求用不同参数(避免缓存干扰),用 request() 或 init()/setpath:
-- rand.lua:每个请求带随机 id
request = function()
local id = math.random(1, 100000)
return wrk.format(nil, "/api/item?id=" .. id)
end
wrk -t4 -c100 -d60s --latency -s rand.lua http://127.0.0.1:8080/
用随机参数能更真实地反映生产流量,也能避免所有请求命中同一条缓存记录导致结果虚高。
六、和 ab 的对比
| 维度 | wrk | ab |
|---|---|---|
| 并发模型 | 多线程 + 事件驱动 | 单线程,进程/线程模型 |
| 能否压高并发 | 能,适合多核 | 受限,单机上限低 |
| 延迟分布 | 有(P50/P90/P99) | 只有部分统计 |
| 脚本扩展 | Lua,灵活 | 基本不支持 |
| 上手难度 | 低 | 很低 |
| 适用 | 现代多核服务器、接口压测 | 快速小规模验证 |
结论:小规模快速验证用 ab,正式压测用 wrk。ab 最大的局限是单线程,压测机上它自己先到瓶颈,容易低估服务端能力。
七、注意事项:压测客户端可能先成瓶颈
这是 wrk 使用中最重要的提醒:wrk 再强,压测机资源也是有限的。
- CPU 不够:wrk 线程会和
-t匹配。压测机 CPU 跑满,QPS 就被压测机限住了。 - 端口/连接耗尽:高并发下客户端大量 TIME_WAIT,可能耗尽本地端口。可临时调整内核参数,或让服务端支持长连接。
- 网络带宽:响应体大时,压测机网卡可能先被打满。看
Transfer/sec和压测机网卡。 - 压测机与被测机分离:绝对不要把 wrk 和被压服务放同一台机器,两者抢资源,结果毫无意义。
判断压测机是否成瓶颈:压测时看压测机的 top、ss -s、网卡流量。若压测机 CPU 接近满而服务端还有余量,就是它的问题,需要换更强压测机或分布式压测。
八、阶梯加压找单机拐点
单跑一个并发值只能得到一个点,真正有用的是"加压曲线"——随着并发上升,QPS 和响应时间怎么变。
# 阶梯加压:从 50 并发加到 800,观察 QPS 与延迟变化
for c in 50 100 200 400 800; do
echo "===== 并发 $c ====="
wrk -t4 -c$c -d30s --latency http://127.0.0.1:8080/api/hot
sleep 5
done
把每轮的结果记成一张表:
| 并发 | QPS | Avg 延迟 | P99 延迟 | Socket errors |
|---|---|---|---|---|
| 50 | 2100 | 23ms | 60ms | 0 |
| 100 | 3200 | 31ms | 110ms | 0 |
| 200 | 3500 | 57ms | 260ms | 0 |
| 400 | 3400 | 118ms | 800ms | 12 |
| 800 | 2900 | 276ms | 2200ms | 340 |
判读方法:
- QPS 达到平台并开始回落,同时 P99 明显变长、错误出现,这个拐点就是单机上限。上表里 200 并发附近是拐点,400 之后已经在劣化。
- 取拐点前的健康并发(这里是 100~200)作为推荐工作区间,而不是取极限值。
- 拐点之后 QPS 下降,是因为资源饱和导致排队,请求还没处理完就超时,属"过载自噬"。
这个拐点值,就是容量规划里"单机可承载 QPS"的来源。
九、几个常见误区
误区一:只看 Requests/sec,不看延迟。 QPS 高但 P99 已经到秒级,用户照样受不了。要 QPS 和延迟一起看。
误区二:并发拉到最高。 并发越高越能压出上限,但也越容易把服务压垮、产生大量错误,测出的数据反而没有参考价值。要从低到高阶梯加压。
误区三:压测机和服务端放一起。 两者抢 CPU 和网络,测出来的数字毫无意义,必须分开部署。
误区四:不考虑真实流量特征。 只压一个静态接口、只发同一请求、带满缓存,结果会虚高。用 Lua 脚本模拟真实请求分布和随机参数,结果才有意义。
误区五:测完不记录环境信息。 不记机器配置、软件版本、参数,下次无法复现、无法对比。压测报告要把环境写清楚。
常见问题
Q1:-t 和 -c 怎么设?
-t 按压测机核数设(如 4 核设 4);-c 设成你要测的并发,且明显大于 -t。比如 -t4 -c100。想找极限可以阶梯加 -c,观察 QPS 拐点。
Q2:Requests/sec 忽高忽低正常吗?
小幅波动正常。若大幅波动,先查压测机是否成瓶颈、服务端是否有 GC 或缓存冷热问题、网络是否抖动。
Q3:Socket errors 有数字要紧吗?
要紧。connect 错误多为端口耗尽或服务端拒绝,timeout 多为服务端慢或网络差。先解决它,再看 QPS,否则数据不可信。
Q4:怎么测 HTTPS?
wrk 编译时带 OpenSSL 就支持,直接写 https:// 地址即可。注意 HTTPS 的握手开销会消耗更多 CPU。
Q5:wrk 能做分布式压测吗?
wrk 本身不内置分布式,需要自己用多台机器同时压,或用专门的分布式压测工具。单机不够用时,优先排查是不是压测机成瓶颈,再考虑多机。
Q6:为什么压测结果和线上监控对不上?
常见原因有几类:压测流量单一、没模拟真实请求分布;压测环境数据量、缓存状态和线上不同;压测机自己拖了后腿;线上还有别的业务共享资源。要尽量让压测环境贴近线上,并把压测报告里的环境信息写清楚,才能对比。
Q7:HTTPS 压测结果比 HTTP 低很多正常吗?
正常。TLS 握手加解密要消耗 CPU,连接建立阶段尤其明显。如果业务以短连接为主,HTTPS 开销更突出;用长连接(keep-alive)能摊薄握手成本,结果会更接近实际。
总结
- wrk 是多线程事件驱动的 HTTP 压测工具,适合压高并发;RHEL 系一般需源码编译,Debian/Ubuntu 可尝试包安装。
- 核心参数:
-t线程、-c并发、-d时长、--latency看分布、-s加载 Lua 脚本。 - 结果重点:Requests/sec 是 QPS,Latency Distribution 看 P99,Socket errors 非零必须查。
- 用 Lua 脚本发 POST 和随机参数,避免缓存干扰,让压测更贴近真实流量。
- 小规模用 ab、正式用 wrk;永远把压测机与被测机分开,警惕压测客户端自己成为瓶颈。
企业QQ咨询




