3. 网络故障模拟基础:断网、延迟、丢包、带宽限制
在测试离线优先应用时,精准模拟真实网络条件是评估数据同步、冲突解决和用户体验的关键前提。本章介绍四种核心网络故障类型及其模拟原理、常用工具与操作步骤,为后续章节的测试脚本编写和自动化故障注入奠定基础。
3.1 故障类型与影响范围
| 故障类型 | 定义 | 对离线优先应用的主要影响 |
|---|---|---|
| 断网 | 网络连接完全断开,无法收发任何数据包 | 触发离线模式、本地缓存回退、同步队列堆积 |
| 延迟 | 数据包往返时间(RTT)显著增加 | 超时重试、用户界面卡顿、乐观更新与服务器确认不一致 |
| 丢包 | 部分数据包在传输过程中丢失 | 请求失败、数据不完整、需要依赖重试机制和一致性校验 |
| 带宽限制 | 吞吐量被压低至指定上限 | 大文件同步缓慢、增量同步策略失效、占用过多用户流量 |
3.2 模拟原理与工具选择
模拟网络故障的核心思想是在操作系统或应用层拦截网络流量,按规则修改包的行为。主流工具对比:
| 工具 | 平台 | 支持的故障类型 | 注入粒度 |
|---|---|---|---|
| Network Link Conditioner | macOS / iOS | 断网、延迟、丢包、带宽 | 系统级 |
| clumsy | Windows | 延迟、丢包、带宽、重排、篡改 | 进程/端口级 |
| tc (Traffic Control) | Linux | 延迟、丢包、带宽、损坏、重复 | 网络接口/流分类级 |
| toxiproxy | 跨平台 | 延迟、丢包、带宽、超时、关闭连接 | 代理级(应用层) |
| Docker + iptables | Linux(容器) | 断网、延迟、丢包 | 容器网络命名空间级 |
选择建议: 本地开发阶段优先使用系统级或进程级工具(如 Linux 的 tc、Windows 的 clumsy),便于快速验证;CI/CD 流水线建议使用 toxiproxy 或 iptables 脚本化注入,保持测试环境可重复。
3.3 执行流程与命令示例
以下以 Linux 系统为例,演示如何通过 tc 在 eth0 网卡上注入四种典型故障。
3.3.1 断网模拟
直接禁用网卡或通过 iptables 丢弃所有出站/入站流量。
# 方法一:禁用网卡
sudo ip link set eth0 down
# 方法二:丢弃所有流量(保留连接可用于后续恢复)
sudo iptables -A INPUT -j DROP
sudo iptables -A OUTPUT -j DROP
# 恢复
sudo ip link set eth0 up
sudo iptables -F
3.3.2 延迟模拟
# 添加 200ms 固定延迟
sudo tc qdisc add dev eth0 root netem delay 200ms
# 添加 200ms ± 50ms 随机抖动
sudo tc qdisc add dev eth0 root netem delay 200ms 50ms distribution normal
# 清除
sudo tc qdisc del dev eth0 root
3.3.3 丢包模拟
# 随机丢弃 10% 的数据包
sudo tc qdisc add dev eth0 root netem loss 10%
# 基于概率的关联丢包(25% 概率丢包,且相邻包有 25% 概率也丢)
sudo tc qdisc add dev eth0 root netem loss 25% 25%
# 清除
sudo tc qdisc del dev eth0 root
3.3.4 带宽限制模拟
# 使用 tbf ( Bucket Filter) 限制带宽为 1Mbit,突发 32k
sudo tc qdisc add dev eth0 root tbf rate 1mbit burst 32kbit latency 400ms
# 使用 htb 层层级限制更为灵活(示例:限制为 512kbit)
sudo tc qdisc add dev eth0 root handle 1: htb default 30
sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 512kbit
# 清除
sudo tc qdisc del dev eth0 root
注意: 在生产环境或连接远程机器的网卡上操作 tc 时,建议先创建 cron 恢复任务或使用脚本定时清理,防止因网络锁定导致无法恢复连接。
3.4 故障模拟完整流程(Linux + tc)
3.5 调试与验证方法
- 使用 ping 测试延迟和丢包:
ping -c 10 8.8.8.8 # 观察 rtt min/avg/max/mdev 和 packet loss 百分比 - 使用 iperf3 测试带宽:
# 服务端(目标机) iperf3 -s # 客户端(本机) iperf3 -c <server-ip> -t 10 # 查看实际吞吐量是否接近限制值 - 查看 tc 当前规则:
sudo tc qdisc show dev eth0 - 检查系统日志:
dmesg | tail -20 # 查看是否因规则导致驱动异常
调试窍门: 同时开启 tcpdump -i eth0 -w capture.pcap 抓包,后续可用 Wireshark 分析重传、RTT 抖动、窗口缩放行为,与 tc 注入参数对照验证。
3.6 常见错误与避坑
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
RTNETLINK answers: Operation not supported |
内核未启用 netem 模块或 qdisc 不兼容 | 执行 sudo modprobe sch_netem,或升级内核 |
| 延迟规则在重启后消失 | tc 规则不是持久化配置 | 将命令写入启动脚本(如 /etc/rc.local 或 systemd service) |
| 带宽限制后,实际流量仍超过设定值 | 使用了 burst 参数过大,或没有考虑 TCP 突发特性 | 减小 burst(如 burst 8kbit),或改用 htb 配合 ceil 参数 |
| 断网模拟后无法恢复 SSH 连接 | 在远程会话中直接丢弃了管理接口流量 | 使用 iptables -I INPUT -s <管理IP> -j ACCEPT 设置白名单,或使用 cron 定时清理 |
| 丢包导致应用崩溃而非优雅降级 | 应用未实现重试或指数退避 | 检查超时设置,参考第 5 章“离线优先应用重试策略” |
3.7 性能与稳定性优化建议
- 分组测试:不要在测试机上同时注入多种故障,避免相互干扰;建议按场景(如“弱网同步”、“完全离线”)分别建立脚本。
- 超时/重试阈值调整:注入延迟前,确保应用层的 connect/read 超时时间大于注入的 RTT 上限,否则被误判为断网。
- CI/CD 集成:使用 Docker 容器网络命名空间隔离故障注入,测试结束后销毁容器,避免残留规则影响后续任务。
- 日志与监控:将故障注入参数、开始时间、结束时间记录到测试报告,便于复现和对比不同故障下的同步行为。
本章核心要点: 四种基本故障(断网、延迟、丢包、带宽限制)可通过 Linux tc 和 iptables 快速模拟。重点掌握 netem 的 delay 与 loss 参数、tbf/htb 的 rate 设置,以及清理命令。理解这些基础后,第 4 章将使用 toxiproxy 实现更精细的应用层故障注入。