尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Linux 内核技术实战课 · TCP 重传模块:把“看不见的丢包“揪出来

Linux 内核技术实战课 · TCP 重传模块:把“看不见的丢包“揪出来
📅 发布时间:2026/7/19 21:01:11

Linux 内核技术实战课 · TCP 重传模块:把"看不见的丢包"揪出来

实验环境说明:本文所有数据全部来自华为云 FlexusX(x2e.8u.16g)双机真实实验——靶机 ecs-665a-0003(私网 192.168.0.198),对端 ecs-665a-0001(私网 192.168.0.13);均为 Ubuntu 24.04.4 LTS、内核6.8.0-106-generic;弱网使用tc netem在两端eth0上真实注入(延迟 + 随机丢包),非 loopback 自环。文中每一个数字均来自真实命令输出,未做任何编造。


一、基础篇 · 如何观测 TCP 重传

TCP 重传是网络中最常见也最容易被误解的现象。很多朋友一上来就tcpdump -i eth0 tcp-retransmit——抱歉,TCP 没有独立的重传标志位,不存在这样的过滤器。那到底怎么查?

1.1 排查四件套

实战中排查 TCP 重传,我依赖以下四板斧,按干扰从小到大排列:

①nstat -az TcpRetransSeg—— 内核实时重传段计数(最轻量)

nstat直接读取内核 SNMP 计数器,不碰网卡、不开抓包,零开销。实验 5 中,我的操作流程:

# 1. 记录基线$ nstat-azTcpRetransSegs#TcpRetransSegs 18697 0.0# 2. 跑流(iperf3 8s,注入 2% 丢包)# 3. 跑流后再次读取$ nstat-azTcpRetransSegs#TcpRetransSegs 33577 0.0# >>> 增量:33577 - 18697 = 14880(段)

结论:增量 14880 段 = 8 秒内因 2% 丢包触发的重传段数。这是最权威的计数,无需任何猜测。

②/proc/net/snmp的TcpRetransSegs—— 文本化累计计数

与nstat同源,只是以文本形式呈现:

$ grep "^Tcp:" /proc/net/snmp Tcp: 1 200 120000 -1 138 9 0 22 3 23577 498890 6019 0 230 0

RetransSegs= 6019(实验 3 跑完 cubic+bbr 后累计值),与同期的nstat输出完全一致。

经验:nstat和/proc/net/snmp读取的是同一组内核计数器,用哪个都行——但关键是看增量,不是看绝对值。重启过的机器初始值接近 0,生产上跑了几周可能几百万,你只需要跑流前后的差值。

③ss -ti—— 单 socket 级重传、RTO、cwnd 全景

nstat是全局计数,如果你想知道具体哪个连接在重传、重传了多少,用ss -ti:

$ ss-tin|grep-A3"5201"cubic wscale:7,7 rto:201 rtt:0.204/0.136 mss:1448 pmtu:1500 rcvmss:536 advmss:1448 cwnd:10 ssthresh:8 bytes_sent:118198829 bytes_retrans:2306664 bytes_acked:115877686 segs_out:81633 segs_in:9631 data_segs_out:81631 send 568Mbps lastrcv:1003 pacing_rate 679Mbps delivery_rate 858Mbps delivered:80029 busy:1002ms unacked:10 retrans:0/1593 rcv_space:14480 rcv_ssthresh:64088 notsent:932512 minrtt:0.056 snd_wnd:2154496

关键指标解读:

字段实验5实测值含义
rto:201201 ms当前超时重传定时器值(动态退避)
rtt:0.204/0.1360.204 ms avg / 0.136 ms mdev平滑 RTT 与抖动
cwnd:1010 段拥塞窗口(已塌缩)
bytes_retrans:2306664约 2.3 MB该连接累计重传字节数
retrans:0/15930 超时 / 1593 段快速重传核心指标——后排详讲
delivery_rate:858Mbps858 Mbps实际投递速率
④tcpdump—— 抓包人工分析(最后手段)

前面三板斧能回答"有没有重传、多少重传",但回答不了"这些重传的包长什么样"。这时才需要抓包:

# 实验5:8 秒抓包,落盘约 857 MB$ tcpdump-ieth0-s94-w/tmp/cap.pcap $ capinfos /tmp/cap.pcap# 文件大小: 857,666,096 bytes# 包含包数: 187,668

抓包后用 Wireshark 打开,重传包的特征是:同一 Seq 号的报文出现两次以上,且后发的包时间晚于前一个。Wireshark 靠[TCP Retransmission]注解帮你标出来,但这只是后处理启发式判定,网卡/内核本身并不会给包打"我是重传"的标签。


二、基础篇 · 重传是怎么发生的

理解了怎么观测,再看重传的两种触发机制。

2.1 超时重传(RTO)

发送端发出一个数据段,启动 RTO 定时器。如果 RTO 超时仍未收到 ACK,则重传该段。

  • RTO 初始值:200 ms(RtoMin)~120 s(RtoMax)
  • 每次超时后 RTO 指数退避(直到 120 s),这就是业务上连接卡死几秒钟的根源

ss -ti中的rto:201就是当前连接的定时器值,retrans:0/1593前半部分(0)就是超时重传次数为 0——说明实验 5 中所有丢包都没有等到超时,这就引出了第二种。

2.2 快速重传(Fast Retransmit)

接收端收到乱序报文(序列号不连续)时,会立即回复重复 ACK(DupACK)或携带 SACK 选项告知发送端缺失哪些段。发送端收到3 个重复 ACK(标准阈值)后,不等 RTO 超时,立即重传缺失的段。

实验 5 的nstat -az拆解就把这个讲透了:

TcpRetransSegs 39774 # 总重传段数 TcpExtTCPFastRetrans 39540 # 快速重传段数 (99.4%!) TcpExtTCPSlowStartRetrans 117 # 超时后慢启动重传段数 (0.3%) TcpExtTCPLostRetransmit 840 # 重传后仍未送达最终判丢 TcpExtTCPSynRetrans 47 # SYN 重传 TcpExtTCPRetransFail 0 # 重传失败的段数=0

TCPFastRetrans(39540) ≫ TCPSlowStartRetrans(117),占比 99.4%——这就是我们说的"健康的重传"。绝大多数丢包被快速重传以毫秒级代价修复了,业务几乎无感知。只有TCPSlowStartRetrans发生时才意味着 RTO 超时、cwnd 塌缩、业务秒级卡顿。

2.3 弱网如何把正常报文变成重传

弱网的本质是两个效应叠加:延迟 + 丢包。

  • 延迟(delay):报文到达慢 → ACK 回来慢 → 发送端发送空窗期增大 → 吞吐下降
  • 丢包(loss):报文丢了 → ACK 缺失 → 触发 dupACK 或 RTO

我们在实验 3 两端各注入delay 30ms loss 1%(RTT ≈ 60ms,双向 1% 随机丢包),cubic 吞吐从内网无注入时的线速降到18.51 Mbps,不是因为带宽不够,而是丢包导致 cwnd 反复塌缩,链路一直被缓慢恢复填满,从未达到高水位。


三、案例篇 · 弱网下 cubic vs bbr 谁更稳

3.1 实验设计

同一组弱网参数(两端 eth0 各delay 30ms loss 1%),同一台 iperf3 服务端,先跑 cubic 再切 bbr,对比差异。

3.2 真实数据对比

指标cubicbbr倍数
发送吞吐18.51 Mbps268.99 Mbps≈14.5×
接收吞吐17.04 Mbps267.87 Mbps≈15.7×
iperf 报告重传1125 段4789 段bbr 更多
nstat 总重传 (含多流累计)6019同口径—

3.3 为什么 bbr 碾压 cubic?

核心原因:cubic 是丢包敏感型算法,一旦检测到丢包就塌缩 cwnd,然后从更小的窗口慢慢恢复——在 1% 随机丢包下,窗口一直在塌缩-恢复-塌缩中循环,链路利用率极低。BBR 基于带宽和 RTT 建模,不把丢包当作拥塞信号,它用 pacing 填满管道,丢包靠快速重传弥补。

3.4 生产上如何切换 bbr

重点踩坑:Ubuntu 24.04 内核默认只在tcp_available_congestion_control中提供reno cubic,没有 bbr。

# 错误示范:直接切换,会报错$sysctl-wnet.ipv4.tcp_congestion_control=bbr# sysctl: setting key "net.ipv4.tcp_congestion_control": No such file or directory

正确姿势:

# 1. 加载 bbr 内核模块$ modprobe tcp_bbr# 2. 确认已加载$sysctlnet.ipv4.tcp_available_congestion_control# net.ipv4.tcp_available_congestion_control = reno cubic bbr# 3. 切换$sysctl-wnet.ipv4.tcp_congestion_control=bbr# 4. (可选)写入 /etc/sysctl.conf 持久化# echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.conf

经验:modprobe tcp_bbr仅当前会话有效,重启后需要重新加载。如需开机自启,建议写入/etc/modules或/etc/modules-load.d/。

3.5 切换 bbr 后的预期管理

从实验 3 的数据可以清晰看到:bbr 的 iperf 报告重传数(4789)比 cubic(1125)高得多。这不叫"bbr 不稳",这叫"bbr 用更多的重传换取了 14.5 倍的吞吐"。在 BBR 的模型里,丢包不是拥塞——你的运维监控如果只看TcpRetransSegs报警,切 bbr 后重传阈值需要重新校准。

生产建议:

  • 长肥管道 / 跨公网 / 无线链路 → 优先 BBR
  • 低延迟内网 / CPU 受限场景 → 可以继续用 cubic
  • 切 bbr 后重传计数器预期升高,阈值建议调整 3-5 倍

四、案例篇 · RTT 抖动如何定位

"用户说慢"是最难排查的问题之一。从 TCP 层面看,RTT 是最直接的诊断维度。

4.1 先打 RTT 基线

$ping192.168.0.13-c5# --- 192.168.0.13 ping statistics ---# 5 packets transmitted, 5 received, 0% packet loss, time 4126ms# rtt min/avg/max/mdev = 0.157/0.189/0.239/0.032 ms

同 VPC 内网,基线 RTT 仅为0.189 ms(亚毫秒级)。

4.2 注入延迟,看变化

本机 eth0 注入 50 ms 延迟:

$ tc qdiscadddev eth0 root netem delay 50ms# 再 ping$ping192.168.0.13-c5# --- 192.168.0.13 ping statistics ---# rtt min/avg/max/mdev = 50.159/50.187/50.232/0.031 ms

RTT 从 0.189 ms 精确变为50.187 ms,差值 50 ms = 注入延迟。这一步就验证了延迟确确实实来自本机 egress 路径。

4.3 ss -tin 验证连接级 RTT

$ ss-tin|grep-A3"5201"cubic wscale:7,7 rto:251 rtt:50.187/0.032 mss:1448 pmtu:1500 rcvmss:536 advmss:1448 cwnd:1977 ssthresh:1889 bytes_sent:68724277 bytes_retrans:915880 bytes_acked:64945726 segs_out:47473 segs_in:1308 data_segs_out:47471 send 456324706bps lastsnd:11 lastrcv:1801 lastack:11 pacing_rate 547586912bps delivery_rate 455343000bps delivered:44877 app_limited busy:1800ms rwnd_limited:207ms(11.5%)sndbuf_limited:101ms(5.6%)unacked:1977 retrans:0/633 dsack_dups:15 reordering:28 reord_seen:2 rcv_space:14480 rcv_ssthresh:64088 notsent:1319128 minrtt:50 snd_wnd:3954176
  • rtt:50.187/0.032→ 与 ping 结果一致,确认是本机侧延迟
  • pmtu:1500/mss:1448→ 链路 MTU 无问题
  • delivery_rate:455 Mbps→ 即使有 50ms 延迟,大窗口(cwnd=1977)仍能填满
  • retrans:0/633→ 0 超时重传,633 段快速重传
  • bytes_retrans:915880→ 该连接累计重传 ~916 KB

4.4 关联 sysctl:连接建立与保活

实验 1 中记录了与连接生命周期相关的 sysctl:

net.ipv4.tcp_syncookies=1# SYN Cookie 防 SYN Flood(生产保持开启)net.ipv4.tcp_tw_reuse=2# 允许复用 TIME-WAIT 连接(设为2=仅安全场景)net.ipv4.tcp_fin_timeout=60# FIN-WAIT-2 超时 60snet.ipv4.tcp_max_syn_backlog=1024# SYN 半连接队列上限net.core.somaxconn=4096# 全连接 accept 队列上限(sshd 监听 :22 的 Send-Q=4096)net.ipv4.tcp_abort_on_overflow=0# 全连接队列满时不暴力 RST(默认优雅丢弃)

4.5 关联 sysctl:收发缓冲区与协议特性

实验 2 中记录的缓冲区参数:

net.ipv4.tcp_rmem=40961310726291456# 读缓冲区 min-default-max(字节)net.ipv4.tcp_wmem=4096163844194304# 写缓冲区 min-default-max(字节)net.ipv4.tcp_mem=179415239221358830# TCP 全局内存(单位:页=4KiB)# 179415×4K ≈ 734 MiB(min)# 239221×4K ≈ 935 MiB(pressure 阈值)# 358830×4K ≈ 1.47 GiB(max)net.ipv4.tcp_sack=1# 选择性 ACK(开启,加速丢包判断)net.ipv4.tcp_window_scaling=1# 窗口缩放(开启,长肥管道必备)net.ipv4.tcp_timestamps=1# 时间戳选项(开启,精确 RTT 计算)

尤其是tcp_sack=1与tcp_window_scaling=1,它们是快速重传高效工作的基础设施——没有 SACK,发送端只能收到累积 ACK,不知道丢了哪几个段;没有 Window Scaling,窗口最大 65535 字节,在 50ms RTT 下带宽瓶颈只有 ~10 Mbps。

4.6 路由与 MTU 验证

# 确认流量走哪个网卡$iproute get192.168.0.13# 192.168.0.13 dev eth0 src 192.168.0.198 uid 0# cache# 验证链路 MTU:1472(DATA) + 28(ICMP+IP头) = 1500,DF=不分片$ping-Mdo-s1472192.168.0.13-c3# 1480 bytes from 192.168.0.13: icmp_seq=1 ttl=64 time=50.2 ms# 3 packets transmitted, 3 received, 0% packet loss

1500 字节(DF)探测成功,链路 MTU ≥ 1500,无需 PMTU 绕行。


五、分析篇 · 一步一步分析真实重传

最后,我把实验 5 的完整排查链路整理为一份TCP 重传排查清单,照着做就能复现。

5.1 复现步骤

Step 1:记录重传计数基线

$ nstat-azTcpRetransSegs# TcpRetransSegs = 18697$grep"^Tcp:"/proc/net/snmp|awk'{print "RetransSegs:",$NF}'# RetransSegs: 18697

两个数据源同源,交叉确认。

Step 2:注入弱网(模拟真实链路丢包)

$ tc qdiscadddev eth0 root netem loss2%

Step 3:起 iperf3 流并同时抓包

服务端:

$ iperf3-s-D

客户端(对端 192.168.0.13):

$ iperf3-c192.168.0.198-t8

本机抓包:

$ tcpdump-ieth0-s94-w/tmp/cap.pcap&sleep9;kill%1

Step 4:跑流后读数

$ nstat-azTcpRetransSegs# TcpRetransSegs = 33577# 增量 = 33577 - 18697 = 14880 段(8秒内净增)

Step 5:ss -ti 看哪个连接在重传

$ ss-tin|grep-A3"5201"# retrans:0/1593 → 0 超时,1593 段快速重传# bytes_retrans:2306664 → 2.3 MB 累计重传# rto:201 → RTO 定时器 201ms

Step 6:nstat -az 全量拆解重传构成

$ nstat-az# TcpRetransSegs 39774# TcpExtTCPFastRetrans 39540 # 99.4%# TcpExtTCPSlowStartRetrans 117 # 0.3%# TcpExtTCPLostRetransmit 840 # 重传后仍丢# TcpExtTCPSynRetrans 47 # SYN 重传# TcpExtTCPRetransFail 0 # 全部重传成功

Step 7:清理

$ tc qdisc del dev eth0 root $pkill-xiperf3

5.2 快速判断矩阵

观测现象可能的根因确认手段
TcpRetransSegs持续增长链路存在丢包ss -ti看单连接 retrans
TCPSlowStartRetrans占比高RTO 超时频繁,链路极度拥塞看 cwnd 是否持续 < 10
TCPFastRetrans占比高,吞吐正常少量随机丢包,系统健康无需处理,这是正常工作方式
bytes_retrans大但retrans:0/0重传历史数据,当前无丢包对比前后两次观察
rtt突然增大(如 0.2ms → 50ms)链路路径延迟增加ping验证 +ip route get
rto接近 RtoMax(120s)连接即将超时断开检查对端是否存活
TcpExtTCPLostRetransmit增长快重传仍丢,链路质量极差需要网络团队配合

六、本模块要点速记

  1. TCP 重传没有独立标志位,不能用单条 tcpdump 过滤器直接抓"重传包"
  2. 排查四件套:nstat(内核计数)→/proc/net/snmp(文本计数)→ss -ti(单连接)→tcpdump(抓包后处理)
  3. 看增量,别看绝对值——TcpRetransSegs跑流前后差值才是权威数字
  4. 大部分重传是健康的——TCPFastRetrans ≫ TCPSlowStartRetrans是正常状态
  5. BBR 在丢包弱网下吞吐 ≈ cubic 的 14.5 倍,但重传计数也会更高,这是预期行为
  6. 切 BBR 必须先modprobe tcp_bbr,Ubuntu 24.04 内核默认没有加载
  7. ss -tin的rtt字段直接读出连接级 RTT + 抖动,是定位"慢"的第一工具
  8. SACK / Window Scaling / Timestamps是快速重传高效工作的基础设施,不要关

七、下篇预告

重传问题搞定后,另一类让 SRE 头疼的问题浮出水面——“CPU 利用率没有明显异常,但应用就是慢”。下一节我们将进入内核态 CPU 利用率飙高模块,从perf top、/proc/softirqs到netstat -s软中断计数,手把手排查ksoftirqd 跑满、NET_RX 软中断分发不均衡、napi_poll 次数暴涨、单核 softirq 飙到 80%+ 的典型案例。

敬请期待。

相关新闻

  • Unity导出Android项目BuildIl2CppTask报错:5大原因与系统化解决方案
  • 芝柏官方服务项目及价格查询|网点地址及24小时电话权威信息通告(2026年7月最新) - 亨得利官方服务中心
  • ZBrush2026.2.1免安装版全面解析:部署指南与性能优化

最新新闻

  • 向华为学习——解读华为等级保护三级系统安全解决方案【附全文阅读】
  • 2026年7月最新卡地亚中国区售后服务网络更新优化 全国60+门店地址及电话汇总 - 亨得利中国服务中心
  • 2026年7月戴尔DELL官方售后服务中心官方地址与24小时热线信息更新通知 - 优企甄选
  • C++内存泄漏排查实战:Valgrind与AddressSanitizer工具详解
  • 生成式引擎优化(GEO)技术详解:与 SEO 的核心差异与落地常识
  • Codex CLI实战指南:AI编程代理的安装配置与核心使用技巧

日新闻

  • 百达翡丽官方服务项目及价格查询|维修地址与电话权威信息通告(2026年7月最新) - 百达翡丽服务中心
  • 2026年药食同源冲泡饮品哪家好:衡身堂三伏天内调外养 - 晚香时候
  • 芝柏官方更换原装表带价格查询|详细地址与24小时客服电话权威信息公告(2026年7月最新) - 亨得利官方服务中心

周新闻

  • SaaS软件行业GEO实践:AI搜索时代的品牌可见性与获客新路径
  • 什么是PCTFE?医药高端包装的“防潮王牌“材料
  • 【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号