确认UDP丢包真实存在:执行netstat -su查receive buffer errors值,若持续上升(如30秒增超100)即证实内核因接收缓冲区满静默丢包;若命令不存在则用cat /proc/net/snmp | grep Udp查RcvbufErrors是否非零递增。

当UDP服务突然出现大量数据收不到、监控显示业务指标断崖式下跌,且应用日志无异常时,必须立即排查内核是否在静默丢弃UDP数据包。这类丢包不触发错误码、不写入系统日志,仅通过特定统计字段暴露,需逐层定位丢弃发生的位置。
确认UDP丢包是否真实存在
执行 netstat -su,查看输出中 receive buffer errors 字段值。该数值每增长1,代表内核因接收缓冲区满而丢弃1个UDP包。若该值持续上升(例如30秒内增加超100),即确认存在真实UDP丢包。
⚠️ 注意:netstat 已被标记为废弃,若系统提示命令不存在,请改用 cat /proc/net/snmp | grep Udp,检查第二行中 RcvbufErrors 对应的数字是否非零且递增。
定位丢包发生的层级
UDP丢包只可能发生在三个位置:网卡 Ring Buffer → 内核协议栈接收队列 → 应用 Socket 缓冲区。必须按此顺序排查,跳过任一层都会误判。
第一步:检查网卡 Ring Buffer 是否溢出
运行 ethtool -S eth0 | grep -E "(missed|no_buffer|fifo)",重点看 rx_missed_errors。若该值非零,说明网卡硬件侧已开始丢包——此时数据根本未进入内核,后续所有调优都无效,必须先增大 Ring Buffer。
第二步:检查内核接收队列是否溢出
执行 sysctl net.core.rmem_max,若返回值 ≤ 262144(256KB),则极大概率是瓶颈。Linux默认值常为212992,对千兆网卡上每秒万级小包场景完全不够用。
第三步:检查应用是否未及时读取
运行 ss -uln | grep ':端口号'(将“端口号”替换为实际监听端口),观察第七列 rx_queue 值。若该值长期 > 80% 的 net.core.rmem_max,说明应用读取速度跟不上接收速度,缓冲区持续积压直至溢出丢包。
针对性修复操作
方法一:临时扩大内核接收缓冲区上限
执行 sysctl -w net.core.rmem_max=26214400(设为25MB)。这一步立竿见影,但重启后失效。
方法二:永久生效并同步应用层配置
向 /etc/sysctl.conf 追加三行:net.core.rmem_max = 26214400net.core.netdev_max_backlog = 30000net.ipv4.udp_rmem_min = 4096
然后执行 sysctl -p 加载。⚠️ 【必须同时修改应用代码,调用 setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) 显式设置同等大小缓冲区】,否则内核限制虽放宽,应用仍使用默认小缓冲区,丢包照旧。
方法三:增大网卡 Ring Buffer(仅限 rx_missed_errors 非零时)
先查支持上限:ethtool -g eth0;再设新值,例如:ethtool -G eth0 rx 4096。万兆卡通常支持到8192,千兆卡常见上限为4096。该操作无需重启,但部分老旧驱动可能拒绝超出硬件能力的设置。


















