丢包,顾名思义,就是网络传输中数据包 “丢了”,没能顺利到达目的地。HTTP 协议跑在 TCP/IP 协议栈上,丢包可能发生在网络层,比如路由器忙不过来直接丢包,或者传输层,比如 TCP 重传机制出了岔子。常见原因有网络拥堵、线路故障、硬件性能跟不上,或者配置出了问题。举个例子,路由器的队列满了,就像超市结账排长队,后面的人只能被 “挤掉”;再比如无线网络信号不稳定,数据包就像被风吹散的信件,半路失踪。丢包在 HTTP 通信中会触发 TCP 重传,拖慢整体性能,堪称 “网络杀手”。
丢包对 HTTP 性能的影响可不小,主要体现在延迟飙升、吞吐量暴跌和用户体验拉胯。咱们来细数一下:
HTTP 请求的总耗时可拆分为以下几个阶段:
在这些阶段中,TCP 层的重传与拥塞控制,是受丢包影响最大的部分,尤其是 TTFB 与响应接收时间。
TCP 靠确认机制(ACK)保证数据不丢,数据包一旦丢失,发送端收不到 ACK,就得重传。打个比方,假设你在寄一本书,邮局要求每页纸都要对方签收。如果有一页丢了,你得重新寄这一页,还要再等确认,整个过程就拖长了。HTTP 请求也是如此,丢包触发重传,延迟直接 “翻车”。比如,一个 RTT 10ms 的网络,1% 的丢包率可能让延迟从 10ms 飙到 30ms 甚至更高,重传的代价可不小。
TCP 的重传机制主要包括超时重传和快速重传两种方式。超时重传是指在发送数据后,如果在一定时间(RTO)内没有收到 ACK 确认,则重新发送该数据包,适用于网络波动大或连续丢包的场景,但响应较慢,容易引发延迟。快速重传则是在接收方收到乱序数据时,连续发送三个相同的 ACK 提示发送方某个数据包丢失,发送方据此立即进行重传,无需等待超时。它适用于轻微丢包和有后续数据包到达的情况,能显著减少重传延迟。
丢包不仅拖慢速度,还让吞吐量 “吃瘪”。TCP 的拥塞控制算法把丢包当网络拥堵的信号,立马缩小发送窗口,数据发送速度直线下降。重传还得占用带宽,挤占有效数据的 “地盘”。在高负载场景下,比如视频流服务,1% 的丢包率就能让吞吐量跌掉 20% 以上。更别提 TCP 流量控制的开销,比如接收端窗口调整,在高丢包率下更是 “火上浇油”,吞吐量直接 “趴窝”。
更糟糕的是,大包(如 HTTP 下载大文件)更容易命中丢包风险。大数据传输过程中,每多一轮重传,CPU 和内存压力也会水涨船高。
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)随丢包率上升而 “炸裂”,说明吞吐量波动越来越大,稳定性 “崩盘”。
FunTester_HttpPerf
数据很直观。故障测试中,设置丢包率得 “量体裁衣”,结合业务场景和云厂商的承诺。主流云厂商(比如阿里云、AWS)通常保证丢包率低于 0.1%,高端服务甚至低到 0.01%。基于此,推荐以下实践:
同时建议将丢包注入限定在 特定链路或服务,避免全链路干扰,干扰观测。
FunTester 原创精华
【免费合集】从 Java 开始性能测试
故障测试与 Web 前端
服务端功能测试
性能测试专题
Java、Groovy、Go
测试开发、自动化、白盒
测试理论、FunTester 风采
视频专题