暗色模式

HTTP 压测:从 ApacheBench 到 wrk 的 Web 性能测量

技术教程
2026-08-26
9
0
本文要点
  • docker 起一个 nginx:alpine 容器当压测目标,避免污染本机环境
  • ab-n 指定总请求数、-c 指定并发数,重点看 Requests per secondTime per request
  • 加上 -k 开启 keep-alive 后吞吐量可提高数倍,对比测试最能说明连接复用的价值
  • wrk 用线程 + 连接数的模型,配合 --latency 输出延迟分位,适合长时间持续压测
  • 压测结论依赖机器与网络,重点是横向对比而非绝对值;测带宽/负载均衡等场景应结合其他工具

为什么要做 HTTP 压测

上线前的性能评估、配置调优后的效果对比、确定一台机器的承载上限,都需要"用数据说话"。HTTP 压测工具的作用就是模拟大量并发请求打到服务上,输出吞吐量、响应时间、失败率等指标,帮我们回答三个问题:能扛多少 QPS、响应有多快、瓶颈在哪里

本文会用 ApacheBench(ab)wrk 两种最具代表性的工具,在一台真实的 Ubuntu 24.04 服务器上完成一轮完整的压测。前者历史悠久、开箱即用,适合快速摸底;后者基于事件驱动模型,高并发下的表现更接近真实负载,适合深入观察延迟。

准备压测环境

压测的是本地服务,为了不污染系统,我用 Docker 直接起一个轻量 nginx 作为被测对象,把容器的 80 端口映射到宿主机的 8080:

docker run -d --name web-bench -p 8080:80 nginx:alpine

先确认服务已就绪:

$ curl -s -o /dev/null -w "HTTP %{http_code} | size %{size_download}B\n" http://127.0.0.1:8080/
HTTP 200 | size 896B

返回 200,页面 896 字节,这就是我们后面要反复打的"靶子"。注意压测全部走 127.0.0.1 回环地址,避免公网链路干扰,这样测出来的是纯服务性能。

提醒:被测页面的体积会直接影响测试结果。同样的服务,返回 896 字节首页和返回 2MB 文件,QPS 可能差一个数量级。做对比测试时务必保持目标一致。

ApacheBench 入门

ab 是 Apache 自带的小工具,Ubuntu 上装在 apache2-utils 包里:

sudo apt-get install -y apache2-utils

安装后直接就能用 ab -V 查看版本:

$ ab -V
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>

第一次压测

ab -n 2000 -c 50 http://127.0.0.1:8080/

-n 2000 表示总共发送 2000 个请求,-c 50 表示同时维持 50 个并发连接。下面是完整输出:

ab 基础压测输出

输出里最重要的几行:

  • Concurrency Level: 50——本次压测的并发数,即同时有 50 个连接。
  • Requests per second: 5922.33——每秒完成的请求数,也就是日常说的 QPS,性能的核心指标。
  • Time per request: 8.443 ms——平均每个"用户"完成一次请求花费的时间(同等并发下单次请求的总耗时)。
  • Time per request: 0.169 ms (mean, across all concurrent requests)——按总耗时除以全部请求数得出的均值,比上面那个更有参考意义。
  • Transfer rate: 6529.60 Kbytes/sec——网络吞吐,受响应体大小影响。
  • Percentage of the requests served within a certain time——响应时间分布,50% 的请求在 8ms 内完成、99% 在 16ms 内完成,是判断"尾部延迟"的关键。

这次实测单台 1.9G 内存的小型云主机,nginx 大约能扛 5900 QPS,平均单请求 8.4ms,Failed requests 为 0,表现符合预期。

常用参数

ab 的参数不多,日常够用的就这几个:

参数含义示例
-n总共发多少个请求-n 10000
-c并发连接数-c 100
-k启用 HTTP Keep-Alive,复用连接-k
-H添加自定义请求头-H "Authorization: Bearer xxx"
-p发送 POST 请求并用文件提供 body-p post.json
-T指定 Content-Type-T application/json
-t按时长压测(如 -t 10 跑 10 秒)-t 10 -n 1000000

注意默认情况下 ab 每发一个请求就新建一个 TCP 连接、用完就断开。这在真实世界里并不常见,因为浏览器和 HTTP 客户端都会复用连接。想让压测更贴近生产环境,就得加上 -k

Keep-Alive 的巨大影响

用同样的参数只加一个 -k 再跑一次:

ab -n 2000 -c 50 -k http://127.0.0.1:8080/

ab keep-alive 压测输出

对比肉眼可见:

指标不带 -k-k
Requests per second592215381
Time taken for tests0.338 s0.130 s
Time per request (mean)8.443 ms3.251 ms
中位延迟 (50%)8 ms3 ms

吞吐量从 5922 提升到 15381 QPS,接近 2.6 倍。原因很简单:HTTP/1.1 下每次请求都要经过 TCP 三次握手 + TLS 握手(走 HTTPS 时更明显),而 keep-alive 复用连接省掉了这部分开销。输出里也多了 Keep-Alive requests: 2000 这一行,表示全部请求都走了复用连接。

调优经验:如果线上服务本来就开启了 keep-alive(nginx 默认 keepalive_timeout 65s),压测却不加 -k,测出的数字会明显低估真实容量。两种都测一遍能顺便验证"连接复用"这个优化项到底值多少。

wrk:新一代压测工具

wrk 用 C 语言 + epoll/kqueue 事件驱动模型实现,单机可以轻松撑起几十万并发连接,输出也更简洁。Ubuntu 24.04 的仓库里直接有:

sudo apt-get install -y wrk

运行压测

wrk -t2 -c50 -d5s --latency http://127.0.0.1:8080/

-t2 用 2 个线程、-c50 维持 50 个连接、-d5s 持续压 5 秒,--latency 额外输出延迟分布:

wrk 压测输出

wrk 的输出分为三块:

  • Thread Stats——每个线程的统计。Req/Sec 8.54k 表示每个线程每秒约处理 8.5k 请求;Latency 列给出平均、标准差和最大值,+/- Stdev 是"多少数据落在均值一个标准差内"的比例。
  • Latency Distribution——延迟分位:50% 的请求 2.84ms 内完成、90% 在 4.67ms、99% 在 6.67ms。相比 ab 的百分比表,这里更直观。
  • Requests/sec: 16975.96——总体 QPS,这是最核心的结论。5 秒内完成了 84929 个请求,平均每秒约 1.7 万。

wrk 内部自动复用连接,所以它的数字和 ab + -k 接近(本例 16975 vs 15381),而不是和 ab 默认模式(5922)接近。

线程、连接与时长

wrk 的参数模型和 ab 不同,它不是"总请求数",而是"每次发 N 秒":

参数含义说明
-t线程数通常设为 CPU 核数,启动 -tN 会 fork N 个线程(实际还有主线程)
-c连接数总连接的开启的连接,会均分到每个线程
-d持续时间数值支持单位,5s30s2m
--latency打印延迟分位建议始终加上,否则看不到延迟分布
-s加载 Lua 脚本支持自定义请求、签名鉴权等高级场景

压测时建议先小规模(-t1 -c10 -d3s)快速确认服务正常,再加大到目标负载,避免一开始就把服务打挂。

观察"平台期"

真实的压测不只是看一个峰值,更要观察随着并发上升 QPS 的曲线。把并发从 50 拉到 200、时长拉到 10 秒,看看这台小主机的表现:

wrk -t4 -c200 -d10s --latency http://127.0.0.1:8080/

实测对比很有意思:

并发QPS平均延迟99% 延迟
50(-c50180112.78 ms6.43 ms
200(-c2001690011.84 ms24.97 ms

并发提高到 4 倍,QPS 反而掉了约 6%,而延迟涨了 4 倍多——这就说明服务已经逼近处理上限,瓶颈通常在 CPU 单核、worker 数量或数据库连接这类资源上。这也解释了为什么压测必须带着延迟一起看:光看吞吐高没有意义,当并发上去后台延迟陡增时,用户体验已经崩了。

ab 与 wrk 对比与选择

维度abwrk
模型单线程,每请求独占连接(除非 -k事件驱动,线程 + 数万连接
安装apache2-utilswrk
请求控制按总数 -n 或按时间 -t按时间 -d
高并发能力一般,并发高时有偏差强,适合大并发
延迟统计百分位表(50%~100%)分位分布 + 线程统计
自定义请求-p body / -HLua 脚本,功能更强
典型场景快速摸底、简单验证持续压测、详细延迟分析

选择建议:快速验证服务通不通、功能正常不正常,用 ab 一条命令就够;要评估服务在高并发、长时间下的承载能力和延迟表现,用 wrk;两者互补,可以都装。

压测注意事项

  1. 目标要单一:压测对象只放一个 nginx/应用容器即可,别让系统的其他负载干扰结果;同一轮对比必须保证环境不变。
  2. 先本机再跨机:本机回环测的是服务纯性能,适合对比调优;跨机器压测才能反映网络栈、公网链路的真实表现。
  3. 控制量级-c-d 从小到大逐步加,视服务能力而定,避免稀少的云主机瞬间被打到内存或带宽耗尽。
  4. 读懂失败Failed requests 不为 0 或 wrk 输出 Socket errors 时,要区分是超时(服务慢)还是连接被拒(并发上限),排错方向完全不同。
  5. 关注尾部延迟:平均延迟漂亮不代表体验好,99%/99.9% 分位才是用户真正感知到的"卡不卡"。
  6. 数据只做参考:云主机的 CPU 会因邻居抢资源波动,同一命令每次跑出的数字都不同。结论看趋势和量级,别纠结 ±10% 的差异。真实峰值压测建议用 heyApache JMeter 做更大规模的验证。

小结

压测不是跑一条命令发一堆请求那么简单,它的核心是用对工具、看懂指标、做好对比。这一次演示覆盖了:

  • 用 Docker 快速搭一个干净的压测目标;
  • ab -n -c 快速摸底,读懂 QPS、时延、分位这些关键输出;
  • -k 验证 keep-alive 对吞吐量近 2.6 倍的提升;
  • wrk -t -c -d 做持续压测,结合延迟分位判断服务是否到达平台期。

当你需要回答"这台机器能扛多大流量"时,从这两条命令开始:

ab -n 5000 -c 50 -k http://127.0.0.1:8080/
wrk -t2 -c50 -d10s --latency http://127.0.0.1:8080/

同样是这台小主机,ab -k 能到每秒 1.9 万,wrk 能到每秒 1.8 万左右,两者互相印证,结论就可靠了。

相关阅读:ApacheBench 官方文档wrk 源码仓库henning m-bench 基准测试与压测工具比较

发表评论

暂无评论,快来抢沙发吧!