TCP 重传率 1%,如何区分是网络丢包还是接收窗口满
解读
面试官给出“1% 重传率”这一量化指标,核心想考察两点:
- 能否把“传输层现象”拆成“网络层/链路层丢包”与“传输层流控丢包”两类根因;
- 能否用国内数据中心、云厂商、办公网真实可抓到的数据,给出低成本、可落地的判别步骤,而不是背 RFC。
知识点
-
TCP 重传触发条件
- 超时重传(RTO):RTT 采样后计算出的 RTO 内未收到 ACK;
- 快速重传:收到 3 个重复 ACK 立即重传,不等待 RTO。
-
接收窗口满导致的“丢包”本质 接收缓冲区无空间,协议栈把后续包直接丢弃,发送端收不到 ACK,最终只能走“超时重传”路径;不会触发 3 个重复 ACK,因此不会有 Fast Retransmit。
-
网络链路丢包特征
- 随机比特错误、队列溢出、QoS 限速、光纤衰耗、运营商拥塞等;
- 丢包位置不可预测,可能落在乱序包中,常触发 3 个重复 ACK,出现 Fast Retransmit。
-
国内常用观测手段
- Linux ss -ti、nstat -az、/proc/net/netstat 可输出 TCP 重传段数、快速重传段数、RTO 超时次数;
- 云监控:阿里云“网络性能分析 NPA”、腾讯云“云拨测”、华为云“VPC 流日志”可直接给出丢包点;
- 抓包:tcpdump 或云厂商“流量镜像”到 ES,Wireshark 专家信息一键统计 Retransmission vs Fast Retransmission;
- 应用层日志:Nginx、Envoy、Dubbo 3 默认打印 upstream RT、socket error,可侧面佐证。
答案
“1% 重传率”只是结果,区分思路分三步,全部基于现网可拿到的指标,不依赖额外压测。
第一步:看“重传方式” 在 Linux 服务器上执行
nstat -az | egrep 'TcpRetransSegs|TcpFastRetrans|TcpTimeoutRetrans'
- 若 TcpFastRetrans/TcpRetransSegs ≥ 70%,说明多数重传由 3 个重复 ACK 触发,链路随机丢包概率大;
- 若 TcpTimeoutRetrans/TcpRetransSegs ≥ 70%,则多数重传等满 RTO,高度怀疑接收窗口满或严重乱序。
第二步:看“接收窗口是否打满”
- 同一台机器
ss -ti | grep -i 'rcv_space|rtt|retrans'
持续观察“rcv_space”接近“rcv_ssthresh”且不再增长,同时 RTT 没有明显抖动,可判定接收缓冲区瓶颈; 2. 对端是 Java/Go 服务,把 JVM/Go runtime 的 receive buffer 大小打印到监控,若 99th 时刻 buffer 利用率≈100%,即可确认窗口满。
第三步:看“链路是否丢包”
- 云环境直接读“云监控→私有网络→丢包率”曲线,若交换机、网关、运营商接口在同一时段出现丢包,则归因为网络;
- 物理机房用“镜像口+Wireshark”算“Out-Of-Order + Duplicate ACK”比例,若与重传段数时间对齐,也可确认链路丢包。
综合判定:
- 快速重传占比高 + 云监控显示链路丢包 > 0 → 网络丢包;
- 超时重传占比高 + 接收窗口长期打满 + 链路丢包≈0 → 接收窗口满;
- 两者比例接近,则属于混合场景,需同时扩容接收缓冲并检查网络质量。
拓展思考
- 微服务场景下,接收窗口满往往伴随“应用消费慢”而非单纯 buffer 设小了,可结合业务日志看线程池、GC、CPU 抢占,定位“伪网络问题”。
- 1% 重传率在 10 Gbps 专线看似不高,但对延迟敏感的交易链路可能把 99th RTT 抬高 3~5 倍,需换算成“重传时间占比”再评估是否值得优化。
- 国内多线 BGP 机房常有“跨运营商偶发丢包 0.1%~0.3%”,建议把“重传率”与“TCP 握手失败率、零窗口通告次数”一起纳入 SLA 看板,避免单指标误报。
- 若定位到窗口满,调大 net.core.rmem_max 只是第一步,更要让应用异步消费;若定位到网络丢包,优先排查 QoS、 ECN、网卡 offloading 与光纤误码,而不是盲目扩容带宽。