2. 网络层丢包:路由器/交换机缓存溢出、MTU分片与重组失败、路由环路与黑洞路由

网络层丢包,说白了就是数据包在IP层就被“干掉”了。你应用层发出去的数据,到了这一层可能连个响儿都没有。我排查过很多UDP丢包案例,最后发现根因都在网络层。这一节,咱们就聊聊最常见的三个“杀手”。

核心观点:网络层丢包通常不是应用代码的问题,而是设备或链路配置的问题。排查时,先看设备计数器,再看路径MTU,最后查路由表。

2.1 路由器/交换机缓存溢出

先问个问题:你见过路由器“撑死”吗?

路由器转发数据包,靠的是内部缓存(Buffer)。当瞬间流量超过转发能力时,数据包就得排队。如果队列满了,新来的包就直接被丢弃。这就是缓存溢出。

我个人习惯把缓存溢出分成两类:

  • 微突发(Microburst):毫秒级的流量尖峰。你监控平均带宽只有50%,但实际某几毫秒内可能冲到200%。交换机来不及处理,直接丢包。
  • 持续拥塞:链路长期跑满,比如出口带宽只有100M,但业务流量持续120M。这种丢包是持续的,很好发现。

我在项目中遇到过最典型的场景:视频监控平台,UDP流从摄像头到NVR。偶尔画面卡顿,但ping不丢包。后来我登录核心交换机,敲了 show interface counters errors,发现出方向有大量 output drops。嗯,就是缓存溢出了。

排查技巧:大多数厂商的交换机都支持查看丢包计数器。Cisco用 show interface <interface> | include drops,华为用 display interface <interface> | include error。重点关注 output drops 和 buffer failures。

怎么解决?

  1. 升级链路带宽:最直接,但花钱。
  2. 调整队列调度:给UDP业务配置优先级队列(PQ),保证关键流量优先转发。
  3. 启用流量整形:在入方向做限速,避免微突发。
  4. 增大缓存:部分交换机支持调整Buffer大小,但治标不治本。

2.2 MTU分片与重组失败

MTU(最大传输单元)是网络层的“门框”。以太网标准MTU是1500字节。如果你的UDP报文超过这个值,IP层就会分片。

分片本身不是问题,问题出在重组上。UDP不像TCP那样有自动重传机制。一旦某个分片在传输中丢失,接收端就无法重组完整报文,整个UDP包就废了。

我曾经排查过一个跨公网的UDP传输问题:两个数据中心之间同步日志,偶尔丢包率高达5%。检查链路、设备都没问题。最后我用 ping -M do -s 1472 测试路径MTU,发现中间某段链路的MTU只有1400。UDP报文超过1400字节时,中间路由器尝试分片,但分片被防火墙拦截了。

避坑指南:很多防火墙默认会丢弃IP分片包,认为这是安全风险。如果你的UDP应用需要传输大报文,要么在应用层控制报文大小(建议<1400字节),要么在防火墙上放行分片包。

排查MTU问题的标准步骤:

步骤 命令/操作 说明
1 ping -M do -s 1472 <目标IP> 测试路径MTU是否支持1500字节(Linux)
2 tcpdump -i any 'icmp[0]==3 and icmp[1]==4' 抓取“需要分片但DF标志置位”的ICMP消息
3 ip route get <目标IP> 查看路由缓存中的PMTU值

如果发现路径MTU小于1500,你有两个选择:

  • 应用层调整:把UDP发送缓冲区大小设为 MTU - IP头(20) - UDP头(8) = 1472 字节以内。
  • 网络层调整:在路由器上强制设置接口MTU,或者启用PMTUD(路径MTU发现)。但PMTUD依赖ICMP消息,很多网络会屏蔽ICMP,导致失效。

2.3 路由环路与黑洞路由

路由环路,就是数据包在路由器之间来回转圈,直到TTL归零被丢弃。黑洞路由,则是路由表指向了一个不存在的下一跳,数据包进去就没了。

这两种情况都会导致UDP丢包,而且丢得很“干净”——应用层完全收不到任何反馈。

我记得有一次帮客户排查VoIP通话质量问题。通话时断时续,但网络监控显示链路正常。我登录核心路由器,查看路由表,发现去往VoIP服务器网段有两条等价路由(ECMP)。其中一条下一跳指向了一台已经下线的旧路由器。这就是典型的黑洞路由。

关键点:黑洞路由通常发生在网络变更之后。比如某台设备被移除,但路由表中指向它的静态路由没有删除。或者动态路由协议收敛慢,导致临时黑洞。

排查路由环路和黑洞路由的方法:

  1. 查看路由表:show ip route <目标网段>,确认下一跳是否可达。
  2. 跟踪路由:traceroute 或 mtr,看数据包路径是否出现重复跳数。
  3. 检查TTL:如果 traceroute 显示TTL在某个节点突然归零,说明那里发生了环路。
  4. 查看CPU:路由环路会导致路由器CPU飙升,因为数据包被反复处理。

怎么修复?

  • 静态路由:删除或修正指向错误下一跳的静态路由。
  • 动态路由:检查OSPF/BGP邻居状态,确保路由收敛正常。可以启用 loopguard 或 route-map 过滤异常路由。
  • 黑洞路由预防:在边界路由器上配置 null0 路由,把无法到达的流量引向黑洞,避免环路。但这需要配合精确的静态路由使用。

2.4 知识体系总览

下面这张图,我把网络层丢包的三个原因、排查方法和修复手段串起来了。你排查时,可以按这个思路走。

网络层UDP丢包排查知识体系 缓存溢出 MTU分片与重组失败 路由环路/黑洞路由 output drops 计数器增长 ICMP 需要分片消息 traceroute 跳数重复 查看接口计数器 分析流量峰值 ping -M do 测试MTU tcpdump 抓ICMP 查看路由表 检查CPU负载 升级带宽/队列调整 流量整形 应用层限制报文大小 调整接口MTU 修正静态路由 配置null0黑洞路由 排查顺序:先看计数器 → 再测MTU → 最后查路由表

嗯,网络层丢包排查,说白了就是“望闻问切”。望——看计数器;闻——抓包分析;问——问网络变更历史;切——traceroute摸脉。把这套流程走一遍,大部分问题都能定位到。