wrk:现代 HTTP 压测工具编译部署与使用指南
wrk 是一款用 C 编写的现代 HTTP 基准测试(压测)工具。它在单核多路 CPU 上就能产生可观的压力:把多线程设计与 epoll、kqueue 这类可扩展事件通知机制结合,用很少的资源就能打满目标服务。它还可选地通过 LuaJIT 脚本自定义请求生成、响应处理与统计报告,是后端服务上线前做容量评估、接口压测的常用利器。
一、项目官方信息
| 项目 | 信息 |
|---|---|
| GitHub 仓库 | https://github.com/wg/wrk |
| 主要语言 | C(约 96%) |
| 开源协议 | Modified Apache 2.0 License(Apache 2.0 修改版) |
| Star 数 | 40k+ |
| 运行方式 | 从源码编译出单个二进制 wrk |
说明:wrk 官方仓库的 README 与源码中未提供任何 Logo / Banner 图片,故本文不设「官方图片」小节,封面亦不使用占位图,保持与官方素材一致。
二、环境要求
- 操作系统:类 Unix 系统(Linux、macOS、FreeBSD 等)。
- 构建工具:GNU make(BSD 上通常是
gmake)与一个 C 编译器(gcc/clang)。 - 依赖库:wrk 需要 LuaJIT 与 OpenSSL,但它随源码自带了对应版本(
deps/LuaJIT-2.1.zip、deps/openssl-1.1.1i.tar.gz),编译时会自动解压并构建,无需你手动安装。 - 目标侧准备:压测机器要有足够多的临时端口(ephemeral ports)、TIME_WAIT 套接字回收要快;被压服务器的
listen(2) backlog应大于并发连接数。
三、完整部署(编译)步骤
1. 克隆源码
git clone https://github.com/wg/wrk.git
cd wrk
2. 编译
按照官方 INSTALL 文档,大多数情况下直接运行 make 即可:
make
编译过程会自动解压 deps/ 下的 LuaJIT 与 OpenSSL 并静态构建,最终在当前目录生成可执行文件 wrk。
如果你想改用系统已安装的 LuaJIT / OpenSSL(例如打 OS 发行版包时),可以在 make 时指定路径:
```bash
Linux 使用系统库
make WITH_LUAJIT=/usr WITH_OPENSSL=/usr
macOS 使用 Homebrew 的 OpenSSL
make WITH_OPENSSL=/usr/local/opt/openssl ```
3. 验证安装
查看版本与帮助:
./wrk --version
./wrk --help
能打印出版本号与命令行选项即说明编译成功。可把 wrk 复制到 /usr/local/bin 以便全局调用:
sudo cp wrk /usr/local/bin/
四、使用方法
1. 基础压测
官方 README 给出的标准用法:
wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html
含义:用 12 个线程、保持 400 个 HTTP 连接打开、持续压测 30 秒,目标是 http://127.0.0.1:8080/index.html。
运行后输出类似:
Running 30s test @ http://127.0.0.1:8080/index.html
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 635.91us 0.89ms 12.92ms 93.69%
Req/Sec 56.20k 8.07k 62.00k 86.54%
22464657 requests in 30.00s, 17.76GB read
Requests/sec: 748868.53
Transfer/sec: 606.33MB
重点看最后两行:Requests/sec 是每秒请求数(吞吐),Transfer/sec 是每秒传输流量;中间还给出了平均延迟、标准差与最大延迟。
2. 命令行参数
| 参数 | 说明 |
|---|---|
-c, --connections |
保持打开的总 HTTP 连接数,每个线程处理 N = connections/threads 个 |
-d, --duration |
压测时长,如 2s、2m、2h |
-t, --threads |
使用的总线程数 |
-s, --script |
指定 LuaJIT 脚本(见 SCRIPTING) |
-H, --header |
为请求添加 HTTP 头,如 "User-Agent: wrk" |
--latency |
输出详细的延迟统计分布 |
--timeout |
在该时间内未收到响应则记为一次超时 |
3. 常用组合示例
压测 2 分钟、带详细延迟统计:
wrk -t8 -c200 -d2m --latency http://127.0.0.1:8080/api
给请求加鉴权头:
wrk -t8 -c200 -d30s -H "Authorization: Bearer token123" http://127.0.0.1:8080/api
4. LuaJIT 脚本进阶
仓库 scripts/ 目录自带多个示例脚本:post.lua(POST 请求)、auth.lua(鉴权)、counter.lua、delay.lua、pipeline.lua、report.lua、setup.lua、stop.lua、addr.lua。用 -s 指定即可,例如发 POST:
wrk -t8 -c200 -d30s -s scripts/post.lua http://127.0.0.1:8080/
官方提示:只改 HTTP 方法、路径、请求头或 body 的脚本对性能几乎无影响;但每个请求都重新构造请求、或使用
response()处理响应,会明显降低能产生的压力。
五、常见问题 FAQ
Q1:编译时报错缺少 make / gcc?
请先安装构建工具链(如 Debian/Ubuntu 上 sudo apt install build-essential)。wrk 自带了 LuaJIT 与 OpenSSL 源码,正常不需要额外安装这两个库。
Q2:为什么压测吞吐上不去、客户端先到瓶颈? README 提醒:压测机要有足够的临时端口、关闭的套接字要能快速回收;线程数一般建议不超过 CPU 核心数的 2 倍,连接数再按需调大。
Q3:压测时被压服务大量报错?
说明服务的 listen(2) backlog 小于并发连接数,初始连接突发时被丢弃。请调大服务端 backlog 后再测。
Q4:-c 和 -t 怎么配?
-t 是线程数(通常按 CPU 核数取 2~4 倍即可),-c 是总并发连接数,每个线程分摊 connections/threads 个。二者要一起设置,单独调大其一没有意义。
Q5:能压测 HTTPS 接口吗?
可以。wrk 编译时静态链接了 OpenSSL,直接把目标 URL 写成 https:// 即可。
Q6:为什么用 Lua 脚本后吞吐下降?
官方说明:每请求动作(尤其是新建 HTTP 请求、用 response() 处理响应)会消耗 CPU,从而压低可生成的压力;只做静态字段改写的脚本无性能损耗。
六、跳转链接
- GitHub 仓库:https://github.com/wg/wrk
- 脚本编写说明(仓库内 SCRIPTING):https://github.com/wg/wrk/blob/master/SCRIPTING
- 示例脚本目录:https://github.com/wg/wrk/tree/master/scripts
- 编译说明(仓库内 INSTALL):https://github.com/wg/wrk/blob/master/INSTALL