丢包的那些事儿

丢包,顾名思义,就是网络传输中数据包 “丢了”,没能顺利到达目的地。HTTP 协议跑在 TCP/IP 协议栈上,丢包可能发生在网络层,比如路由器忙不过来直接丢包,或者传输层,比如 TCP 重传机制出了岔子。常见原因有网络拥堵、线路故障、硬件性能跟不上,或者配置出了问题。举个例子,路由器的队列满了,就像超市结账排长队,后面的人只能被 “挤掉”;再比如无线网络信号不稳定,数据包就像被风吹散的信件,半路失踪。丢包在 HTTP 通信中会触发 TCP 重传,拖慢整体性能,堪称 “网络杀手”。

丢包的 “破坏力”

丢包对 HTTP 性能的影响可不小,主要体现在延迟飙升、吞吐量暴跌和用户体验拉胯。咱们来细数一下:

  1. 延迟飙升:丢包让 TCP 不得不重传,响应时间直接翻倍。对于视频会议这种实时性要求高的场景,延迟一高就卡得像幻灯片,用户体验直线下降。
  2. 吞吐量暴跌:重传和 TCP 的流量控制让数据传输效率大打折扣,尤其在高丢包率下,吞吐量可能跌到 “谷底”,大文件下载或视频流服务直接 “瘫痪”。
  3. 连带效应:丢包还会引发 “多米诺骨牌” 效应,比如 Web 服务器因超时断开连接,增加负载;客户端可能因为等不及而疯狂重试,进一步把网络堵得水泄不通。在高并发场景下,这些问题简直是 “雪上加霜”,甚至让服务彻底 “歇菜”。

HTTP 的时间账本

HTTP 请求的总耗时可拆分为以下几个阶段:

  1. DNS 解析时间:从域名到 IP 的解析。
  2. TCP 连接建立时间:三次握手阶段。
  3. TLS 握手时间(HTTPS 下)。
  4. 请求发送时间:包括写入 socket 的时间。
  5. 首字节时间(TTFB):服务器处理并返回第一个字节的耗时。
  6. 响应接收时间:从首字节开始到完整响应结束。

在这些阶段中,TCP 层的重传与拥塞控制,是受丢包影响最大的部分,尤其是 TTFB 与响应接收时间。

丢包如何 “拖慢” HTTP 请求

TCP 重传:罪魁祸首

TCP 靠确认机制(ACK)保证数据不丢,数据包一旦丢失,发送端收不到 ACK,就得重传。打个比方,假设你在寄一本书,邮局要求每页纸都要对方签收。如果有一页丢了,你得重新寄这一页,还要再等确认,整个过程就拖长了。HTTP 请求也是如此,丢包触发重传,延迟直接 “翻车”。比如,一个 RTT 10ms 的网络,1% 的丢包率可能让延迟从 10ms 飙到 30ms 甚至更高,重传的代价可不小。

TCP 的重传机制主要包括超时重传和快速重传两种方式。超时重传是指在发送数据后,如果在一定时间(RTO)内没有收到 ACK 确认,则重新发送该数据包,适用于网络波动大或连续丢包的场景,但响应较慢,容易引发延迟。快速重传则是在接收方收到乱序数据时,连续发送三个相同的 ACK 提示发送方某个数据包丢失,发送方据此立即进行重传,无需等待超时。它适用于轻微丢包和有后续数据包到达的情况,能显著减少重传延迟。

丢包如何卡住吞吐量

丢包不仅拖慢速度,还让吞吐量 “吃瘪”。TCP 的拥塞控制算法把丢包当网络拥堵的信号,立马缩小发送窗口,数据发送速度直线下降。重传还得占用带宽,挤占有效数据的 “地盘”。在高负载场景下,比如视频流服务,1% 的丢包率就能让吞吐量跌掉 20% 以上。更别提 TCP 流量控制的开销,比如接收端窗口调整,在高丢包率下更是 “火上浇油”,吞吐量直接 “趴窝”。

更糟糕的是,大包(如 HTTP 下载大文件)更容易命中丢包风险。大数据传输过程中,每多一轮重传,CPU 和内存压力也会水涨船高。

HTTP/2 和 HTTP/3 如何 “硬刚” 丢包

HTTP/2 用多路复用减少 TCP 连接数,多个请求共用一个连接,丢包的影响被 “摊薄”。但它还是基于 TCP,丢包会导致所有流 “卡壳”(队头阻塞)。

HTTP/3 基于 UDP 和 QUIC 协议,另辟蹊径,通过独立流控制和快速重传 “硬刚” 丢包。比如,QUIC 能只重传丢包的流,不影响其他流,还用 0-RTT 连接建立减少初始延迟,面对丢包更 “抗揍”。

实验验证

我们用 ChaosMesh 平台模拟不同丢包率,测试 HTTP 响应延迟和吞吐量。测试环境是 100Mbps 带宽,客户端与服务器间 RTT 10ms,负载包括小数据(996B)、中等数据(25.1KB)和大数据(227.2KB)的 HTTP 请求,测试脚本命名为 FunTester_HttpPerf

响应延迟结果

丢包率 996 B 响应时间 (ms) 25.1 KB 响应时间 (ms) 227.2 KB 响应时间 (ms)
0% 1 3 22
0.1% ≈1(无明显变化) ≈3(无明显变化) ≈22(无明显变化)
1% 31 41 170
2% 42 60 190

分析:丢包率在 0.1% 时,延迟几乎没变化,说明 TCP 重传机制能 “兜底” 少量丢包。但丢包率到 1%,延迟 “坐火箭”,尤其是大数据(227.2KB),从 22ms 飙到 170ms,增幅近 8 倍。2% 丢包率下,延迟更是 “雪上加霜”,大响应数据传输直接 “卡成 PPT”。

吞吐量结果

带宽 0% 1% 2% 3% 4% 5% 6% 7% 8% 9% 10%
Mean 804.67 222.49 168.03 106.43 63.57 36.59 24.99 15.52 10.82 36.59 15.52
STD 13.02 13.79 34.91 44.62 34.81 24.44 16.93 11.58 8.26 24.44 11.58
Min 710 51.21 5.97 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
25% 799.99 214.79 151.14 72.57 35.80 16.90 11.93 5.97 4.97 16.90 5.97
50% 809.93 222.73 182.45 108.35 59.66 31.84 21.87 11.94 8.95 31.84 11.94
75% 810.046 230.68 191.89 144.67 87.00 51.70 34.79 21.87 14.92 51.70 21.87
Max 830.419 280.88 212.79 188.91 163.07 148.64 118.81 82.03 63.64 148.64 82.03

分析:0% 丢包率下,平均吞吐量 804.67Mbps,接近理论带宽,稳如老狗。1% 丢包率时,吞吐量跌到 222.49Mbps,暴跌 72%。到 5% 丢包率,吞吐量仅剩 36.59Mbps,跌了 95%,服务基本 “歇菜”。标准差(STD)随丢包率上升而 “炸裂”,说明吞吐量波动越来越大,稳定性 “崩盘”。

  1. 延迟:丢包率超 0.1% 后,HTTP 响应延迟 “起飞”,大数据传输场景下延迟增幅能到数倍,测试脚本 FunTester_HttpPerf 数据很直观。
  2. 吞吐量:丢包率每涨 1%,吞吐量就 “跳水”,5% 以上基本 “全军覆没”,服务直接 “瘫痪”
  3. 实际意义:高性能 Web 应用得把丢包率控制在 0.1% 以下,否则延迟和吞吐量都得 “跪”。

故障测试丢包率的最佳实践

故障测试中,设置丢包率得 “量体裁衣”,结合业务场景和云厂商的承诺。主流云厂商(比如阿里云、AWS)通常保证丢包率低于 0.1%,高端服务甚至低到 0.01%。基于此,推荐以下实践:

  1. 低丢包率测试(0.1%):模拟正常网络,验证应用在云服务标准下的表现,延迟和吞吐量基本 “纹丝不动”。
  2. 中等丢包率测试(1%):模拟网络拥堵或小故障,测试应用的 “抗压能力”,延迟可能涨 10–100 倍,吞吐量跌 50%–80%。
  3. 高丢包率测试(5%):模拟极端故障,比如线路中断,测试应用在 “炼狱模式” 下的表现,服务基本 “全线崩盘”,得靠降级策略或容错机制救场。
  4. 动态调整:根据业务需求(比如实时性要求高不高),重点测高负载场景的中等丢包率,用 ChaosMesh 结合自动化测试脚本揪出稳定性的薄弱环节。

同时建议将丢包注入限定在 特定链路或服务,避免全链路干扰,干扰观测。

FunTester 原创精华
【免费合集】从 Java 开始性能测试
故障测试与 Web 前端
服务端功能测试
性能测试专题
Java、Groovy、Go
测试开发、自动化、白盒
测试理论、FunTester 风采
视频专题


↙↙↙阅读原文可查看相关链接,并与作者交流