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。
怎么解决?
- 升级链路带宽:最直接,但花钱。
- 调整队列调度:给UDP业务配置优先级队列(PQ),保证关键流量优先转发。
- 启用流量整形:在入方向做限速,避免微突发。
- 增大缓存:部分交换机支持调整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)。其中一条下一跳指向了一台已经下线的旧路由器。这就是典型的黑洞路由。
关键点:黑洞路由通常发生在网络变更之后。比如某台设备被移除,但路由表中指向它的静态路由没有删除。或者动态路由协议收敛慢,导致临时黑洞。
排查路由环路和黑洞路由的方法:
- 查看路由表:
show ip route <目标网段>,确认下一跳是否可达。 - 跟踪路由:
traceroute或mtr,看数据包路径是否出现重复跳数。 - 检查TTL:如果
traceroute显示TTL在某个节点突然归零,说明那里发生了环路。 - 查看CPU:路由环路会导致路由器CPU飙升,因为数据包被反复处理。
怎么修复?
- 静态路由:删除或修正指向错误下一跳的静态路由。
- 动态路由:检查OSPF/BGP邻居状态,确保路由收敛正常。可以启用
loopguard或route-map过滤异常路由。 - 黑洞路由预防:在边界路由器上配置
null0路由,把无法到达的流量引向黑洞,避免环路。但这需要配合精确的静态路由使用。
2.4 知识体系总览
下面这张图,我把网络层丢包的三个原因、排查方法和修复手段串起来了。你排查时,可以按这个思路走。
嗯,网络层丢包排查,说白了就是“望闻问切”。望——看计数器;闻——抓包分析;问——问网络变更历史;切——traceroute摸脉。把这套流程走一遍,大部分问题都能定位到。