Computer NetworkNotes

第 32 章:网络测试与压测

zjc 于 2026-02-01 发布

这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 网络测试的目的是验证容量、延迟、稳定性和故障行为,而不是得到一份好看的最大 QPS。完整测试应覆盖带宽、RTT、丢包、建连、TLS、HTTP 语义、长连接、重试和故障切换。

32.1 测试目标

先定义问题:

1. 系统目标 QPS 是多少?
2. P99 / P999 延迟预算是多少?
3. 峰值持续多久?
4. 允许错误率是多少?
5. 单连接还是多连接?
6. 请求体和响应体多大?
7. 用户分布在哪里?
8. 故障时如何降级?

测试类型:

类型 目标
基准测试 建立当前性能基线
容量测试 找到安全容量水位
压力测试 观察过载行为
浸泡测试 发现泄漏和衰减
尖峰测试 验证突发和弹性
混沌测试 验证故障切换

32.2 指标

必须采集:

  1. QPS;
  2. 并发数;
  3. 错误率;
  4. P50 / P95 / P99 / P999;
  5. 连接建立耗时;
  6. TLS 耗时;
  7. 首包耗时;
  8. 响应大小;
  9. 带宽;
  10. 重传;
  11. CPU / 内存 / fd;
  12. 服务端队列;
  13. 下游耗时;
  14. LB 状态。

不要只看平均延迟。平均 100ms 可能意味着 95% 请求 5ms,5% 请求 2s。

32.3 带宽与延迟测试

iperf3:

iperf3 -s
iperf3 -c <server> -t 30
iperf3 -c <server> -u -b 500M -t 30
iperf3 -c <server> -P 8 -t 30

路径质量:

ping -c 100 <target>
mtr -rw -c 200 <target>

注意:

  1. 单 TCP 连接受 RTT 和窗口影响;
  2. -P 8 多流测试更接近总容量;
  3. UDP 测试需控制速率并观察丢包;
  4. 测试流量可能触发安全策略;
  5. 云实例带宽常有规格限制。

32.4 HTTP 压测

wrk:

wrk -t8 -c500 -d60s --latency \
  -s post.lua https://api.example.com/api/orders

post.lua:

wrk.method = "POST"
wrk.body = '{"userId":10001,"skuId":20001}'
wrk.headers["Content-Type"] = "application/json"

hey:

hey -z 60s -c 500 -m POST \
  -H "Content-Type: application/json" \
  -d '{"userId":10001}' \
  https://api.example.com/api/orders

k6:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '1m', target: 100 },
    { duration: '3m', target: 500 },
    { duration: '1m', target: 0 }
  ],
  thresholds: {
    http_req_duration: ['p(99)<300'],
    http_req_failed: ['rate<0.01']
  }
};

export default function () {
  const res = http.get('https://api.example.com/api/orders');
  check(res, { 'status is 200': r => r.status === 200 });
  sleep(0.1);
}

32.5 测试脚本要点

  1. 使用生产相似路径长度;
  2. 请求参数有分布,避免全部命中一个缓存;
  3. 响应体大小接近真实;
  4. 认证 token 处理过期;
  5. 写接口必须可清理;
  6. 压测客户端单独部署;
  7. 逐步加压;
  8. 每轮之间恢复基线;
  9. 记录版本和配置;
  10. 不在未授权环境压测。

压测客户端瓶颈:

  1. CPU 不足;
  2. 临时端口耗尽;
  3. fd 不足;
  4. DNS 慢;
  5. TLS 握手过重;
  6. 日志写入阻塞;
  7. 连接数不足。

32.6 延迟统计陷阱

协调遗漏

固定速率压测工具会测量“发起的请求”,但系统卡顿时,普通客户端可能等待后才发起新请求,从而低估真实排队延迟。应使用固定速率工具并记录目标发送时间。

时钟

跨机器测量必须确认时间同步,否则耗时可能出现负数或异常漂移。

冷热差异

冷缓存、JIT、连接池预热、TLS session、CPU 频率调度都会影响首轮结果。

长尾来源

P999 可能来自:

  1. GC;
  2. 重传;
  3. 慢磁盘;
  4. 锁等待;
  5. 重试;
  6. 某个坏节点;
  7. 特定用户数据;
  8. 定时任务。

32.7 故障注入

tc netem:

tc qdisc add dev eth0 root netem delay 100ms 20ms loss 1%
tc qdisc change dev eth0 root netem delay 200ms
tc qdisc del dev eth0 root

验证:

  1. 客户端超时;
  2. 重试预算;
  3. 幂等性;
  4. 熔断;
  5. 降级;
  6. 告警;
  7. 恢复。

其他注入:

  1. 断开后端;
  2. 证书替换为过期;
  3. DNS 返回错误;
  4. 丢包;
  5. 带宽限速;
  6. 节点重启;
  7. 可用区故障。

32.8 报告模板

测试目标:
环境:
版本:
拓扑:
数据规模:
测试工具:
加压模型:
持续时间:

QPS:
错误率:
P50 / P95 / P99 / P999:
平均响应大小:
带宽:
CPU:
内存:
连接数:
重传:

瓶颈判断:
异常现象:
安全容量:
建议:
风险:
复测计划:

安全容量通常不是最大 QPS,而是满足 SLO 并保留故障接管余量的水位。

32.9 测试流程

1. 明确 SLO
2. 准备环境和数据
3. 建立监控基线
4. 小流量验证正确性
5. 逐步加压
6. 观察拐点和错误
7. 重复测试
8. 浸泡测试
9. 故障注入
10. 输出容量结论
11. 设置告警和扩容规则

本章小结

网络测试要覆盖带宽、RTT、丢包、TCP、TLS、HTTP、长连接和故障切换,指标必须看分位数、错误率和资源水位。iperf3 适合链路容量,wrk/hey/k6 适合 HTTP 压测,tc netem 和混沌工具验证弱网与故障行为。压测结论要给出安全容量,而不是短暂峰值。

思考题

  1. 为什么最大 QPS 不等于安全容量?
  2. 单连接和多连接吞吐测试有什么区别?
  3. 平均延迟为什么会掩盖长尾问题?
  4. 什么是协调遗漏?
  5. 设计一次跨可用区入口故障切换演练。