简介:本资源为wrk-4.1.0的Linux版本安装包,面向需要进行Web服务器性能压测的开发者与运维人员。wrk是一款用C语言编写的高性能HTTP基准测试工具,擅长高并发、短连接场景下的压力测试,相比JMeter、ab等工具更轻量、更易扩展。压缩包为7z格式,整体约168.72MB,包内文件以源码及编译相关文件为主,需解压后编译生成可执行文件,并可通过Lua脚本定制请求头、请求体与请求间隔等复杂测试场景。资源配套内容涵盖安装编译、权限设置、基本命令与选项说明、Lua脚本用法及结果指标解析,并对比了wrk与JMeter、ab的适用差异,可帮助读者快速搭建压测环境、理解吞吐量与响应时间等关键指标,定位服务器性能瓶颈。目前已有586人学习下载,适合具备一定Linux基础、希望深入掌握HTTP性能测试的中高级用户参考。
1. 压测工具选型:为什么我最终把 wrk-4.1.0-linux 留在了服务器上
很多团队做性能测试的路径都差不多:先用 ab 跑个几百并发,发现压不上去,换 JMeter 画几张聚合报告,再往后遇到长连接和 HTTPS 场景又开始卡壳。我最早也是这么一路试过来的,直到某次排查一个接口在 8000 并发下的尾延迟问题,才真正把 wrk-4.1.0-linux 当成主力工具用起来。它解决的核心问题很直接:在单机上用极少的资源,把 HTTP 服务的吞吐和延迟压到一个足够真实的量级,同时给出可读的延迟分布,而不是只丢一个平均值给你。
wrk 属于事件驱动型压测工具,底层用 epoll 做多路复用,配合多线程和可选的 Lua 脚本扩展,单进程就能把一台普通 4 核机器的网络栈吃满。它适合谁?适合已经过了「接口能不能通」阶段、开始关心「QPS 天花板在哪、P99 抖不抖、长连接下会不会雪崩」的后端和运维同学。如果你还在用单线程工具跑 100 并发就以为测到了极限,那 wrk 大概率会刷新你的认知。这一篇就按「装起来 → 跑通 → 调参 → 避坑 → 进阶」的顺序,把 wrk-4.1.0-linux 这套东西讲透。
2. 把 wrk-4.1.0-linux 跑起来:编译、依赖与最小验证
2.1 为什么这个版本在 Linux 上要自己编译
wrk 官方并不总是提供现成的 Linux 二进制包,4.1.0 这个版本在很多发行版仓库里也没有直接收录,所以常见做法是拉源码自己编译。它的依赖非常干净:一个 C 编译器、make、以及 OpenSSL 开发库(如果要压 HTTPS)。相比那些需要 JVM、需要装一堆插件的工具,wrk 的编译过程基本不会翻车,前提是你把开发库装全。
先确认系统里有没有编译环境。下面这几条命令在主流发行版上都能用,按你的包管理器选一条执行即可。
# Debian/Ubuntu 系:装编译器和 OpenSSL 开发库 sudo apt-get update sudo apt-get install -y build-essential libssl-dev git # RHEL/CentOS 系:装对应的开发包 sudo yum groupinstall -y "Development Tools" sudo yum install -y openssl-devel git这里build-essential提供 gcc 和 make,libssl-dev是 HTTPS 压测的前提。如果你只压 HTTP,理论上可以不带 OpenSSL,但实际项目里 HTTPS 几乎躲不掉,建议一次装齐,省得后面重新编译。
2.2 编译安装与版本确认
拿到源码后进入目录,直接 make 即可。wrk 的 Makefile 写得比较克制,默认会链接系统 OpenSSL。
# 进入源码目录后编译,-j 后面跟 CPU 核数加速编译 make -j4 # 编译产物是当前目录下的 wrk 可执行文件 # 把它放到 PATH 里方便全局调用 sudo cp wrk /usr/local/bin/ # 确认版本,输出应包含 4.1.0 wrk --versionmake -j4里的 4 表示并行编译任务数,按你机器的核数调整,核多就写大一点。编译完成后不要急着跑压测,先执行wrk --version确认版本号,避免装了个旧版本还以为参数不生效。如果编译报 OpenSSL 相关的链接错误,八成是开发库没装或路径不对,回头检查libssl-dev/openssl-devel是否真的装上了。
2.3 最小可用压测命令与输出解读
先用一条最简单的命令验证工具链是否正常。找一个你确定能访问的测试接口,别一上来就打生产。
# -t 线程数 -c 连接数 -d 持续时间 最后跟目标 URL wrk -t4 -c200 -d30s http://127.0.0.1:8080/health跑完之后输出大致长这样,重点看四块:Requests/sec是吞吐,Latency是平均延迟,Stdev是延迟标准差,下面那几行50% / 75% / 90% / 99%才是真正决定体验的延迟分布。很多人只盯 Requests/sec,结果线上 P99 已经飙到几百毫秒还没察觉,这就是只看平均值的代价。-t4表示开 4 个线程,-c200表示维持 200 个连接,-d30s表示压 30 秒。线程数一般不要超过 CPU 核数,连接数则根据你要模拟的并发规模来定,这两个参数后面还会细说。
3. 参数怎么调:线程、连接、超时与脚本扩展
3.1 线程数与连接数的配比关系
wrk 的并发模型是「多线程 + 每线程一个事件循环」,每个线程内部用 epoll 管理自己那部分连接。所以-t决定的是并行的事件循环数量,-c决定的是总连接数,平均下来每个线程扛c/t个连接。这个比值直接决定了单线程的事件循环压力。
我的经验配比是这样的:4 核机器上-t4起步,-c从 100 开始,每次翻倍往上试,观察Requests/sec什么时候不再增长甚至回落。如果-c加到 2000 但吞吐反而掉了,说明瓶颈已经不在服务端,而在压测机自己的网络栈或文件描述符上限。这时候要做两件事:一是确认压测机的ulimit -n够大,二是别再无脑加连接数。
# 查看当前进程可打开的文件描述符上限 ulimit -n # 临时调高到 65535,只对当前 shell 生效 ulimit -n 65535文件描述符上限是压测里最容易被忽略的坑。每个连接占一个 fd,-c开到几千而ulimit -n还是默认的 1024,wrk 会直接报错或者连接建立失败,表现就是吞吐低得离谱,你还以为是服务端不行。
3.2 超时设置与延迟统计口径
wrk 默认的超时是 2 秒,这个值在高并发下经常不够用,尤其是被测服务有慢查询的时候。超时的连接会被计入错误,但 wrk 的错误统计不像某些工具那么显眼,容易漏看。
# --timeout 设置单次请求超时,单位可以是 s/ms wrk -t4 -c500 -d60s --timeout 5s http://127.0.0.1:8080/api/list # --latency 会打印更完整的延迟分布,排查尾延迟必加 wrk -t4 -c500 -d60s --latency http://127.0.0.1:8080/api/list--timeout 5s把超时放宽到 5 秒,适合被测接口本身响应偏慢的场景。--latency这个参数强烈建议每次都带上,它会额外输出最大值和更细的分位数,排查 P99 抖动时没有它基本等于盲人摸象。注意延迟统计是客户端视角的,包含了网络往返,所以压测机和被测服务如果在不同机房,这个数字会明显偏大,别拿它当服务端处理时间的绝对值。
3.3 用 Lua 脚本模拟真实请求
wrk 真正拉开差距的地方是 Lua 脚本扩展。默认它只会对同一个 URL 发 GET,但真实业务里往往要带 header、要 POST body、要参数化。wrk 内置了 LuaJIT,脚本写起来很轻。
-- post.lua:模拟带 JSON body 的 POST 请求 -- wrk.method / wrk.body / wrk.headers 是内置可写字段 wrk.method = "POST" wrk.body = '{"userId":123,"page":1}' wrk.headers["Content-Type"] = "application/json" wrk.headers["Authorization"] = "Bearer test-token" -- 每个请求发出前调用,可在这里做参数随机化 request = function() -- 用随机数避免服务端缓存命中,测出真实压力 local uid = math.random(1, 100000) local body = '{"userId":' .. uid .. ',"page":1}' return wrk.format("POST", "/api/query", nil, body) endwrk.method、wrk.body、wrk.headers是全局默认值,request函数则是每个请求的钩子,返回什么就发什么。上面用math.random随机化 userId,是为了绕开服务端可能存在的缓存,否则你压的其实是缓存而不是真实逻辑。wrk.format的四个参数依次是方法、路径、headers、body,headers 传 nil 表示沿用全局设置。脚本用-s加载:
wrk -t4 -c300 -d60s --latency -s post.lua http://127.0.0.1:8080/api/query注意 URL 里的路径会被脚本里的路径覆盖,所以脚本里写清楚目标路径就行,命令行 URL 主要提供 host 和端口。
4. 避坑与排查:那些让压测结果失真的细节
4.1 压测机自己先成了瓶颈
现象:-c加到 1000 以上,吞吐不升反降,CPU 里sys占比很高。原因通常是压测机的网络中断处理、fd 上限或者 wrk 线程数配置不合理,压测机先扛不住了。解决:先看top里 wrk 进程的 CPU 分布,如果sys远高于usr,说明大量时间花在系统调用上;把-t调到等于或略小于核数,同时确认ulimit -n足够大,必要时换一台配置更高的机器专门做压测端。
4.2 只压 localhost 导致结果虚高
现象:本地压 localhost 跑出几十万 QPS,换到真实网络环境直接掉一个数量级。原因是 loopback 不走物理网卡,省掉了协议栈和网卡的中断开销,数字好看但不真实。解决:压测机和被测服务尽量放在同一内网但不同机器上,至少跨一次真实网卡。如果只能本机压,心里要清楚这个数字是上限参考,不能直接当容量结论。
4.3 连接复用掩盖了握手开销
现象:压测结果很漂亮,但线上用户首次访问很慢。原因是 wrk 默认复用连接,测的是长连接下的稳态吞吐,而真实用户每次都要经历 TCP 握手甚至 TLS 握手。解决:如果业务是短连接场景,需要在脚本里主动关闭连接,或者用Connection: close头模拟;HTTPS 场景要意识到 wrk 的 TLS 会话复用同样会美化结果,评估时要留出握手余量。
4.4 忽略错误计数
现象:吞吐数字正常,但服务端日志里一堆 5xx。原因是 wrk 默认输出里错误信息不显眼,很多人只看 Requests/sec 就下结论。解决:压测结束后一定要看输出里的Socket errors和Non-2xx responses两行,非 2xx 的响应会被单独计数,如果这个数字不为零,说明你的吞吐是建立在失败请求上的,毫无意义。
4.5 持续时间太短导致数据不稳
现象:两次同样的命令,结果差 20% 以上。原因是-d太短,压测还没进入稳态就结束了,启动阶段的抖动被放大。解决:正式压测-d至少 60 秒,最好 120 秒以上,并且跑三轮取中间值。前 10 秒的数据基本可以当预热丢掉,wrk 本身不提供分段统计,但你可以通过延长总时长来稀释启动阶段的影响。
5. 进阶技巧:把 wrk 用成可复现的压测基线
5.1 用固定脚本固化压测场景
压测最大的敌人是「每次跑的条件都不一样」。我的习惯是把线程、连接、时长、脚本、目标 URL 全部写进一个 shell 脚本,每次压测只改版本号或环境变量,保证可比性。
#!/bin/bash # bench.sh:固定参数的压测基线脚本 TARGET=${1:-"http://127.0.0.1:8080/api/query"} THREADS=4 CONNS=500 DURATION=120s echo "target: $TARGET" echo "threads=$THREADS conns=$CONNS duration=$DURATION" # 跑三轮,人工对比稳定性 for i in 1 2 3; do echo "===== round $i =====" wrk -t$THREADS -c$CONNS -d$DURATION --latency --timeout 5s \ -s post.lua "$TARGET" sleep 10 # 轮次之间留冷却,避免服务端积压影响下一轮 done这个脚本的价值在于「可复现」。TARGET用参数传入,方便切换环境;三轮之间sleep 10是给服务端冷却,避免上一轮积压的请求影响下一轮。跑完把三轮的Requests/sec和99%延迟拉出来对比,如果波动超过 10%,说明要么环境不稳,要么压测参数还没到稳态,结论不能采信。
5.2 延迟分布比吞吐更值得盯
很多人做容量规划只问「能扛多少 QPS」,但真正影响用户体验的是尾延迟。wrk 的--latency输出里,99%那一行才是关键。我的判断标准是:如果 P99 超过平均延迟的 5 倍,说明系统里存在长尾,可能是 GC、锁竞争或者慢查询,这时候即使吞吐达标也不能上线。把 P50、P90、P99 三个值记下来,作为每次发版的对比基线,比单看一个 QPS 有用得多。
5.3 结合服务端指标交叉验证
wrk 给的是客户端视角,服务端的 CPU、内存、连接数、GC 日志要同步看。常见做法是压测时另开一个终端跑top、ss -s或者看应用的监控面板。如果客户端显示吞吐到顶了,但服务端 CPU 才 40%,那瓶颈大概率在压测机或者网络;反过来服务端 CPU 打满而吞吐上不去,才是真正的服务端瓶颈。两边对不上,先怀疑压测端,这是我踩过好几次坑之后养成的习惯。
5.4 一个容易忽略的收尾动作
压测跑完别急着关终端,先把输出重定向存下来。我一般会在脚本里加| tee result_$(date +%s).log,把每轮结果落盘。原因很简单:压测当时觉得数字都记住了,过两天要对比新版本时,翻聊天记录找不全。存成文件,配合版本号命名,才是能长期用的基线。这个习惯看起来琐碎,但真到要证明「这次优化到底有没有效果」的时候,它就是你的后悔药。
希望帮到你。
本文还有配套的精品资源,点击获取