ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

wrk压测工具已编译tar.gz包:解压即用的轻量级HTTP压测指南

wrk压测工具已编译tar.gz包:解压即用的轻量级HTTP压测指南 简介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 --versiontar 的 -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/wrkldd 是排查运行环境的关键命令它会列出可执行文件依赖的动态库。如果每一行都显示 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/SecLatency 的 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 核机器上常用 -t816 核机器上用 -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 endresponse 回调在每次请求响应后触发第一个参数就是 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 是 1024wrk 要建立 1000 个连接加上进程自身的标准输入、输出、日志等文件描述符直接撞到硬上限。连接数超过上限后socket 创建失败内核直接返回 Connection refused压测从启动那刻就开始崩。解决分两步走。临时生效用 ulimit -n 65535执行后当前 shell 会话内的进程都拿到新限制但重登就失效永久生效改 /etc/security/limits.conf追加下面两行然后重新登录。如果服务是 systemd 管理的还要在 service 文件里补一句 LimitNOFILE65535否则限制不会抬起来。# 临时抬高当前会话的文件描述符限制 ulimit -n 65535# 永久抬高文件描述符限制 * soft nofile 65535 * hard nofile 65535ulimit 命令只作用于当前会话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第二次 22000Latency 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 21 echo 报告已写入 report_${ts}.txt这里把并发固定在 800依据是阶梯加压中已经确认这是这台服务的合理水位。60 秒时长让延迟分布数据更稳定重定向到文件后可以用 diff 或脚本提取关键指标做对比。wrk 没有预热机制第一次跑的数据偶尔会偏高或偏低我一般在正式压测前先跑一个 10 秒的短压测当预热然后立刻接着跑正式的 60 秒。这个习惯帮我剔除过不少假性结论。从那以后我每次压测都强制走一遍阶梯加压先预热再取数报告文件按日期归档在 benchmark 目录里。wrk 这份已编译的 tar.gz 包帮我省下的时间远不止安装那半小时更重要的是压出来的数据终于能被团队信服了。希望帮到你。本文还有配套的精品资源点击获取
返回列表