nstat 是唯一能直接输出每秒重传段数的工具,其第二列即为上一秒增量,如 TcpRetransSegs 27 表示该秒重传 27 段;ss -ti 的 retransmits 是连接级累计超时次数,非频率;/proc/net/snmp 需手动差值计算;sar -n TCP 的 retrans/s 已是瞬时频率。

用 nstat 看每秒重传段数(最准、最省事)
想知“具体频率”,本质是问「单位时间内重传了多少次」,不是看累计值,而是看增量速率。nstat 是唯一能直接输出「每秒重传段数」的系统工具,且自动做差值、单位归一:
运行 watch -n 1 'nstat -z -t 1 | grep -E "TcpRetransSegs|TcpOutSegs"',你会看到类似:
TcpRetransSegs 27 0.0 TcpOutSegs 5432 0.0
第二列就是上一秒内的增量——这里表示该秒重传了 27 段,总发段 5432 段。频率即 27 次/秒;若要换算成比例,就用 27 ÷ 5432 ≈ 0.5%。
注意:-t 1 表示按 1 秒聚合,-z 过滤掉零值,避免干扰;不加 -t 默认是自启动以来的累计值,毫无频率意义。
ss -ti 的 retransmits 字段不能当频率用
很多人执行 ss -ti state established 后盯着末尾的 retransmits 值,以为它代表“每秒重传次数”,这是典型误读:
这个字段只记录该连接**超时重传(RTO timeout)发生的总次数**,且连接关闭后清零;它不随时间推移自动累加,也不会重置为每秒计数。
例如你看到某行末尾是 retransmits:3,只说明这个连接至今触发过 3 次 RTO 超时,无法判断是 3 秒内发生还是 3 小时内发生。
- 它对应的是 /proc/net/snmp 中的
TCPTimeouts,不是TCPRetransSegs - 它不包含快速重传(3×dupACK)、SACK 重传或 TLP,所以即使网络丢包严重,该值也可能长期为 0
- 真要观察变化趋势,得反复执行
ss -ti并手动比对同一连接的值是否在增长——但无法得出“频率”,只能确认“是否在持续出问题”
用 /proc/net/snmp 手动算瞬时频率(轻量、通用、容器可用)
如果环境没装 nstat(比如精简镜像),就靠 /proc/net/snmp 自己算:它提供 TCPRetransSegs(第 15 列)和 TcpOutSegs(第 11 列)两个绝对值,必须取两组采样点的差值才能得到真实频率。
- 执行
watch -n 1 'cat /proc/net/snmp | grep -A1 Tcp | tail -n1',等 5–10 秒,记下两组值 - 假设第一组:RetransSegs=12345,OutSegs=987654;第二组:RetransSegs=12372,OutSegs=988120
- 则重传频率 = (12372 − 12345) ÷ (10 − 0) = 2.7 次/秒;总发段频率 = (988120 − 987654) ÷ 10 = 46.6 段/秒
- 注意:分母是采样间隔秒数,不是 OutSegs 差值——前者才是“频率”的物理单位(次/秒)
这个方法所有内核版本都支持,不依赖任何额外包,适合嵌入式或容器场景。
sar -n TCP 的 retrans/s 是协议栈级频率,但别直接除
sar -n TCP 1 3 输出里的 retrans/s 列确实是每秒重传段数,但它和 oseg/s 都是快照差值,本身已带“/s”单位,可直接当频率用。
-
retrans/s值突增(比如从 0 跳到 50+)比百分比更早暴露问题 - 不要用
retrans/s ÷ oseg/s算“重传率”——因为oseg/s包含大量纯 ACK 段,导致分母虚高,比值偏低且失真 - 真正该关注的是
retrans/s+atmptf/s+estres/s是否同步上涨:三者齐升大概率指向路径丢包或延迟抖动
记住:sar -n TCP 不是实时滚动命令,每次执行都是独立快照;想连续观察,必须靠 watch 或脚本轮询——这点常被忽略,导致误以为它“卡住”或“没输出”。


















