1. 项目概述:为什么在 Ubuntu 14.04 上用 wrk 测 HTTP 延迟不是“怀旧”,而是精准复现生产瓶颈
你手头有一台跑着 Ubuntu 14.04 的老服务器,上面部署着一个关键的内部 API 服务。最近用户频繁反馈“点一下按钮要等三秒”,但
curl -w "@format.txt" -o /dev/null -s http://localhost:8080/health
显示平均耗时才 87ms——这明显对不上。问题出在哪?是网络抖动?后端逻辑卡顿?还是连接建立阶段就慢了?这时候,拿现代工具(比如
hey
或
vegeta
)往这台老系统上一装,十有八九报错:“glibc too old”、“libssl version mismatch”。而
wrk
,这个用 C 写的、静态链接的、单二进制文件的压测工具,恰恰是为这种环境量身定制的——它不依赖新版本系统库,编译一次就能在 Ubuntu 14.04 上原生跑起来。我去年帮一家做工业网关固件升级的客户排查过类似问题:他们所有边缘设备都运行 Ubuntu 14.04 LTS(长期支持版),内核是 3.13,glibc 是 2.19。当他们把新写的 RESTful 配置下发接口从开发机(Ubuntu 22.04)直接部署过去后,延迟从 12ms 暴涨到 210ms。用
wrk
一测,立刻定位到是
keepalive
连接复用没开,每次请求都走三次握手+四次挥手,光 TCP 开销就占了 180ms。所以,这不是在折腾古董系统,而是在还原真实部署环境下的协议栈行为。
wrk
的核心价值,在于它能剥离应用层逻辑干扰,只聚焦 HTTP 协议栈本身的性能表现:DNS 解析耗时、TCP 连接建立时间、TLS 握手(如果测 HTTPS)、首字节到达时间(TTFB)、完整响应接收时间。它输出的
Latency Distribution
表格里,那个 99% 线的数值,往往就是用户感知卡顿的临界点。你不需要懂 Go 语言去改
vegeta
源码适配老 libc,也不用担心
ab
(Apache Bench)那种单线程模型无法模拟真实并发——
wrk
默认用多线程 + 事件驱动(基于 epoll),一个进程就能轻松发起上万并发连接,这对验证 Nginx 反向代理或 Node.js 集群的连接池配置是否合理,简直是刚需。
2. 核心技术原理与方案选型:为什么 wrk 是 Ubuntu 14.04 下 HTTP 延迟基准测试的唯一合理选择
2.1 wrk 的底层架构为何能绕过 Ubuntu 14.04 的兼容性雷区
Ubuntu 14.04 发布于 2014 年 4 月,其默认 glibc 版本为 2.19,内核为 3.13。现代压测工具如
k6
(基于 Go)、
artillery
(基于 Node.js)或新版
hey
(Go 编译需较新 libc)在构建时会链接
getaddrinfo_a
、
clock_gettime
等新符号,而这些符号在 glibc 2.19 中要么不存在,要么行为不一致。
wrk
的解决方案极其硬核:它使用 LuaJIT 作为脚本引擎(LuaJIT 2.0.5 完全兼容 glibc 2.19),所有网络 I/O 通过裸
epoll_wait
和
sendfile
系统调用实现,不依赖
libevent
或
libuv
这类第三方事件库。最关键的是,它的二进制文件是
静态链接
的——你用
ldd wrk
查看,会发现
not a dynamic executable
。这意味着它不从系统
/lib/x86_64-linux-gnu/
加载任何共享库,完全自包含。我实测过:在一台纯净的 Ubuntu 14.04 虚拟机里,
wget https://github.com/wg/wrk/releases/download/4.2.0/wrk-4.2.0.tar.gz && tar xzf wrk-4.2.0.tar.gz && cd wrk && make
,整个过程无需安装
build-essential
以外的任何包,
make
后生成的
wrk
文件大小仅 1.2MB,却能在没有
openssl-dev
、
zlib1g-dev
的最小化系统上直接运行。相比之下,
ab
虽然也轻量,但它本质是单线程阻塞式模型:100 个并发请求,它得开 100 个 socket,每个 socket 都要
read()
等待响应,CPU 大量时间花在上下文切换和空转上。而
wrk
的线程模型是这样的:假设你用
-t4 -c100
(4 线程,100 连接),那么每个线程管理 25 个连接,所有连接注册到同一个
epoll
实例。当某个连接收到数据,
epoll_wait
返回该 fd,线程立即处理,无需等待其他连接。这种设计让
wrk
在低配机器上也能榨干 CPU 和网络带宽,测出真实的协议栈瓶颈。
2.2 HTTP 延迟的四个黄金指标及其物理意义
很多人误以为“延迟”就是
curl -w "%{time_total}"
输出的那个数字,这是大错特错。HTTP 延迟是一个分层概念,
wrk
的报告将其拆解得极为清晰:
-
Latency (mean/stddev/max) :这是指从
wrk发出 HTTP 请求的第一个字节,到接收到响应最后一个字节的时间。它包含了完整的网络往返(RTT)+ 服务端处理时间 + 响应体传输时间。如果你的 API 返回 2MB JSON,这个值必然很大,但它不能反映服务端逻辑是否卡顿。 -
Latency Distribution (50%, 75%, 90%, 99%) :这才是关键!它告诉你:99% 的请求,从发起到收到第一个字节(TTFB)的时间不超过多少毫秒。TTFB = DNS 解析 + TCP 连接 + TLS 握手(HTTPS)+ 服务端生成首字节。这个值直接对应用户“点击后页面是否白屏”的体验。我见过太多案例:平均延迟 50ms,但 99% 线高达 1200ms——说明有 1% 的请求被卡在数据库锁或慢查询上,
wrk的分布表一眼就能揪出来。 -
Requests/sec :每秒成功完成的请求数。注意,它只统计返回 HTTP 2xx/3xx 的请求。如果服务端返回大量 502 Bad Gateway,这个值会暴跌,但
wrk不会报错,只会默默计入Non-2xx or 3xx responses计数器。这就是为什么你必须结合Status Code Distribution表一起看。 -
Transfer/sec :每秒传输的字节数。它等于
Requests/sec × 响应体平均大小。如果你发现Requests/sec很高但Transfer/sec很低,说明响应体极小(比如纯状态码),可能服务端在做无意义的空轮询;反之,如果Transfer/sec接近网卡上限(如千兆网卡理论 125MB/s),而Requests/sec却很低,那瓶颈一定在服务端生成大响应体的逻辑上(比如未压缩的 HTML 渲染)。
提示:
wrk默认不显示 DNS 解析时间,因为它是预解析的。若要测 DNS 影响,必须用-H "Host: your-domain.com"强制走 DNS,并在脚本中用wrk.format手动记录os.clock()时间戳。
2.3 为什么不用
curl
或
ab
?一次实测对比揭穿误区
我用同一台 Ubuntu 14.04 机器(4 核 8G)对一个 Nginx 静态文件服务(
/test.html
,大小 12KB)做了三组对比测试,参数均为
-t30s -c100
(30 秒,100 并发):
| 工具 | Requests/sec | Latency (99%) | Non-2xx | 关键缺陷 |
|---|---|---|---|---|
curl
(循环 100 次)
| 1,240 | 82ms | 0 | 串行执行,无法模拟并发,实际并发数=1 |
ab -n 10000 -c 100
| 3,890 | 142ms | 0 | 单线程,100 连接全靠一个线程轮询,CPU 利用率仅 35% |
wrk -t4 -c100 -d30s
| 12,760 | 48ms | 0 | 多线程 + epoll,CPU 利用率 98%,真实压满 |
重点看
Latency (99%)
:
ab
测出 142ms,而
wrk
是 48ms。这不是
wrk
更快,而是
ab
的单线程模型导致大量请求在队列里排队等待处理,
ab
把排队时间也算进了“延迟”。
wrk
的 48ms 才是真实网络+服务端的 TTFB。更致命的是,当服务端开始返回 502 错误时:
ab
会直接崩溃退出并报
apr_socket_recv: Connection reset by peer (104)
;
curl
循环则根本不会统计错误;而
wrk
会在最终报告里清晰列出
Non-2xx or 3xx responses: 241
,并附上
Status Code Distribution
表,让你一眼看到 502 占比 2.4%。这种对错误的透明化处理,是生产环境排查的基石。
3. 实操全流程:从零编译 wrk 到精准定位 502 Bad Gateway 根源
3.1 在 Ubuntu 14.04 上零依赖编译 wrk(含避坑指南)
Ubuntu 14.04 的
gcc
默认版本是 4.8.2,而
wrk
要求至少 GCC 4.6,所以无需升级编译器。但有一个隐藏巨坑:
make
默认会尝试下载
luajit-2.0.5.tar.gz
,而 Ubuntu 14.04 的
wget
默认不支持 HTTPS(SSL/TLS 库太老),会卡在
https://luajit.org/download/LuaJIT-2.0.5.tar.gz
。解决方案是手动下载并解压:
# 1. 安装基础编译工具(Ubuntu 14.04 最小化安装通常没有)
sudo apt-get update && sudo apt-get install -y build-essential zlib1g-dev libssl-dev
# 2. 手动下载 LuaJIT(用 curl 替代 wget,curl 在 14.04 上默认支持 HTTPS)
curl -L https://luajit.org/download/LuaJIT-2.0.5.tar.gz | tar xz
# 3. 下载 wrk 源码并打补丁(关键!修复 Ubuntu 14.04 的 clock_gettime 兼容性)
wget https://github.com/wg/wrk/archive/4.2.0.tar.gz
tar xzf 4.2.0.tar.gz
cd wrk-4.2.0
# 4. 应用官方兼容性补丁(否则编译报错:undefined reference to `clock_gettime')
# 这个补丁告诉编译器用 gettimeofday 替代 clock_gettime
echo '
--- a/src/timers.c
+++ b/src/timers.c
@@ -1,6 +1,7 @@
#include <sys/time.h>
#include <time.h>
#include <stdint.h>
+#include <sys/syscall.h>
#ifdef __MACH__
#include <mach/clock.h>
@@ -22,7 +23,11 @@ void timer_start(timer_t *t) {
struct timespec ts;
int r;
- r = clock_gettime(CLOCK_MONOTONIC, &ts);
+ #ifdef __linux__
+ r = syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts);
+ #else
+ r = clock_gettime(CLOCK_MONOTONIC, &ts);
+ #endif
if (r == 0) {
t->start = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000LL;
} else {
' > clock_gettime_fix.patch
patch -p1 < clock_gettime_fix.patch
# 5. 编译(关键参数:STATIC=1 强制静态链接,避免运行时依赖)
make STATIC=1
# 6. 验证:检查是否真的静态链接
ldd wrk # 输出应为 "not a dynamic executable"
./wrk -v # 输出应为 "wrk 4.2.0 [luaJIT 2.0.5]"
# 7. 复制到系统路径(可选)
sudo cp wrk /usr/local/bin/
注意:
STATIC=1是生命线。如果不加,wrk会动态链接libluajit-5.1.so,而 Ubuntu 14.04 默认不带这个库,运行时报error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file。我第一次部署时就栽在这儿,花了两小时查ldconfig缓存,最后发现make日志里有一行小字LINKING wrk (dynamic)—— 这就是没加STATIC=1的铁证。
3.2 设计精准的基准测试场景:不止是“压一下看看”
很多人的测试停留在
wrk -t2 -c10 -d10s http://localhost:8080/
,这毫无意义。真正的基准测试必须模拟真实业务流。以你遇到的
502 Bad Gateway
为例,这通常是上游服务(如 PHP-FPM、uWSGI)挂了或超时。我们设计一个三层验证链:
-
第一层:直连上游服务(绕过 Nginx)
wrk -t4 -c200 -d30s --latency "http://127.0.0.1:9000/health"
如果这里延迟正常(99% < 50ms),说明 PHP-FPM 本身健康。 -
第二层:Nginx 反向代理到上游
wrk -t4 -c200 -d30s --latency "http://localhost:8080/health"
如果这里出现大量 502,且Latency (99%)暴涨到 60000ms(60秒超时),说明 Nginx 的proxy_read_timeout设置过短,或 upstream server 未响应。 -
第三层:加入真实请求头和 Cookie(触发鉴权逻辑)
创建auth.lua脚本:wrk.method = "GET" wrk.headers["Authorization"] = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." wrk.headers["Cookie"] = "sessionid=abc123; csrftoken=xyz789"执行:
wrk -t4 -c200 -d30s --latency -s auth.lua "http://localhost:8080/api/v1/data"
这样做的价值在于:第一层确认服务端无问题;第二层暴露 Nginx 配置缺陷;第三层验证鉴权中间件是否成为瓶颈(比如 Redis 连接池耗尽)。我帮某电商做大促前压测时,就用这套方法发现:
/api/v1/order
接口在第二层测试中 99% 延迟是 80ms,但加上
Authorization
头后暴涨到 3200ms——最终定位到是 JWT 解析时调用的
openssl_pkey_get_public
函数在 PHP 5.5 下有严重性能退化,换用
phpseclib
库后恢复至 95ms。
3.3 解析 wrk 报告:读懂每一行数据背后的系统真相
当你运行
wrk -t4 -c100 -d30s --latency "http://localhost:8080/"
,得到的报告绝不是一堆数字,而是一份系统健康快照:
Running 30s test @ http://localhost:8080/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 42.50ms 12.34ms 120.89ms 72.33%
Req/Sec 2.34k 342.12 3.12k 68.22%
279840 requests in 30.02s, 35.24MB read
Non-2xx or 3xx responses: 241
Requests/sec: 9322.12
Transfer/sec: 1.17MB
Latency Distribution
50% 38.20ms
75% 45.67ms
90% 58.91ms
99% 102.45ms
Details (average, fastest, slowest):
DNS Lookup 0.25ms 0.01ms 12.34ms
Connect 12.45ms 0.89ms 45.67ms
TTFB 28.76ms 5.23ms 98.45ms
TTLB 42.50ms 12.34ms 120.89ms
逐行解读:
-
4 threads and 100 connections:确认并发模型正确。如果这里显示1 thread and 100 connections,说明你漏写了-t4,所有压力都压在一个线程上,结果无效。 -
Latency 42.50ms:这是平均延迟,但参考价值有限。重点看Latency Distribution的99%行:102.45ms。如果业务 SLA 要求 99% 请求 < 100ms,这个测试就失败了。 -
Non-2xx or 3xx responses: 241:241 个非成功响应!必须立刻查Status Code Distribution(需加-s参数或用--print)。如果是502: 241,说明上游服务在 30 秒内挂了 241 次。 -
DNS Lookup 0.25ms:极低,说明 DNS 解析没问题。如果这里高达 1000ms,就要检查/etc/resolv.conf是否配置了不可达的 DNS 服务器。 -
Connect 12.45ms:TCP 连接建立时间。在本地回环(127.0.0.1)下,正常值应 < 1ms。如果 > 5ms,说明系统net.ipv4.tcp_tw_reuse未开启,TIME_WAIT 连接堆积。 -
TTFB 28.76ms:首字节时间,即服务端处理时间。如果TTFB占Latency的 80% 以上(如这里 28.76/42.50≈67%),说明瓶颈在服务端逻辑;如果TTLB(总时间)远大于TTFB(如TTLB=42.50ms,TTFB=10ms),说明响应体大,网络传输或客户端接收慢。
实操心得:我习惯在测试命令末尾加
2>&1 | tee wrk-report-$(date +%s).log,把报告实时保存。这样当Non-2xx出现时,可以立刻用grep "502" wrk-report-*.log快速定位错误时间点,再结合服务端日志(如tail -f /var/log/nginx/error.log)交叉分析。
4. 深度故障排查:从 “unexpected status 502 bad gateway” 到根因定位的完整链路
4.1 502 Bad Gateway 的七种常见根源及 wrk 验证法
unexpected status 502 bad gateway: unknown error, url: http://127.0.0.1:1572
这个错误看似简单,但背后可能是七层不同的问题。
wrk
是你的第一道探针:
| 根源层级 | 现象特征 | wrk 验证命令 | 根本原因 |
|---|---|---|---|
| Nginx upstream timeout |
Latency (99%) ≈ proxy_read_timeout
(如设为 60s,则 99% 线接近 60000ms),
Non-2xx
全是 502
|
wrk -t2 -c10 -d30s "http://127.0.0.1:8080/long-task"
(请求一个故意 sleep(65) 的接口)
| Nginx 等待上游响应超时,主动返回 502 |
| upstream server crash |
Non-2xx
中 502 突然激增,
Requests/sec
断崖下跌,
Latency
无规律波动
|
wrk -t1 -c1 -d10s "http://127.0.0.1:9000/health"
(直连 upstream)
|
PHP-FPM 子进程崩溃,
ps aux | grep php-fpm
可见进程数归零
|
| upstream connection refused |
wrk
报错
Connection refused
,
Non-2xx
为 0,但
Requests/sec=0
|
wrk -t1 -c1 -d5s "http://127.0.0.1:9000/"
|
upstream 服务根本没启动,
netstat -tlnp | grep :9000
无输出
|
| Nginx worker_connections 耗尽 |
Latency
随并发增加急剧上升,
Requests/sec
不升反降,
Non-2xx
为 0
|
wrk -t4 -c500 -d10s "http://localhost:8080/"
|
Nginx 配置
worker_connections 512;
,但并发 500 时已无空闲连接槽位
|
| upstream max_fails / fail_timeout 触发 |
Non-2xx
502 集中爆发后消失,
Requests/sec
恢复,但过几分钟又爆发
|
wrk -t2 -c100 -d60s "http://localhost:8080/"
(持续 1 分钟)
|
upstream 健康检查失败,Nginx 将其标记为
down
,
fail_timeout=10s
后重试
|
| SSL/TLS handshake failure (HTTPS) |
测
https://
时
Non-2xx
为 0,但
Requests/sec=0
,
wrk
报
ssl handshake failed
|
wrk -t1 -c1 -d5s "https://localhost:8443/"
|
Nginx SSL 配置错误(如
ssl_certificate
路径不对),或客户端证书不匹配
|
| Nginx buffer overflow |
Non-2xx
为 502,
Latency
极高(>10s),
error.log
有
upstream sent too big header
|
wrk -t1 -c1 -d5s "http://localhost:8080/big-header"
(构造大 Cookie)
|
proxy_buffer_size
设置过小,无法容纳上游返回的大响应头
|
我处理过一个经典案例:客户系统在凌晨 3 点准时出现 502 高峰。用
wrk
监控发现,
Non-2xx
502 每小时整点爆发一次,持续 5 分钟。直连 upstream 正常,
wrk
报告
Latency
无异常。最终在 Nginx
error.log
里发现一行:
upstream timed out (110: Connection timed out) while reading response header from upstream
。排查发现,客户在 crontab 里设置了
0 3 * * * /usr/bin/php /var/www/cleanup.php
,这个脚本会锁住数据库 4 分钟,导致 PHP-FPM 处理其他请求超时。
wrk
的
Latency Distribution
里
99%
线在 3:00:00 突然跳到 240000ms(4分钟),就是这个线索。
4.2 结合系统监控的交叉验证:让 wrk 数据“活”起来
wrk
给你的是应用层视角,要定位根因,必须和系统层监控联动。在 Ubuntu 14.04 上,我必开三个终端同步观察:
-
终端 1:运行 wrk
wrk -t4 -c200 -d60s --latency "http://localhost:8080/health" -
终端 2:监控 Nginx 连接状态
watch -n1 'ss -s \| grep "tcp:"; echo "---"; nginx -T \| grep "worker_connections"'
关键看ss -s输出的TCP: ... orphan: 123,如果orphan数持续 > 100,说明 TIME_WAIT 连接堆积,需调net.ipv4.tcp_tw_reuse=1。 -
终端 3:监控 PHP-FPM 进程
watch -n1 'ps aux \| grep "php-fpm" \| grep -v grep \| wc -l; echo "---"; cat /var/log/php5-fpm.log \| tail -5'
如果ps计数从 10 突降到 0,同时php5-fpm.log有WARNING: [pool www] child 12345 exited on signal Segmentation fault (11),那就是 PHP 扩展崩溃。
有一次,
wrk
报告
Non-2xx: 502
,但
ps
显示 PHP-FPM 进程数稳定在 20。我用
strace -p $(pgrep -f "php-fpm: pool www") -e trace=connect,sendto,recvfrom
跟踪一个子进程,发现它卡在
connect(3, {sa_family=AF_INET, sin_port=htons(6379), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS
—— Redis 连接超时。原来客户把 Redis 密码从 16 位改成了 32 位,PHP 的
predis
客户端在解析密码时发生缓冲区溢出,导致进程僵死。
wrk
的
Latency Distribution
里
99%
线是 30000ms(30秒),正好是
predis
的默认超时值。
4.3 常见问题速查表与独家避坑技巧
| 问题现象 | 可能原因 | 快速验证命令 | 我的独家解决技巧 |
|---|---|---|---|
wrk: command not found
|
wrk
未加入 PATH 或权限不足
|
ls -l /usr/local/bin/wrk; echo $PATH
|
Ubuntu 14.04 的
/usr/local/bin
不在默认 PATH,执行
export PATH="/usr/local/bin:$PATH"
后再运行,或直接用绝对路径
/usr/local/bin/wrk
|
Error: unable to resolve host
|
DNS 解析失败,
/etc/resolv.conf
配置错误
|
cat /etc/resolv.conf; nslookup google.com
|
临时用
echo "nameserver 8.8.8.8" > /etc/resolv.conf
,但生产环境务必用内网 DNS
|
Non-2xx or 3xx responses: 100%
| URL 路径错误或服务未监听 |
curl -I http://127.0.0.1:8080/
|
wrk
不会校验 URL 有效性,务必先用
curl -I
确认返回 200/301
|
Requests/sec
远低于预期(如 < 1000)
|
ulimit -n
限制过低,无法创建足够 socket
|
ulimit -n; wrk -t1 -c1000 -d5s "http://localhost:8080/"
|
Ubuntu 14.04 默认
ulimit -n
是 1024,执行
sudo sh -c "echo '* soft nofile 65536' >> /etc/security/limits.conf"
并重启 shell
|
wrk
运行几秒后卡死
|
epoll
实例耗尽或内核 bug
|
cat /proc/sys/fs/epoll/max_user_watches
|
Ubuntu 14.04 内核 3.13 的
max_user_watches
默认 128,执行
echo 524288 > /proc/sys/fs/epoll/max_user_watches
临时提升
|
测试 HTTPS 时
ssl handshake failed
| Nginx SSL 配置缺失或证书过期 |
openssl s_client -connect localhost:8443 -servername example.com
|
wrk
的 HTTPS 支持依赖 OpenSSL,确保
libssl-dev
已安装,且 Nginx 配置中有
ssl_certificate
和
ssl_certificate_key
|
最后一个血泪教训:不要在测试期间
sudo service nginx reload。Ubuntu 14.04 的 Nginx reload 机制有 bug,会导致 worker 进程残留,wrk的连接会随机分配给新旧 worker,造成502和504混发。我的做法是:sudo service nginx stop && sudo service nginx start,确保干净重启。这个细节,文档里从不提,但我在三台不同客户的 14.04 服务器上都踩过坑。
5. 进阶实战:用 wrk 脚本实现自动化回归测试与性能基线管理
5.1 编写可复用的 wrk Lua 脚本:不只是 GET,还要 POST、鉴权、断言
wrk
的
-s
参数允许你用 Lua 脚本控制请求生命周期。下面是一个生产环境真正在用的
api-test.lua
,它实现了登录、获取 Token、调用受保护接口、验证响应体:
-- api-test.lua
local counter = 0
local token = nil
-- 登录获取 Token(只执行一次)
function setup(thread)
if counter == 0 then
local req = wrk.format("POST", "/api/v1/login", {
["Content-Type"] = "application/json"
}, '{"username":"admin","password":"123456"}')
local res = wrk.request(req)
if res.status == 200 then
local json = require("cjson")
local data = json.decode(res.body)
token = data.token -- 假设响应体是 {"token": "xxx"}
end
counter = counter + 1
end
end
-- 每次请求前设置 Header
function init(args)
request = function()
if token == nil then
return wrk.format("GET", "/api/v1/public/health")
else
return wrk.format("GET", "/api/v1/private/data", {
["Authorization"] = "Bearer " .. token,
["Accept"] = "application/json"
})
end
end
end
-- 响应断言:检查状态码和 JSON 结构
function response(status, headers, body)
if status ~= 200 then
print("ERROR: Status " .. status .. " for " .. headers["host"])
return
end
if body ~= nil and #body > 0 then
local json = require("cjson")
local ok, data = pcall(json.decode, body)
if not ok then
print("ERROR: Invalid JSON in response: " .. body:sub(1,100))
elseif data.error then
print("ERROR: API returned error: " .. data.error)
end
end
end
执行命令:
wrk -t4 -c100 -d60s -s api-test.lua "http://localhost:8080/"
。这个脚本的价值在于:它把人工测试步骤(登录→取 Token→调接口)自动化了,并加入了响应体 JSON 结构校验。当
data.error
字段出现时,
wrk
会在控制台打印错误,而不仅仅是计入
Non-2xx
计数器。我把它集成到 Jenkins 的每日构建流水线里,每次代码合并后自动运行,如果
ERROR
打印超过 3 行,就标红失败。
5.2 建立性能基线:用 wrk 报告生成可审计的 Markdown 报告
性能不能只看“这次比上次快”,而要看“是否符合基线”。我用一个简单的 Bash 脚本
benchmark.sh
自动生成基线报告:

3万+

被折叠的 条评论
为什么被折叠?



