丢包的那些事儿
丢包,顾名思义,就是网络传输中数据包 “丢了”,没能顺利到达目的地。HTTP 协议跑在 TCP/IP 协议栈上,丢包可能发生在网络层,比如路由器忙不过来直接丢包,或者传输层,比如 TCP 重传机制出了岔子。常见原因有网络拥堵、线路故障、硬件性能跟不上,或者配置出了问题。举个例子,路由器的队列满了,就像超市结账排长队,后面的人只能被 “挤掉”;再比如无线网络信号不稳定,数据包就像被风吹散的信件,半路失踪。丢包在 HTTP 通信中会触发 TCP 重传,拖慢整体性能,堪称 “网络杀手”。
丢包的 “破坏力”
丢包对 HTTP 性能的影响可不小,主要体现在延迟飙升、吞吐量暴跌和用户体验拉胯。咱们来细数一下:
- 延迟飙升:丢包让 TCP 不得不重传,响应时间直接翻倍。对于视频会议这种实时性要求高的场景,延迟一高就卡得像幻灯片,用户体验直线下降。
- 吞吐量暴跌:重传和 TCP 的流量控制让数据传输效率大打折扣,尤其在高丢包率下,吞吐量可能跌到 “谷底”,大文件下载或视频流服务直接 “瘫痪”。
- 连带效应:丢包还会引发 “多米诺骨牌” 效应,比如 Web 服务器因超时断开连接,增加负载;客户端可能因为等不及而疯狂重试,进一步把网络堵得水泄不通。在高并发场景下,这些问题简直是 “雪上加霜”,甚至让服务彻底 “歇菜”。
HTTP 的时间账本
HTTP 请求的总耗时可拆分为以下几个阶段:
- DNS 解析时间:从域名到 IP 的解析。
- TCP 连接建立时间:三次握手阶段。
- TLS 握手时间(HTTPS 下)。
- 请求发送时间:包括写入 socket 的时间。
- 首字节时间(TTFB):服务器处理并返回第一个字节的耗时。
- 响应接收时间:从首字节开始到完整响应结束。
在这些阶段中,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)随丢包率上升而 “炸裂”,说明吞吐量波动越来越大,稳定性 “崩盘”。
-
延迟:丢包率超 0.1% 后,HTTP 响应延迟 “起飞”,大数据传输场景下延迟增幅能到数倍,测试脚本
FunTester_HttpPerf
数据很直观。 - 吞吐量:丢包率每涨 1%,吞吐量就 “跳水”,5% 以上基本 “全军覆没”,服务直接 “瘫痪”
- 实际意义:高性能 Web 应用得把丢包率控制在 0.1% 以下,否则延迟和吞吐量都得 “跪”。
故障测试丢包率的最佳实践
故障测试中,设置丢包率得 “量体裁衣”,结合业务场景和云厂商的承诺。主流云厂商(比如阿里云、AWS)通常保证丢包率低于 0.1%,高端服务甚至低到 0.01%。基于此,推荐以下实践:
- 低丢包率测试(0.1%):模拟正常网络,验证应用在云服务标准下的表现,延迟和吞吐量基本 “纹丝不动”。
- 中等丢包率测试(1%):模拟网络拥堵或小故障,测试应用的 “抗压能力”,延迟可能涨 10–100 倍,吞吐量跌 50%–80%。
- 高丢包率测试(5%):模拟极端故障,比如线路中断,测试应用在 “炼狱模式” 下的表现,服务基本 “全线崩盘”,得靠降级策略或容错机制救场。
- 动态调整:根据业务需求(比如实时性要求高不高),重点测高负载场景的中等丢包率,用 ChaosMesh 结合自动化测试脚本揪出稳定性的薄弱环节。
同时建议将丢包注入限定在 特定链路或服务,避免全链路干扰,干扰观测。
FunTester 原创精华
【免费合集】从 Java 开始性能测试
故障测试与 Web 前端
服务端功能测试
性能测试专题
Java、Groovy、Go
测试开发、自动化、白盒
测试理论、FunTester 风采
视频专题