4. 丢包原因分析:网络拥塞、缓冲区溢出、防火墙规则、MTU问题、硬件故障

UDP 丢包了,别急着骂运营商。说实话,大部分丢包都不是玄学,而是有迹可循的。我做了这么多年网络排障,总结下来,原因基本就这五类:网络拥塞、缓冲区溢出、防火墙规则、MTU 问题、硬件故障。

咱们一个一个来拆解。你拿着 Wireshark 抓包,心里得有个谱——到底该看哪里?

核心观点: 丢包原因不是猜出来的,是用证据链锁定的。Wireshark 就是你的证据收集器。

UDP丢包原因分类与排查路径 UDP 丢包原因分类与排查路径 UDP 丢包 网络拥塞 缓冲区溢出 防火墙规则 MTU 问题 硬件故障 排查路径:先看 Wireshark 统计 → 再查系统日志 → 最后定位硬件 Wireshark 关键指标 • 重传/快速重传统计 • ICMP 不可达报文 • 时间戳差值分析 • 窗口缩放因子 系统侧排查命令 • netstat -s • ifconfig/ip -s • ethtool -S • ss -u -a 常见误判 • 把乱序当成丢包 • 把延迟抖动当成丢包 • 忽略单向丢包 • 忘记看校验和

4.1 网络拥塞——最常见的丢包元凶

说白了,就是路太窄,车太多。UDP 本身没有 TCP 那样的拥塞控制机制,发送端只管发,网络设备(路由器、交换机)一旦处理不过来,就只能把包扔掉。

怎么判断?我一般先看 Wireshark 的 IO Graph。如果流量曲线突然掉下去,然后又恢复,十有八九是拥塞丢包。另外,Expert Info 里如果出现大量 "Previous segment not captured" 或者 "ACKed lost segment",也是信号。

我的经验: 有一次帮客户排查视频会议卡顿,抓包发现每 3 秒就有一波丢包。后来发现是公司出口带宽被备份任务占满了。限速之后,问题消失。记住:UDP 不会自己减速,你得帮它减。

排查拥塞,可以看这几个指标:

  • Wireshark 统计 → 吞吐量图:看有没有周期性下降。
  • RTT 变化:拥塞时 RTT 会明显增大。
  • ICMP Source Quench(虽然很少见了):老设备还会发这个。
  • 系统侧:netstat -s 看 "packet receive errors" 是否持续增长。

4.2 缓冲区溢出——接收端来不及处理

这个跟拥塞有点像,但问题出在端侧。接收端的 socket 缓冲区满了,内核就把新来的 UDP 包直接扔掉。嗯,这里要注意:UDP 没有流控,应用层读得慢,缓冲区就爆了。

我在项目中遇到过这种情况:一个日志采集程序,用 UDP 接收数据,但写磁盘太慢,导致 socket 接收缓冲区溢出。Wireshark 上看不到任何异常,但应用就是丢数据。

避坑指南: 我曾经调大过 Linux 的 net.core.rmem_max 和 net.core.rmem_default,但没调 net.core.netdev_max_backlog,结果还是丢。这三个参数要一起调。

排查方法:

  1. 在接收端执行 netstat -su | grep "receive errors",看 errors 是否增长。
  2. 用 ss -u -a 查看当前 socket 的接收队列(Recv-Q)。
  3. Wireshark 里看有没有 TCP Window Full(如果是 TCP 辅助判断),UDP 则看应用层日志。

调优参数参考:

参数 默认值 建议值 说明
net.core.rmem_default 212992 26214400 UDP 接收缓冲区默认大小
net.core.rmem_max 212992 67108864 UDP 接收缓冲区最大大小
net.core.netdev_max_backlog 1000 5000 网卡队列最大包数

4.3 防火墙规则——被误杀的 UDP 包

防火墙和安全组是 UDP 丢包的隐形杀手。UDP 是无连接的,防火墙没法像 TCP 那样跟踪连接状态,所以很多防火墙对 UDP 的策略就是「宁可错杀一千,不可放过一个」。

我见过最坑的一次:客户说视频通话经常断,抓包发现 UDP 包发出去后,对端没收到。查了半天,发现是云平台的安全组规则只放行了 TCP 端口,UDP 端口被默认拒绝了。

排查技巧: 在 Wireshark 里过滤 icmp.type == 3(ICMP 不可达),如果看到大量 "Destination Unreachable (Port unreachable)" 或 "Communication Administratively Prohibited",基本就是防火墙在丢包。

防火墙丢包的常见场景:

  • 状态防火墙超时:UDP 没有连接状态,防火墙会维护一个伪状态,超时后就丢弃后续包。
  • 速率限制:很多防火墙对 UDP 有默认的速率限制(比如每秒 1000 个包)。
  • 分片包拦截:有些防火墙会直接丢弃 UDP 分片包。
  • 应用层网关(ALG)问题:SIP、DNS 等协议的 ALG 可能误改或丢弃包。

4.4 MTU 问题——包太大,路不通

MTU(最大传输单元)是链路层能承载的最大数据包大小。以太网一般是 1500 字节。如果 UDP 包超过路径上某个设备的 MTU,就会被分片或直接丢弃。

UDP 不像 TCP 那样有 MSS(最大分段大小) 协商机制,所以应用层发大包时很容易踩坑。我记得有一次排查一个文件传输工具,发小文件没问题,发大文件就丢包。后来发现是 VPN 隧道把 MTU 降到了 1400,而应用层发了 1472 字节的 UDP 包,结果全被丢了。

我的习惯: 在 Wireshark 里过滤 ip.flags.mf == 1 或 ip.frag_offset > 0,看有没有分片。如果分片很多,说明 MTU 可能有问题。另外,ICMP 的 "Fragmentation Needed"(Type 3, Code 4)是明确信号。

MTU 问题的排查步骤:

  1. 用 ping -M do -s 1472 [目标IP](Linux)测试路径 MTU。
  2. 在 Wireshark 里看 ICMP 不可达报文,确认是哪一跳设备返回的。
  3. 检查中间设备(路由器、VPN、隧道)的 MTU 配置。
  4. 应用层做 UDP 分片 或限制发送大小。

4.5 硬件故障——物理层的锅

这个比较少见,但一旦出现,就是大问题。网卡、网线、光模块、交换机端口,任何一个环节出问题,都会导致丢包。

硬件故障的典型表现是:丢包率稳定且持续,不像拥塞那样有波动。而且往往伴随着 CRC 错误、FCS 错误、碰撞 等物理层指标异常。

我曾经踩过的坑: 有一次机房搬迁后,某台服务器的 UDP 丢包率一直在 0.5% 左右,怎么调都没用。最后发现是网线水晶头没压好,接触不良。换了根网线,问题立刻消失。所以,别一上来就调参数,先看看物理层。

硬件故障的排查手段:

  • ethtool -S eth0:看 rx_crc_errors、rx_frame_errors、rx_fifo_errors 等计数器。
  • ifconfig:看 RX errors、TX errors、collisions。
  • Wireshark:看 Expert Info 里的 "Bad checksum" 或 "Frame check sequence" 错误。
  • 物理检查:网线是否松动、光模块是否清洁、交换机端口指示灯是否正常。

最后,我把这五类原因的核心特征和排查方向整理成了一张表,方便你对照:

丢包原因 核心特征 Wireshark 关键证据 系统侧排查命令
网络拥塞 流量周期性下降,RTT 增大 IO Graph 下降、Expert Info 丢包提示 netstat -s、iperf 测试
缓冲区溢出 接收端 errors 增长,Recv-Q 堆积 无明显异常,需结合系统日志 netstat -su、ss -u -a
防火墙规则 ICMP 不可达,特定端口丢包 icmp.type == 3 iptables -L、防火墙日志
MTU 问题 大包丢,小包正常,分片多 ip.flags.mf == 1、ICMP Frag Needed ping -M do、traceroute
硬件故障 稳定丢包,CRC/FCS 错误 Bad checksum、FCS 错误 ethtool -S、ifconfig

好了,这五类原因基本覆盖了 95% 的 UDP 丢包场景。你下次遇到丢包,别慌,按这个框架一步步排查,很快就能定位问题。