压力测试工具 wrk 的使用

FreeGuideOnline 最新 2026-07-08

bash

Ubuntu/Debian

sudo apt update sudo apt install build-essential libssl-dev git -y

CentOS/RHEL

sudo yum groupinstall 'Development Tools' sudo yum install openssl-devel git -y


然后从源码编译安装:

```bash
git clone https://github.com/wg/wrk.git
cd wrk
make
sudo cp wrk /usr/local/bin

在 macOS 上安装

使用 Homebrew 是最简单的方式:

brew install wrk

在 Windows 上使用

wrk 原生不支持 Windows,建议在 WSL (Windows Subsystem for Linux) 中安装 Linux 版本,或使用替代工具(如 bombardier、hey)。

安装完成后,在终端运行 wrk --version 确认安装成功。

基本用法

最简单的压力测试命令如下,它会使用 2 个线程、10 个并发连接,持续测试 10 秒:

wrk -t2 -c10 -d10s https://example.com

输出结果示例:

Running 10s test @ https://example.com
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    45.12ms   89.05ms   1.23s    89.12%
    Req/Sec     1.12k   312.43     2.21k    68.50%
  22345 requests in 10.01s, 2.78GB read
Requests/sec:   2232.15
Transfer/sec:    284.12MB

输出解读:

  • Latency:延迟,即每个请求的响应时间。
    • Avg:平均值。
    • Stdev:标准差,反映延迟的波动情况。
    • Max:最大延迟。
    • +/- Stdev:延迟分布在平均值±1个标准差范围内的请求百分比。
  • Req/Sec:每秒完成的请求数。
  • Requests/secTransfer/sec:整个测试周期内每秒完成的请求数与每秒传输的数据量。

常用命令行参数

参数 说明
-t, --threads <N> 使用的线程数。建议设置为 CPU 核心数的 2-4 倍。
-c, --connections <N> 保持打开的 HTTP 连接总数。每个线程均匀分配连接数。
-d, --duration <time> 测试持续时间,例如 -d 30s-d 1m
-s, --script <lua_script> 加载 Lua 脚本,用于自定义请求生成过程。
-H, --header <header> 在请求中添加额外的 HTTP 请求头,可多次使用。
--latency 打印详细的延迟分布信息(百分比)。
--timeout <time> 设置请求超时时间,如 --timeout 2s

使用示例:用 4 个线程、100 个连接测试 30 秒,并输出延迟分布。

wrk -t4 -c100 -d30s --latency https://api.example.com/v1/data

通过 Lua 脚本增强测试

wrk 的强大之处在于可以通过 Lua 脚本在请求的三个生命周期阶段(setup、running、done)注入自定义逻辑。脚本中的 wrk 全局对象提供了 setupinitrequestresponsedelaydone 等函数。

创建动态请求

例如,每次请求携带一个随机的用户 ID 和自定义请求头:

-- random_request.lua
counter = 0

wrk.method = "POST"
wrk.body   = '{"key": "value"}'
wrk.headers["Content-Type"] = "application/json"

function request()
   local user_id = math.random(1, 100000)
   local path = "/api/user/" .. user_id
   counter = counter + 1
   -- 返回 wrk 请求路径,会覆盖命令行中的 URL 路径
   return wrk.format("GET", path, wrk.headers, wrk.body)
end

function done(summary, latency, requests)
   print("-------------------------")
   io.write("Script counter: " .. counter .. "\n")
end

运行:

wrk -t2 -c10 -d20s -s random_request.lua https://api.example.com

校验响应内容

使用 response 函数可以在每个响应返回时执行校验,并统计错误:

-- validate.lua
errors = 0
successes = 0

function response(status, headers, body)
   if status ~= 200 then
      errors = errors + 1
   elseif not string.find(body, "expected_text") then
      errors = errors + 1
   else
      successes = successes + 1
   end
end

function done(summary, latency, requests)
   io.write("Validation errors: " .. errors .. "\n")
   io.write("Successes: " .. successes .. "\n")
end

自定义延迟计算(忽略连接建立时间)

有时只关心服务器处理请求的延迟,可以在 setup 阶段标记请求发送时间:

-- precise_latency.lua
wrk.method = "GET"

function init(args)
   -- 用于存储每个请求发送时间戳的表
   req_time = {}
end

function request()
   local idx = 0 -- 这里可以使用线程安全的递增计数器,但简单演示
   -- 记录请求发送前的时间
   req_time[math.random(1,100000)] = socket.gettime()
   return wrk.format()
end

function response(status, headers, body)
   -- 实际处理中需要匹配对应的请求,这里仅为思路演示
end

高级技巧与注意事项

1. 合理设置线程与连接数

  • 线程过多会带来上下文切换开销,一般设置为 CPU 核心数的 2~4 倍即可。
  • 连接数直接影响并发压力,不要设置得过大,以免本地端口被耗尽或触及目标服务器的限制。
  • 逐步增加连接数,观察请求速率是否达到瓶颈,当请求速率不再线性增长时,说明目标服务或本地系统已到极限。

2. 针对 HTTPS 测试

wrk 使用 OpenSSL 进行 HTTPS 通信,测试时会消耗较多 CPU 资源。如果目的是测试应用层性能,可以考虑在本地使用反向代理(如 nginx)终结 TLS,然后用 wrk 压测 HTTP 端口,以排除加解密开销。

3. 监控目标服务器状态

压力测试的核心在于观察服务器行为。请务必在测试期间监控目标服务器的 CPU、内存、磁盘 I/O 以及应用级指标(如 QPS、错误率、响应时间分布)。不要仅依赖 wrk 的输出数字,因为它反映的是客户端视角。

4. 避免测试结果失真

  • 在局域网或同机器测试时,网络延迟极小,测试结果可能无法反映真实用户体验。
  • wrk 是单机负载生成器,如果目标服务非常强大,可能单台 wrk 机器无法压满其吞吐量,此时可使用多台机器同时发起测试,或使用分布式压力测试方案。

5. 使用预热和 ramp-up

wrk 不支持内置的逐步增加并发(ramp-up)功能。如果需要平滑增加负载,可以编写脚本多次调用 wrk,逐步增大 -c 参数,或者使用功能更丰富的工具如 k6。

6. 读懂百分位延迟

使用 --latency 参数可以获得延迟的百分位分布:

  Latency Distribution
     50%    7.12ms
     75%   10.23ms
     90%   14.55ms
     99%   35.10ms