目录
- 安装
- 基本用法
- 读懂输出
- [Lua 脚本](#Lua 脚本)
-
- [1. POST JSON 请求](#1. POST JSON 请求)
- [2. 动态参数(随机化请求)](#2. 动态参数(随机化请求))
- [3. 统计响应(done 钩子)](#3. 统计响应(done 钩子))
- [4. 可用的 Lua 钩子函数](#4. 可用的 Lua 钩子函数)
- 参数详解
- 场景示例
-
- 短链重定向(GET)
- [带 Token 的 API 接口](#带 Token 的 API 接口)
- [POST 创建接口(Lua 脚本)](#POST 创建接口(Lua 脚本))
- 逐步加压找瓶颈
- 推荐配置
安装
sh
# macOS homebrew
brew install wrk
# version
wrk -v
wrk 仅支持 Linux/macOS,不支持 Windows。建议在 Linux 服务器上跑压测,结果更准确。
基本用法
基本命令格式
sh
wrk [options] <url>
最简单的压测命令(3个核心参数):
sh
wrk -t8 -c400 -d30s http://localhost:8080/api/link
-
-t, threads
线程数,通常设为 CPU 核心数。
推荐:nproc(Linux), sysctl -n hw.logicalcpu(macOS) 查看核心数
-
-c, connections
并发连接数,总连接 = c
每线程连接 = c / t
-
-d, duration
测试持续时间
30s / 2m / 1h
连接数
经验公式:连接数 = 线程数 × (目标QPS / 单线程QPS估算)
通常从 -t4 -c100 开始,逐步增加 -c 直到 QPS 不再增长,此时即为服务瓶颈。
读懂输出
sh
# 运行命令
wrk -t12 -c400 -d30s http://localhost:8080/link/test
# 输出
Running 30s test @ http://localhost:8080/link/test
12 threads and 400 connections # 压测配置,12个线程,400个并发连接
# 线程级统计:平均值、标准差、最大值、符合标准差范围的请求占比
Thread Stats Avg Stdev Max +/- Stdev
Latency 16.72ms 3.21ms 89.44ms 91.23% # 延迟:平均16ms, 波动3ms,最大89ms,有91.23%的请求在均值±标准差范围内
Req/Sec 2.09k 312.54 3.12k 68.45% # 每秒请求数:单线程平均2.09k,波动 321.54,峰值3.12k,68%的请求在均值±标准差范围内
# 延迟分布(分位数,核心用户体验指标)
Latency Distribution
50% 13.03ms # 中位数:50%的请求延迟≤13.03ms
75% 17.86ms
90% 24.15ms
99% 38.92ms # 99%的请求延迟 ≤ 38.92ms(重点:仅1%请求超过272ms)
754238 requests in 30.01s, 124.47MB read # 30s内共处理的请求数以及读取数据大小
Requests/sec: 25114.21 # QPS:核心吞吐量,平均每秒处理请求数
Transfer/sec: 4.14MB # 数据传输量:平均每秒传输的数据量
| 字段 | 含义 | 关注点 |
|---|---|---|
| Latency Avg | 平均延迟 | 反映正常情况下的响应速度 |
| Latency Stdev | 延迟标准差 | 越小越稳定,大说明抖动严重 |
| Latency Max | 最大延迟 | 极端情况,关注是否超时 |
| 50%(P50) | 中位数延迟 | 50% 请求在此时间内完成 |
| 99%(P99) | 长尾延迟 | 最重要!生产关注 P99 |
| Requests/sec | QPS | 核心指标,越高越好 |
| Transfer/sec | 吞吐量 | 带宽占用参考 |
注意:输出中若出现 Socket errors 或 Non-2xx 行,说明有连接失败或服务端报错,此时 QPS 数据不可信!
sh
# 问题输出示例(需要排查)
Socket errors: connect 0, read 12, write 0, timeout 24
Non-2xx or 3xx responses: 1024
Lua 脚本
wrk 支持 Lua 脚本实现:自定义请求头、POST Body、动态参数、响应处理等。
1. POST JSON 请求
lua
-- post.lua
wrk.method = "POST"
wrk.body = '{"originUrl":"https://www.google.com","gid":"test001"}'
wrk.headers["Content-Type"] = "application/json"
wrk.headers["Authorization"] = "Bearer eyJhbGciOiJ..."
sh
wrk -t8 -c200 -d30s -s post.lua http://localhost:8080/api/link/create
2. 动态参数(随机化请求)
lua
-- random_param.lua
math.randomseed(os.time())
-- 每次请求前调用,修改请求路径
request = function()
local suffix = math.random(1, 100000)
local path = "/link/" .. suffix
return wrk.format("GET", path)
end
3. 统计响应(done 钩子)
lua
-- stats.lua
local counter = 0
local errors = 0
response = function(status, headers, body)
counter = counter + 1
if status ~= 200 then
errors = errors + 1
end
end
done = function(summary, latency, requests)
io.write("Total requests: " .. counter .. "\n")
io.write("Error responses: " .. errors .. "\n")
io.write("P99 latency: "
.. latency:percentile(99) / 1000 .. "ms\n")
end
4. 可用的 Lua 钩子函数
| 函数 | 触发时机 | 用途 |
|---|---|---|
| setup(thread) | 每个线程启动时 | 初始化线程私有数据 |
| init(args) | 线程开始前 | 解析命令行参数 |
| request() | 每次发请求前 | 动态构造请求 |
| response(s,h,b) | 收到响应后 | 处理/统计响应 |
| done(sum,lat,req) | 测试结束 | 自定义输出统计 |
参数详解
| 参数 | 说明 | 示例 |
|---|---|---|
| -t N | 线程数 | -t 8 |
| -c N | 并发连接数 | -c 400 |
| -d T | 持续时间 | -d 30s / -d 2m |
| -s file | Lua 脚本路径 | -s post.lua |
| --latency | 输出延迟分布(P50/P75/P90/P99) | --latency |
| --timeout T | 请求超时时间 | --timeout 5s |
| -H "header" | 添加请求头 | -H "Authorization: Bearer xxx" |
| --version | 查看版本 | --version |
推荐固定加上 --latency,默认输出不含延迟分布,这个参数让你看到 P50/P75/P90/P99。
sh
# 添加请求头
wrk -t8 -c200 -d30s --latency \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_token" \
http://localhost:8080/api/link/abc123
场景示例
短链重定向(GET)
sh
# 基准测试 - 不带缓存
wrk -t8 -c200 -d30s --latency \
http://localhost:8080/link/abc123
# 对比:开启 Caffeine 本地缓存后
wrk -t8 -c200 -d30s --latency \
http://localhost:8080/link/abc123
你之前跑出的数据:baseline QPS ~23,896 / P99 13.03ms → Caffeine 后 QPS ~25,114 / P99 5.69ms(P99 降低 56%)
带 Token 的 API 接口
sh
wrk -t8 -c100 -d30s --latency \
-H "Authorization: Bearer eyJ..." \
-H "Content-Type: application/json" \
http://localhost:8080/api/user/info
POST 创建接口(Lua 脚本)
sh
# 先创建 create_link.lua
cat > create_link.lua << 'EOF'
wrk.method = "POST"
wrk.body = '{"originUrl":"https://example.com","gid":"gid001"}'
wrk.headers["Content-Type"] = "application/json"
wrk.headers["Authorization"] = "Bearer your_token"
EOF
# 运行
wrk -t4 -c50 -d30s --latency \
-s create_link.lua \
http://localhost:8080/api/link/create
逐步加压找瓶颈
sh
# 梯度压测脚本
for c in 50 100 200 400 800; do
echo "--- 并发连接: $c ---"
wrk -t8 -c$c -d15s --latency \
http://localhost:8080/link/test
sleep 5
done
当 QPS 不再随 -c 增长甚至下降时,即为当前配置的性能上限。
推荐配置
-
本机测试
shwrk -t$(sysctl -n hw.logicalcpu) -c200 \ -d30s --latency \ http://localhost:8080/ -
远程服务
shwrk -t4 -c100 \ -d30s --timeout 5s \ --latency http://s.xmon.me/