ab —— 最简单的 HTTP 压测

运维工具手册 10-压测与基准 4.9 KB 原文

ab —— 最简单的 HTTP 压测

分类:10 压测与基准 适用:ApacheBench(apache2-utils / httpd-tools),所有 Linux 一句话:一条命令测出接口每秒能扛多少请求,适合快速摸底,不适合精细压测。

1. 它解决什么问题

  • 接口上线前想知道大概能扛多少 QPS。
  • 改完配置(连接池、worker 数)做前后对比。
  • 验证压测环境与链路是否通。

不适合:长连接高并发、HTTP/2、需要脚本化场景的压测(用 wrk/k6/jmeter)。

2. 安装

apt install -y apache2-utils
dnf install -y httpd-tools

3. 基本用法

ab -n 1000 -c 10 http://127.0.0.1:8080/health
  • -n 总请求数
  • -c 并发数(同时进行的请求)
# 带 KeepAlive
ab -n 10000 -c 100 -k http://127.0.0.1:8080/

# 按时间压测(替代 -n)
ab -t 30 -c 50 -k http://127.0.0.1:8080/

# POST JSON
ab -n 1000 -c 20 -p payload.json -T application/json http://127.0.0.1:8080/api

# 带 Header / Cookie
ab -n 1000 -c 20 -H 'Authorization: Bearer xxx' -H 'X-Env: test' http://...
ab -n 100 -c 5 -C 'sessionid=abc123' http://...

# Basic Auth
ab -n 100 -c 5 -A user:pass http://...

# 输出 CSV(每个请求的耗时)
ab -n 1000 -c 10 -e /tmp/result.csv http://...

# 输出 gnuplot 格式(便于画图)
ab -n 1000 -c 10 -g /tmp/result.tsv http://...

4. 结果怎么读

Concurrency Level:      100
Time taken for tests:   12.345 seconds
Complete requests:      10000
Failed requests:        3
   (Connect: 0, Receive: 0, Length: 3, Exceptions: 0)
Non-2xx responses:      20
Total transferred:      12345678 bytes
HTML transferred:       9876543 bytes
Requests per second:    810.05 [#/sec] (mean)
Time per request:       123.456 [ms] (mean)
Time per request:       1.235 [ms] (mean, across all concurrent requests)
Transfer rate:          976.12 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   0.5      1      10
Processing:    20  110  35.2     98     450
Waiting:       15  100  34.1     90     430
Total:         21  111  35.3     99     460

Percentage of the requests served within a certain time (ms)
  50%     99
  66%    120
  75%    135
  80%    150
  90%    190
  95%    230
  99%    420
 100%    460 (longest request)
指标 关注点
Requests per second 吞吐量,核心指标
Time per request(第一个) 单请求平均耗时(含排队)
Time per request(第二个) 所有并发平均,数值小很多,别混淆
Failed requests 非 0 必须排查(连接失败、长度不一致、超时)
Non-2xx responses 业务错误,ab 不算它"失败"
Connect / Processing / Waiting 连接、处理、首字节等待
百分位表 P95/P99 才是用户体验,平均值会骗人

关键判读

  • Non-2xx > 0:压测结果无效,先修服务。
  • Failed requests (Length):响应长度不一致,通常是服务端异常返回。
  • Connect 时间高:TCP 握手慢,可能是 -k 没开或 somaxconn 小。
  • Waiting 高:服务端处理慢,不是网络问题。
  • 并发升到某点 QPS 不再涨、P99 暴涨:到了容量拐点。

5. 压测方法(避免自欺欺人)

# 1. 先单请求确认功能正常
curl -s -o /dev/null -w '%{http_code} %{time_total}\n' http://target/health

# 2. 阶梯加压,找拐点
for c in 10 50 100 200 400; do
  echo "== c=$c"
  ab -n $((c*200)) -c $c -k http://target/api 2>&1 | grep -E 'Requests per second|Time per request|Failed|Non-2xx'
done

记录每档的 QPS 与 P99,画出来就能看到拐点。

6. 实战场景

6.1 前后对比(改配置验证效果)

# 改之前
ab -n 5000 -c 100 -k http://127.0.0.1:8080/api > /tmp/before.txt
# 改 worker/连接池之后
ab -n 5000 -c 100 -k http://127.0.0.1:8080/api > /tmp/after.txt
diff <(grep -E 'Requests per second|Time per request' /tmp/before.txt) \
     <(grep -E 'Requests per second|Time per request' /tmp/after.txt)

6.2 验证 KeepAlive 是否生效

# 不开 -k
ab -n 5000 -c 100 http://127.0.0.1:8080/api
# 开 -k
ab -n 5000 -c 100 -k http://127.0.0.1:8080/api

不开 KeepAlive 会大量出现 TIME_WAIT,QPS 明显更低。若开 -k 后没提升,说明 Nginx/后端没启用长连接(keepalive 指令、Connection 头)。

6.3 压测时同步观察服务端

# 压测机
ab -n 20000 -c 200 -k http://target/api &

# 服务端
watch -n1 'ss -s; echo; vmstat 1 2 | tail -1'

看 TIME_WAIT、ESTAB、sy、wa 是否异常。QPS 上不去往往是 somaxconn、文件描述符、连接池打满。

6.4 使用 POST 压测

cat > /tmp/body.json <<'EOF'
{"userId":123,"action":"query"}
EOF

ab -n 2000 -c 50 -p /tmp/body.json -T application/json \
  -H 'Content-Type: application/json' http://target/api/query

7. 常见坑

  1. -n 太小:-n 100 的结果没统计意义,至少几千。
  2. -c 大于 -n:ab 会报错或结果异常。
  3. 压测机自己成瓶颈:ab 是单线程,高并发下客户端 CPU 先满,测的是 ab 不是服务端。
  4. 本机压本机:网络栈、CPU 争抢导致数据失真,尽量跨机。
  5. 不支持 HTTP/2:对 HTTP/2 服务只能用 HTTP/1.1 压,结果偏低。
  6. -k 与 Connection: close 冲突:服务端强制关闭时 KeepAlive 无效。
  7. Non-2xx 不算失败:看 Failed requests 为 0 就以为成功,其实全是 500。
  8. DNS 解析开销:用域名压测时每个连接可能重新解析,用 IP 或 -H 'Host: ...'。
  9. Time per request 看错:第一个是单请求(含排队),第二个是并发平均,报告里要说明用哪个。
  10. 压测影响生产:绝不对生产直接压,除非有预案和限流。
  11. 没预热:JIT/连接池/缓存冷启动,前几秒数据偏低,先跑一轮丢弃。
  12. -t 与 -n 同时用:-t 优先,-n 被忽略。

8. 速查表

ab -n 1000 -c 10 <url>
ab -n 10000 -c 100 -k <url>                 # KeepAlive(推荐)
ab -t 30 -c 50 -k <url>                     # 按时长
ab -n 1000 -c 20 -p body.json -T application/json <url>
ab -n 1000 -c 20 -H 'Authorization: Bearer x' <url>
ab -n 1000 -c 20 -e /tmp/out.csv <url>
ab -n 1000 -c 10 -g /tmp/plot.tsv <url>     # gnuplot

# 关注
Requests per second        # QPS
Time per request           # 延迟
Failed requests            # 必须为 0
Non-2xx responses          # 必须为 0
P95 / P99                  # 真实体验
ab —— 最简单的 HTTP 压测 - 知识库 - 起航社区