4. 丢包原因分析:网络拥塞、缓冲区溢出、防火墙规则、MTU问题、硬件故障
UDP 丢包了,别急着骂运营商。说实话,大部分丢包都不是玄学,而是有迹可循的。我做了这么多年网络排障,总结下来,原因基本就这五类:网络拥塞、缓冲区溢出、防火墙规则、MTU 问题、硬件故障。
咱们一个一个来拆解。你拿着 Wireshark 抓包,心里得有个谱——到底该看哪里?
核心观点: 丢包原因不是猜出来的,是用证据链锁定的。Wireshark 就是你的证据收集器。
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,结果还是丢。这三个参数要一起调。
排查方法:
- 在接收端执行
netstat -su | grep "receive errors",看 errors 是否增长。 - 用
ss -u -a查看当前 socket 的接收队列(Recv-Q)。 - 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 问题的排查步骤:
- 用
ping -M do -s 1472 [目标IP](Linux)测试路径 MTU。 - 在 Wireshark 里看 ICMP 不可达报文,确认是哪一跳设备返回的。
- 检查中间设备(路由器、VPN、隧道)的 MTU 配置。
- 应用层做 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 丢包场景。你下次遇到丢包,别慌,按这个框架一步步排查,很快就能定位问题。