☰
wrk压测工具已编译tar.gz包:解压即用的轻量级HTTP压测指南
2026/10/2 4:43:58 网站建设 项目流程

简介:wrk.tar.gz 内含已编译好的 wrk 高性能 HTTP 压测工具,解压即可在终端直接运行,无需额外编译,面向需要快速评估 Web 服务器、API 或负载均衡器性能的开发与运维人员。压缩包约 214MB,以可执行文件为主,结构精简,便于部署到目标环境直接使用,目前已有 258 人浏览学习。wrk 基于 LuaJIT,支持通过 -c、-d、-t、-r、-s 等参数灵活控制并发连接数、测试时长、线程数、请求速率和自定义脚本,可模拟不同请求模式并校验响应状态,适用于常规压测与复杂场景模拟。运行后会输出每秒请求数、平均传输速率以及延迟百分位统计等关键指标,帮助定位服务瓶颈。借助这份已编译工具,使用者可省去手动编译和依赖配置环节,快速开展基准测试、配置对比或上线前压力验证,尤其适合日常接口压测和性能调优场景。

1. wrk.tar.gz 压测工具到手就能用:为什么这份已编译包值得留一份

要说 wrk 这个压测工具,最让我上头的不是它压得有多猛,而是它从来不折腾人。tar.gz 解压完就是可执行文件,这在动不动就要装一堆依赖的压测工具里是个异类。这份 wrk.tar.gz 已经编译完,解决的是我压测路上最烦的一道坎:安装环境。以前我每次从源码编译 wrk,都会被 OpenSSL 版本不对、缺少头文件这类问题卡住,半小时起步,压测还没开始人就累了。现在拿到 tar.gz 包,解压、验证、开压,三分钟以内就能跑出第一份压测报告。它适合谁呢?后端开发、测试、运维,只要你的服务器是 Linux x64 架构,这份包解压即用。

2. 直接解压已编译的 wrk 包:从安装到跑出第一份压测报告

wrk 本身的定位就是轻量级 HTTP 压测工具,单文件、事件驱动、基于 epoll,压中小型接口完全够用。我之所以坚持用它而不是 JMeter,原因就两个字:快。启动快、出报告快,命令行敲完就已经在压了。而这份包已经把编译产物打包成 tar.gz,意味着你不需要在目标机器上碰编译器,这正是下面三步要走的路。

2.1 源码编译的痛点与已编译包的选择

wrk 源码编译本身不复杂,官方仓库里 make 一把过。但这是理想情况,实际服务器上你可能会碰到三条拦路虎:第一,最小化安装的系统没有 gcc / make;第二,wrk 需要 openssl 的开发头文件,很多线上机器只装了 openssl 运行时,没装 -devel 包;第三,内网机器连不上外网,clone 源码都费劲。这些场景叠加起来,源码编译的半小时就是这么耗掉的。

所以我现在拿到一台新机器,第一反应是找有没有编译好的产物。tar.gz 格式的好处是保留了可执行权限和目录结构,解压到哪都能跑,不需要 root,不需要改系统配置。对于 Linux x64 环境的服务器,这份包基本是通用件,只要 glibc 版本不是特别老,跑起来没有悬念。

# 源码编译 wrk 才需要,已编译包可整体跳过 yum install -y gcc make openssl-devel

这行命令是源码编译路线的前置条件。注意是 openssl-devel 而不是 openssl,区别在于后者不含编译用的头文件。真要在新机器上源码编译,先把这三样装好再继续。为什么已编译包能跳过这步?因为 wrk 运行时只依赖系统的 glibc 和 OpenSSL 运行库,这两样在绝大多数 Linux 发行版里都是默认存在的,尤其 OpenSSL,几乎任何跑着 Web 服务的机器都有。这就是“已经编译完”四个字最值钱的地方。

2.2 解压、部署与运行验证

下载下来的 tar.gz 包,第一步是解压到一个固定目录。我习惯放在 /usr/local 下面,和手写安装的软件放一起,找起来方便。如果你对系统目录有洁癖,放 /opt/wrk 或者当前用户的 ~/bin 也完全没问题。

# 解压到 /usr/local 并建立软链接 tar -xzf wrk.tar.gz -C /usr/local/ ln -s /usr/local/wrk/wrk /usr/local/bin/wrk wrk --version

tar 的 -xzf 三个参数分别是解压、从 gzip 格式还原、指定文件名;-C 指定解压目标目录。解压完的目录里应该是一个 wrk 可执行文件,用 ln -s 做软链接把它暴露到 PATH 中。最后 wrk --version 验证是否能正常运行,正常会输出版本号和构建信息。

这一步最容易翻车的点不在解压,而在软链接。如果 /usr/local/bin 不在 PATH 里(有些环境变量精简过的系统会这样),wrk 命令会报 command not found。遇到这种情况别慌,直接看 /etc/profile 或 ~/.bashrc 的 PATH 设置,把 /usr/local/bin 加进去,或者干脆用 ./wrk 的方式运行。

# 检查动态库依赖是否完整 ldd /usr/local/bin/wrk

ldd 是排查运行环境的关键命令,它会列出可执行文件依赖的动态库。如果每一行都显示 found,说明在当前机器上可以直接跑;如果出现 not found,最常见的就是 libssl.so 找不到。这时候不要重新编译,先确认系统里有没有 openssl 运行时:which openssl。如果有,多半是库路径没指到,用 ldconfig -p | grep libssl 再确认一下。

另外多说一句,如果执行时直接报 cannot execute binary file: Exec format error,说明架构对不上。Linux x64 编译的包不能跑在 ARM 机器上,也不能跑在 32 位系统上,这个在第 4 章的避坑记录里会专门展开。

2.3 第一个压测命令:压测输出里的五个关键数字

环境就绪后,第一个压测建议拿本机服务试手,避免网络因素干扰判断。命令很简单:

# 4 线程、400 连接、压 30 秒 wrk -t4 -c400 -d30s http://127.0.0.1:8080/api/ping

-t 是线程数,-c 是连接数,-d 是压测时长,最后是目标 URL。四个参数定下了压测的基本盘:4 个线程、400 个并发连接、持续 30 秒。第一次跑建议用这个小配置,确认命令和服务都没问题,再上大并发。

跑完会在终端输出一份报告,字段长这样(数值取决于你的服务性能,这里看结构就行):

Running 30s test @ http://127.0.0.1:8080/api/ping 4 threads and 400 connections Thread Stats Avg Stdev Max +/- Stdev Latency 5.12ms 8.33ms 210.41ms 94.83% Req/Sec 96.21k 15.02k 118.37k 73.29% 2877450 requests in 30.00s, 461.25MB read Requests/sec: 95913.02 Transfer/sec: 15.38MB

五个关键数字分两组看。第一组是 Thread Stats 里的 Latency 和 Req/Sec,Latency 的 Avg 是平均延迟,Stdev 是标准差,Max 是最差一次,+/- Stdev 表示落在均值一个标准差内的请求占比;Req/Sec 是每个线程每秒处理的请求数。第二组是最后的 Requests/sec 和 Transfer/sec,前者是整个压测期间的综合吞吐,后者是网络吞吐。我一般先看 Requests/sec 判断整体能力,再看 Latency 的 Max 和 Stdev 判断稳定性。如果 Max 比 Avg 大两个数量级,并且 Stdev 很大,说明服务有长尾延迟,这时候 p99 才是真正要盯的指标。

3. wrk 压测参数怎么设:线程、连接、时长与 Lua 脚本

wrk 的参数少,但少不等于不用想。很多人压测喜欢一把梭,-t 加满、-c 拉满,结果压出来的数据自己都不信。参数设置背后是 wrk 的并发模型,把模型想清楚,参数就是水到渠成的事。

3.1 wrk 的并发模型:线程数与连接数的关系

wrk 基于 epoll 事件驱动,一个线程可以同时管理几百上千个连接,这和 Apache 那种一个连接一个进程的模型完全不同。所以千万不要把线程数当成并发数。wrk 里的并发数是 -c 控制的连接数,线程数只是分发事件的 worker 数量。

线程数怎么选?经验值是取 CPU 核数或 2 倍核数。wrk 官方默认线程数是 2,但那只适合低并发场景。压测的时候我在 8 核机器上常用 -t8,16 核机器上用 -t16。线程数超过核数后,多出来的线程只是增加上下文切换,吞吐不会变好,反而可能引入抖动。

参数含义第一次建议值调整方向
-t线程数CPU 核数吞吐上不去时,先看核数是否够用
-c并发连接数200每次增加 200-400,观察延迟变化
-d压测时长30s稳定性测试用 60s 以上
-sLua 脚本无POST / 自定义统计时必须用

这个表格是给新手的起步值。连接数才是决定并发压力的关键,逐步加到某个值后 Requests/sec 不再增长甚至下降,那个点就是这台服务的并发上限。关于阶梯加压的具体做法,第 6 章会专门演示。

3.2 用 Lua 脚本压测 POST 接口:方法与脚本模板

GET 压测只需要一条命令,但真实业务大部分是 POST。wrk 的 -s 参数支持加载 Lua 脚本,在请求发出前可以设置方法、请求头、请求体,这是 wrk 最容易被低估的能力。

-- POST 请求设置 wrk.method = "POST" wrk.headers["Content-Type"] = "application/json" wrk.body = '{"userId": 1024, "pageNo": 1}'

这段脚本只有三行,wrk 在构造每个请求时都会读取这三个变量:method 指定请求方法,headers 用 key-value 形式设置请求头,body 是请求体字符串。注意 body 里的 JSON 用了单引号包裹双引号,避免 Lua 字符串转义把 JSON 搞坏。

# 用 post.lua 压测 POST 接口 wrk -t4 -c200 -d60s -s post.lua http://127.0.0.1:8080/api/query

-s 后面跟脚本路径,脚本在启动时加载一次,之后所有请求都复用这套设置。这里把并发降到 200,时长拉到 60 秒,是因为 POST 接口通常涉及业务逻辑处理,负载压力比静态页重,第一次跑用保守参数更安全。

如果只是想压 POST,上面三行就够了。但真实压测里还有个大坑:wrk 默认只要 socket 层面正常收发完,4xx、5xx 都算成功请求,报告里 errors 永远是 0。所以我在压测接口时一定会带上状态码统计脚本:

-- 统计每个状态码出现次数 local errorCount = 0 local statusCount = {} function response(status, headers, body) statusCount[status] = (statusCount[status] or 0) + 1 if status ~= 200 then errorCount = errorCount + 1 end end function done(summary, latency, requests) io.write("非200响应数量: " .. errorCount .. "\n") for k, v in pairs(statusCount) do io.write("状态码 " .. k .. ": " .. v .. "\n") end end

response 回调在每次请求响应后触发,第一个参数就是 HTTP 状态码。这里用 statusCount 表统计每个状态码的出现次数,同时把非 200 的数量累加。done 回调在整个压测结束后执行,把统计结果打到终端。这样压测报告里就能直接看到 500、502 有多少,而不是被“0 errors”骗过去。这两个脚本我一般放在项目的 benchmark 目录下,和压测命令写在一起,方便后续回归对比。

3.3 压测结果怎么看:延迟分布与吞吐量的评估标准

wrk 到手的报告默认只有 Latency 的 Avg、Stdev、Max,想深入看分布,必须在命令里加 --latency。加完之后,报告尾部会多出一张延迟分布表,p50、p75、p90、p99、p99.99 都在里面,这是判断长尾延迟最直接的依据。

# 加 --latency 输出延迟百分位 wrk -t4 -c400 -d30s --latency http://127.0.0.1:8080/api/ping

--latency 让 wrk 在内存里记录每个请求的延迟时间,压测结束前分桶统计出百分位。代价是压测机要多占一点内存和 CPU,做深度分析时建议开,日常快速冒烟可以不开。

我一般会把指标拆成三层看:第一层看 Requests/sec 和 Transfer/sec,判断系统的最大吞吐;第二层看 Req/Sec 的 Stdev,如果 Stdev 超过均值的 20%,说明流量波动大,服务可能在临界点附近抖动;第三层看 Latency 的 p99 和 Max,一旦 p99 超过接口的超时阈值,就说明有一部分请求已经让用户等待到不可接受的程度。

评估标准不固定,但有一条底线:p99 不能超过下游超时时间,吞吐必须满足业务峰值预期。比如一个接口要求 p99 小于 200ms、峰值吞吐 1 万 QPS,那就压到 1 万 QPS 以上再看延迟是不是还稳。如果吞吐到 8000 时延迟已经开始飙升,说明容量瓶颈就在 8000 附近。

提示:wrk 压测结果受压测机性能影响很大。如果压测机 CPU 已经跑满,Requests/sec 会先于被测服务到达瓶颈,这组数据只能作为下限参考,不能作为容量结论。

4. wrk 压测避坑:5 条高频问题排查记录

下面 5 条都是我在真实环境里踩过的,每条按现象、原因、解决的顺序写,方便你对号入座。

4.1 连接数上不去:一堆 connection refused

现象很直接:wrk -c1000 一启动,终端就开始刷屏 connect: Connection refused,或者读到大量 Connection reset。明明服务端已经确认在监听,但并发一上来就是连不上,这种情况压测新手期至少会碰到几次。

原因几乎都是同一个:文件描述符不够。Linux 默认的 ulimit -n 是 1024,wrk 要建立 1000 个连接,加上进程自身的标准输入、输出、日志等文件描述符,直接撞到硬上限。连接数超过上限后,socket 创建失败,内核直接返回 Connection refused,压测从启动那刻就开始崩。

解决分两步走。临时生效用 ulimit -n 65535,执行后当前 shell 会话内的进程都拿到新限制,但重登就失效;永久生效改 /etc/security/limits.conf,追加下面两行,然后重新登录。如果服务是 systemd 管理的,还要在 service 文件里补一句 LimitNOFILE=65535,否则限制不会抬起来。

# 临时抬高当前会话的文件描述符限制 ulimit -n 65535
# 永久抬高文件描述符限制 * soft nofile 65535 * hard nofile 65535

ulimit 命令只作用于当前会话,limits.conf 里的 soft 和 hard 分别表示软限制和硬限制,星号表示对所有用户生效。改完最好重新登录一次,让会话重新加载限制。

4.2 wrk 自己先饱和:线程数拍脑袋设

现象:wrk 压测时压测机 CPU 被 wrk 打到 100%,被测服务 CPU 才 30%,但吞吐就是上不去。这时候你可能会怀疑服务配置,其实问题出在 wrk 自己身上。

原因:wrk 线程数设得太低,事件循环处理不过来。wrk 在单线程下虽然能撑很多连接,但请求解析、Lua 回调、网络读写全在一个线程里跑,单核 CPU 就是天花板。

解决:把线程数从 -t1 提到 -t8 或 -t16,观察 wrk 的 CPU 占用回落。如果 wrk 各线程分布均匀且没有跑满,说明瓶颈已经回到被测服务这边。线程数不是越大越好,超过核数后收益递减,还会增加调度开销。

4.3 报告无错误但业务在报错:状态码没进统计

现象:wrk 报告显示 0 errors,后台监控却显示大量 5xx。两份数据打架,压测的人容易蒙圈。

原因:wrk 对 HTTP 状态码不敏感,只要 socket 层面完成了请求响应,就算一次成功请求。404、500、502 全都算成功,所以“0 errors”只能说明没有连接层错误,不能代表业务成功率高。

解决:用 3.2 里的 status.lua 脚本统计状态码分布,把非 200 状态单独统计。从那次以后,我压测任何接口都默认带上这个脚本,不带不敢信报告。

4.4 结果忽高忽低:压测机资源被占

现象:两次压测参数完全一样,第一次 Requests/sec 35000,第二次 22000,Latency Stdev 也差很多。同一台机器前一天稳定,后一天就像换了台机器。

原因:压测机和被测服务共用一台机器,或者压测机上有其他任务在跑。wrk 是单进程工具,压测机本身被干扰,结果必然抖动。这种情况在开发机、共用测试环境里尤其常见。

解决:压测先后台跑 top 确认压测机空闲,压测过程中再开一个终端盯 CPU 使用率。最好把 wrk 放在独立机器上,被测服务放另一台,中间走内网。如果条件有限,至少在压测期间停掉开发机上的其他重任务。

4.5 二进制无法运行:架构不匹配

现象:把包拷到一台服务器上,执行 ./wrk 报 cannot execute binary file: Exec format error。命令存在、权限也对,但就是跑不起来。

原因:包是 Linux x64 编译的,目标机器是 ARM 或 32 位系统。wrk 是 C 编译产物,不像 Java 或 Python 那样跨平台,架构不对就是跑不了。

解决:先确认架构:uname -m。x86_64 对应 x64 包,aarch64 需要单独找 ARM 版本。下载前先对一下目标机器的架构,这是最省事的做法。

5. 不同压测场景的参数参考:从静态页到登录接口

参数没有万能公式,但按场景分类可以给你一个安全起点。下面这张表是我在不同项目里常用的起步参数,压测时先按表试跑一轮,再根据结果微调。

5.1 按接口类型选参数:一张参考表加三条调整原则

场景线程 -t连接 -c时长 -d说明
静态资源页420030s静态页吞吐高,短时长足够看基线
列表查询接口420060s涉及 DB 查询,给 60s 观察长尾
登录/鉴权接口410030s涉及密码校验和令牌签发,保守起步
写操作接口25030s写库/写缓存要控制压力,防脏数据
复杂聚合接口840060s多重依赖,需要大连接数压出瓶颈

三条调整原则:第一,先默认跑一轮,观察错误数和延迟,有报错就把并发砍半;第二,逐步加并发,每次加 100-200,等一个稳定周期再记录;第三,接口有唯一性校验或幂等要求的,先想清楚请求体构造,别把脏数据写进生产库。

5.2 压测机与被测服务的资源隔离

大部分 wrk 结果失真,根源都在同一句话:压测机和被测服务抢资源。wrk 跑在应用服务器上,压出的延迟里一半是自己的 CPU 排队时间,这种报告没有参考意义。

隔离做三件事:第一,wrk 放独立机器,至少不能是提供服务的应用节点;第二,压测机和被测机走内网,不要过公网网关,公网延迟会把 wrk 的结果噪声放大;第三,压测过程中在两端都开一个 top 观察窗口,压测机 CPU 超过 80%、被测机 CPU 跑满,都要及时记录,因为这意味着数据已经接近失真。

5.3 用 wrk 做版本回归对比的三个固定项

同一个接口,版本升级前后各压一次,对比吞吐和延迟,这是最常用的性能回归方式。但 wrk 是命令行工具,变量控制不好,压出来的差异可能只是噪声。

三个固定项:固定 wrk 参数,-t -c -d 一个不变;固定压测机,两台机器配置不同,结果没有可比性;固定 Lua 脚本,特别是请求体和请求头,业务逻辑有变另说。除此之外,我习惯每个版本跑三遍,取 Requests/sec 的中位数而不是平均值,因为 wrk 偶尔会出现一次冷启动偏高或系统抖动导致的低值,中位数抗噪能力更好。

如果两次版本的吞吐差异在 5% 以内,我倾向于认为是噪音,不进入性能告警;超过 10% 就要关注。这个阈值不是标准,但作为快速筛选足够用了。

6. 进阶:用阶梯加压找容量拐点,把压测沉淀成回归脚本

6.1 阶梯加压找容量拐点

单次压测只有一个并发档位,看不出服务的容量上限。我常用的做法是阶梯加压:从低并发开始,逐步增加,每次压完记录吞吐和延迟,观察 Requests/sec 随并发的变化曲线。曲线会出现一个明显的平台期,再往上加并发,吞吐不再增长甚至掉头,这个拐点就是当前服务的容量上限。

#!/bin/bash # 阶梯加压:200 到 1600 五档并发 for c in 200 400 800 1200 1600; do echo "=== 并发 ${c} ===" ./wrk -t8 -c${c} -d20s -s status.lua http://127.0.0.1:8080/api/list \ | grep -E "Requests/sec|非200|状态码 5" done

这个脚本会依次跑 200 到 1600 五档并发,每档 20 秒,记录吞吐和错误状态。grep 把关键行筛出来,避免终端输出被一堆线程统计淹没。跑完看哪个并发档位出现了吞吐下降或 5xx 增加,那个档位的前一档就是建议的运行水位。

6.2 把压测沉淀成回归脚本

拐点找到了,接下来的问题是让它可复现。我把 wrk 命令和 Lua 脚本固化成一个基准脚本,每次上线前都跑一遍,终端输出重定向到带时间戳的报告文件,方便和上一版对比。

#!/bin/bash # 固定并发 800,输出带时间戳的报告 ts=$(date +%Y%m%d_%H%M%S) ./wrk -t8 -c800 -d60s -s status.lua http://127.0.0.1:8080/api/list \ > "report_${ts}.txt" 2>&1 echo "报告已写入 report_${ts}.txt"

这里把并发固定在 800,依据是阶梯加压中已经确认这是这台服务的合理水位。60 秒时长让延迟分布数据更稳定,重定向到文件后,可以用 diff 或脚本提取关键指标做对比。

wrk 没有预热机制,第一次跑的数据偶尔会偏高或偏低,我一般在正式压测前先跑一个 10 秒的短压测当预热,然后立刻接着跑正式的 60 秒。这个习惯帮我剔除过不少假性结论。从那以后,我每次压测都强制走一遍阶梯加压,先预热再取数,报告文件按日期归档在 benchmark 目录里。wrk 这份已编译的 tar.gz 包帮我省下的时间,远不止安装那半小时,更重要的是压出来的数据终于能被团队信服了。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询