
Linux 没有直接输出“TCP重传率百分比”的命令,必须用 /proc/net/snmp 中同一时间窗口内 TCPRetransSegs 与 TcpOutSegs 的增量比值计算——这才是可比、可告警的真实重传率。
用 /proc/net/snmp 算瞬时重传率(最轻量可靠)
这是所有内核都支持、容器友好的方式,不依赖 net-tools 或额外包:
-
cat /proc/net/snmp | grep -A1 Tcp | tail -n1输出类似:Tcp: RtoAlgorithm RtoMin RtoMax ... InSegs OutSegs RetransSegs InErrs ... - 第 11 列是
OutSegs(总发出段数),第 15 列是RetransSegs(已重传段数) - 不能直接拿绝对值相除——必须取两组采样点的差值:
(RetransSegs₂ − RetransSegs₁) ÷ (OutSegs₂ − OutSegs₁) - 用
watch -n1 'cat /proc/net/snmp | grep -A1 Tcp | tail -n1'观察 5–10 秒,手动记下两组值即可算出 - 结果 > 0.005(即 0.5%)需关注;> 0.02(2%)说明链路已明显丢包,应立刻排查
用 nstat 看每秒增量(更省事)
nstat 是 sysstat 提供的专用网络统计工具,自动处理差值和单位,比手算更稳:
- 运行
watch -n 1 'nstat -z -t 1 | grep -E "TcpRetransSegs|TcpOutSegs"' - 输出第二列是「上一秒内的增量」,例如:
TcpRetransSegs 123 0.0和TcpOutSegs 9876 0.0→ 该秒重传率 ≈ 123 / 9876 ≈ 1.25% -
-t 1表示按 1 秒聚合,-z过滤掉零值,避免干扰 - 注意:
TcpOutSegs包含纯 ACK,所以这个比值偏保守,但趋势判断完全够用
用 ss -ti 查单连接重传次数(别误读字段)
ss -ti 的 retransmits 字段常被当成“总重传数”,但它只统计超时重传(RTO timeout),不包括快速重传、SACK 或 TLP:
- 执行
ss -ti state established,看每行末尾的retransmits值 - 该值在连接关闭后清零,无法回溯;即使
TCPRetransSegs持续上涨,它也可能为 0 - 它对应
/proc/net/snmp中的TCPTimeouts,不是TCPRetransSegs - 真要定位高重传流:先用
ss -tunap找目标四元组,再加-i查其retransmits;若值 > 0 且持续增长,说明该流路径存在稳定丢包
为什么 sar -n TCP 不行,以及常见翻车点
sar -n TCP 实际无效——官方文档和内核源码中根本不存在这个子选项,执行会报错或静默忽略:
- 有人误用
sar -n TCP 1 3,结果什么也没输出,或返回其他协议层数据(如 DEV) - 真正能用的是
sar -n ETCP(扩展 TCP 统计),它提供retransmit(累计重传段数)、orsts、inerrs等字段,但仍是快照,仍需自己做差值 -
netstat -s是对/proc/net/snmp的文本封装,在最小化系统或容器里常不可用;更重要的是字段解析逻辑不透明,容易误判 - 别信
ss -s:它不显示重传细节,只汇总 socket 数量,对重传分析无用
重传率的核心陷阱在于混淆“类型”和“粒度”:全局重传率要看 TCPRetransSegs/TcpOutSegs 增量,单连接行为要看 ss -ti 的 retransmits(仅 RTO),而真实丢包源头可能得靠 tcpretrans 或抓包。三者不能混用,也不能只看一个。











