乐于分享
好东西不私藏

彻底搞懂 wrk:HTTP 压测神器,用过的人都说好

彻底搞懂 wrk:HTTP 压测神器,用过的人都说好

大家好,我是小康。

前言

你有没有遇到过这种情况——

代码写完了,功能测试也过了,信心满满上线,结果一遇到真实流量,服务直接崩了?

或者老板问你:”这个接口能抗多少并发?”你支支吾吾说不出来……

这就是不做压测的代价。

今天就带大家认识一款 C/C++ 开发者必须掌握的压测神器——wrk

一、什么是 wrk?

wrk 是一款高性能的 HTTP 压测工具,使用 C 语言编写,底层基于 epoll/kqueue 实现异步 I/O,用极少的线程就能产生巨大的并发压力。

相比 Apache Bench(ab)、JMeter 这些老牌工具,wrk 的优势非常明显:

工具
语言
并发模型
脚本支持
性能
ab
C
多线程/多进程
一般
JMeter
Java
多线程
较低
wrk C 异步 I/O + 多线程 ✅(Lua) 极高

一句话总结:wrk 用 8 个线程,就能打出几万 QPS 的压力,是压测界的”轻量级格斗冠军”。

二、安装 wrk

Linux(Ubuntu/Debian)

sudo apt-get install build-essential libssl-dev git -ygit clone https://github.com/wg/wrk.gitcd wrkmakesudo cp wrk /usr/local/bin

Linux(CentOS/RHEL)

sudo yum groupinstall 'Development Tools'sudo yum install openssl-devel gitgit clone https://github.com/wg/wrk.gitcd wrkmakesudo cp wrk /usr/local/bin

macOS

brew install wrk

安装完成验证:

wrk --version# wrk 4.2.0 [epoll] Copyright (C) 2012 Will Glozer

看到版本号,说明安装成功 ✅

三、快速上手:第一个压测命令

wrk -t4 -c100 -d30s http://127.0.0.1:8080/api/hello

参数解释:

参数
含义
-t4
使用 4 个线程
-c100
保持 100 个并发连接
-d30s
压测持续 30 秒

输出结果长这样:

Running 30s test @ http://127.0.0.1:8080/api/hello  4 threads and 100 connections  Thread Stats   Avg      Stdev     Max   +/- Stdev    Latency     2.34ms    1.12ms  45.23ms   89.45%    Req/Sec     11.23k     1.45k   14.56k    72.34%  1344872 requests in 30.05s, 213.45MB readRequests/sec:  44754.23Transfer/sec:      7.10MB

怎么看这份报告?

  • Latency(延迟):平均 2.34ms,最大 45.23ms,说明大部分请求响应很快,偶尔有毛刺
  • Req/Sec:每秒每线程处理的请求数,乘以线程数就是总 QPS
  • Requests/sec: 44754.23:这就是最终答案——这台服务器每秒能处理约 4.4 万次请求
  • Transfer/sec:每秒传输的数据量,用来评估带宽消耗

四、常用参数详解

wrk [选项] <URL>选项:  -t, --threads     线程数(建议设置为 CPU 核心数的 2~4 倍)  -c, --connections 并发连接数(连接数 >= 线程数)  -d, --duration    压测持续时间(10s, 2m, 1h)  -s, --script      加载 Lua 脚本  -H, --header      添加请求头,如 -H "Authorization: Bearer xxx"      --latency     打印延迟分布(P50/P75/P90/P99)      --timeout     请求超时时间(默认 2s)

关于线程数怎么设置?

经验法则:线程数 = CPU 逻辑核心数 连接数远大于线程数时,单线程会复用连接,充分利用 epoll 异步 I/O

# 查看 CPU 核心数nproc# 比如是 8 核,就设 -t8

五、实际常见用法大全

5.1 最简单的 GET 请求压测

wrk -t8 -c200 -d30s --latency http://127.0.0.1:8080/

加上 --latency 会输出延迟百分位分布:

  Latency Distribution     50%    1.23ms     75%    2.45ms     90%    4.56ms     99%   12.34ms

P99 = 12.34ms 意味着 99% 的请求都在 12.34ms 内响应,这个指标在生产环境中非常重要。

5.2 带自定义请求头的压测

wrk -t4 -c100 -d30s \  -H "Authorization: Bearer your_token_here" \  -H "Content-Type: application/json" \  http://127.0.0.1:8080/api/user/info

5.3 POST 请求压测(Lua 脚本)

wrk 原生不支持直接指定 POST body,需要用 Lua 脚本

创建文件 post.lua

-- post.luawrk.method = "POST"wrk.body   = '{"username":"test","password":"123456"}'wrk.headers["Content-Type"] = "application/json"

执行:

wrk -t4 -c100 -d30s -s post.lua http://127.0.0.1:8080/api/login

5.4 动态参数压测(每次请求参数不同)

真实场景下,你肯定不希望每次都发同一个请求——缓存可能会让结果失真。

创建 dynamic.lua

-- dynamic.lualocal counter = 0request = function()    counter = counter + 1localpath = "/api/item?id=" .. counterreturn wrk.format("GET"path)end

执行:

wrk -t4 -c100 -d30s -s dynamic.lua http://127.0.0.1:8080

每次请求的 id 都不一样,模拟真实随机流量,压测结果更有参考价值。

5.5 随机 User-Agent 模拟多端访问

-- random_ua.lualocal agents = {"Mozilla/5.0 (Windows NT 10.0; Win64; x64)","Mozilla/5.0 (iPhone; CPU iPhone OS 15_0)","curl/7.68.0","PostmanRuntime/7.29.0"}request = function()local ua = agents[math.random(#agents)]    wrk.headers["User-Agent"] = uareturn wrk.format(nilnilnilnil)end

5.6 先登录拿 Token,再压测需鉴权接口

这是生产中最常见的需求,分两步走:

Step 1:手动获取 token

curl -X POST http://127.0.0.1:8080/api/login \  -H "Content-Type: application/json" \  -d '{"username":"admin","password":"admin123"}'# 返回:{"token":"eyJhbGci..."}

Step 2:写 Lua 脚本带上 token

-- auth_test.luawrk.method = "GET"wrk.headers["Authorization"] = "Bearer eyJhbGci..."wrk.headers["Content-Type"]  = "application/json"
wrk -t4 -c200 -d60s -s auth_test.lua http://127.0.0.1:8080/api/orders

5.7 压测结果统计(自定义 done 回调)

-- stats.lualocal requests_ok  = 0local requests_err = 0response = function(status, headers, body)ifstatus == 200then        requests_ok = requests_ok + 1else        requests_err = requests_err + 1endenddone = function(summary, latency, requests)print("---------- 自定义统计 ----------")print(string.format("成功请求: %d", requests_ok))print(string.format("失败请求: %d", requests_err))print(string.format("P50延迟:  %.2fms", latency:percentile(50) / 1000))print(string.format("P99延迟:  %.2fms", latency:percentile(99) / 1000))print("--------------------------------")end

5.8 多接口轮询压测(模拟混合流量)

-- multi_path.lualocal paths = {"/api/user/list","/api/order/query","/api/product/detail?id=1","/health"}request = function()localpath = paths[math.random(#paths)]return wrk.format("GET"path)end

模拟真实生产环境下多个接口同时被访问的场景,比单接口压测更接近实际情况。

5.9 阶梯压测脚本(手动模拟流量爬升)

wrk 本身不支持阶梯并发,但可以用 shell 脚本模拟:

#!/bin/bash# step_load.shURL="http://127.0.0.1:8080/api/hello"for conn in 10 50 100 200 500 1000; doecho">>> 并发连接数: $conn"    wrk -t4 -c$conn -d15s --latency $URL | grep -E "Req|Latency|requests"echo""    sleep 3done

这样就能看出服务在不同并发下的性能曲线,快速找到性能拐点

六、压测报告怎么分析?

光会跑还不够,更重要的是看懂数据

Thread Stats   Avg      Stdev     Max   +/- Stdev  Latency     2.34ms    5.12ms  245.23ms   95.67%  Req/Sec     5.23k     1.23k    8.45k     68.34%Socket errors: connect 0, read 12, write 0, timeout 3Non-2xx or 3xx responses: 45

几个关键信号:

🔴 Socket errors 不为零 → 说明服务扛不住了,出现了连接拒绝、读写失败或超时

🔴 Non-2xx or 3xx responses 有值 → 服务返回了错误,要检查服务端日志

🟡 Latency 的 Stdev 很大 → 延迟波动剧烈,服务不稳定,可能存在 GC、锁竞争等问题

🟡 Max 延迟远大于 Avg → 存在长尾延迟,说明某些请求会被”卡住”

🟢 Stdev 小、P99 接近 P50 → 服务稳定,延迟可预期,是优秀服务的表现

七、wrk 的局限性

用了这么久 wrk,它的坑也得说清楚:

  1. 只支持 HTTP/HTTPS,不支持 TCP、WebSocket、Unix Domain Socket 等协议
  2. 不支持 HTTP/2(官方维护较少)
  3. 不支持 Windows(只能在 Linux/macOS 上跑)
  4. 不支持分布式压测,单机并发上限受限于本机资源
  5. Lua 脚本功能有限,复杂场景编写麻烦
  6. 没有图形化界面,结果需要自己解读

八、进阶推荐:wrk 不够用了怎么办?

说到 wrk 的局限,忍不住给大家推荐一个更强的工具——

hbench:这是我自己用 C++ 从零实现的一款高性能 HTTP 压测工具。

为什么要造这个轮子?因为在实际项目开发中,我们经常遇到这些场景:

  • 要压测基于 Unix Domain Socket 的本地 IPC 服务
  • 要压测裸 TCP 协议的自定义服务
  • 要在同一个工具里统一压测 HTTP 和非 HTTP 服务

wrk 统统搞不定,而 hbench 全部支持hbench课程链接wrk 压不了 TCP?我用 2000 行纯 C 手撸了一个能压三种协议的压测工具

对于做 C++ 后端、网络编程的同学来说,hbench 是比 wrk 更全能的压测工具,而且源码比wrk更容易学习,可以直接学习其中的 epoll 异步模型、连接池设计、统计模块实现,一份代码,学到工业级工程经验。

九、总结

今天我们系统学习了 wrk 的用法:

  • ✅ wrk 基本原理与安装
  • ✅ 核心参数详解
  • ✅ GET/POST/带 Token/随机参数等常见场景
  • ✅ Lua 脚本进阶用法
  • ✅ 压测报告解读方法
  • ✅ wrk 局限性与替代方案

压测这件事,能帮你在上线前把问题暴露出来,而不是等到用户投诉才发现。 建议每个后端项目在上线前都跑一遍压测,把 QPS 上限、P99 延迟、错误率这三个指标摸清楚。

附:课程推荐

如果你读完这篇还觉得 C、C++、Linux 有些陌生,别急——我也开设了这三门入门课程,从零带你打好地基,快速上手项目实战:

感兴趣可以了解一下。

如果你已经有一定基础,想冲击更高的天花板,那下面这些工业级 C++ 项目正是为你准备的:

C++ 项目课程列表:

项目
亮点
线程池
并发基础设施,从原理到实现
高性能日志库 MiniSpdlog
对标 spdlog,异步无锁
高性能内存池
彻底告别 malloc 瓶颈
多线程下载工具
分片 + 并发实战
MySQL 连接池
数据库高并发必备
内存泄漏检测器
Hook malloc/free 原理
ReactorX
高性能事件驱动框架(就是本文的 epoll 升级版)
无锁栈

 / 无锁队列(SPSC/MPMC)
无锁编程精髓
工业级智能指针(shared_ptr)
手写工业级智能指针
高性能网络库 NetCore
从 epoll 到完整框架
高性能异步日志库 ZephyrLog
异步 + 无锁
死锁检测工具
图算法实战
高性能 HTTP 服务器
性能吊打大多数开源项目
协程库 CoroForge
对标微信 libco
高性能 HTTP 压测工具
支持 TCP、HTTP、Unix Domain Socket
Redis 核心模块实战
从 0 到 1 实现 Redis 全部核心模块

每一个项目都是工业级实现,代码量从几百行到几千行不等,覆盖高并发、网络编程、内存管理、无锁数据结构等核心方向。

👉 详情点击 C++ 项目合集课程链接为什么同样是”学过C++”,有人面试碾压,有人开口就怂?差距在这18个C++硬核项目

觉得有用的话,点赞、推荐、转发给你的同事,让更多人在上线前把服务压垮在测试环境里,而不是生产环境 😄

有问题欢迎在评论区留言,我都会回复。

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » 彻底搞懂 wrk:HTTP 压测神器,用过的人都说好

猜你喜欢

  • 暂无文章