TCP 重传率 1%,如何区分是网络丢包还是接收窗口满

解读

面试官给出“1% 重传率”这一量化指标,核心想考察两点:

  1. 能否把“传输层现象”拆成“网络层/链路层丢包”与“传输层流控丢包”两类根因;
  2. 能否用国内数据中心、云厂商、办公网真实可抓到的数据,给出低成本、可落地的判别步骤,而不是背 RFC。

知识点

  1. TCP 重传触发条件

    • 超时重传(RTO):RTT 采样后计算出的 RTO 内未收到 ACK;
    • 快速重传:收到 3 个重复 ACK 立即重传,不等待 RTO。
  2. 接收窗口满导致的“丢包”本质 接收缓冲区无空间,协议栈把后续包直接丢弃,发送端收不到 ACK,最终只能走“超时重传”路径;不会触发 3 个重复 ACK,因此不会有 Fast Retransmit。

  3. 网络链路丢包特征

    • 随机比特错误、队列溢出、QoS 限速、光纤衰耗、运营商拥塞等;
    • 丢包位置不可预测,可能落在乱序包中,常触发 3 个重复 ACK,出现 Fast Retransmit。
  4. 国内常用观测手段

    • 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,高度怀疑接收窗口满或严重乱序。

第二步:看“接收窗口是否打满”

  1. 同一台机器

ss -ti | grep -i 'rcv_space|rtt|retrans'

持续观察“rcv_space”接近“rcv_ssthresh”且不再增长,同时 RTT 没有明显抖动,可判定接收缓冲区瓶颈; 2. 对端是 Java/Go 服务,把 JVM/Go runtime 的 receive buffer 大小打印到监控,若 99th 时刻 buffer 利用率≈100%,即可确认窗口满。

第三步:看“链路是否丢包”

  1. 云环境直接读“云监控→私有网络→丢包率”曲线,若交换机、网关、运营商接口在同一时段出现丢包,则归因为网络;
  2. 物理机房用“镜像口+Wireshark”算“Out-Of-Order + Duplicate ACK”比例,若与重传段数时间对齐,也可确认链路丢包。

综合判定:

  • 快速重传占比高 + 云监控显示链路丢包 > 0 → 网络丢包;
  • 超时重传占比高 + 接收窗口长期打满 + 链路丢包≈0 → 接收窗口满;
  • 两者比例接近,则属于混合场景,需同时扩容接收缓冲并检查网络质量。

拓展思考

  1. 微服务场景下,接收窗口满往往伴随“应用消费慢”而非单纯 buffer 设小了,可结合业务日志看线程池、GC、CPU 抢占,定位“伪网络问题”。
  2. 1% 重传率在 10 Gbps 专线看似不高,但对延迟敏感的交易链路可能把 99th RTT 抬高 3~5 倍,需换算成“重传时间占比”再评估是否值得优化。
  3. 国内多线 BGP 机房常有“跨运营商偶发丢包 0.1%~0.3%”,建议把“重传率”与“TCP 握手失败率、零窗口通告次数”一起纳入 SLA 看板,避免单指标误报。
  4. 若定位到窗口满,调大 net.core.rmem_max 只是第一步,更要让应用异步消费;若定位到网络丢包,优先排查 QoS、 ECN、网卡 offloading 与光纤误码,而不是盲目扩容带宽。