解决高频syslog UDP丢包需协同调优接收路径:定位网卡DMA、内核队列、应用读取三层瓶颈,调大rmem_max并强制rsyslog显式设置SockBufSize,辅以RPS、netdev_max_backlog或改用TCP syslog,并限制udp_mem防内存滥用。

要解决高频 syslog 突发流量导致的 UDP 接收丢包问题,核心不是单纯“拉高 rmem_max”,而是让 内核接收路径全程不卡在缓冲区瓶颈上——从网卡 DMA 层、协议栈队列到应用读取环节必须协同调优。
先定位丢包真正在哪一层
高频 syslog(尤其是小包、多源并发)丢包常被误判为“UDP 不可靠”,实际多发生在接收路径中间环节:
-
网卡环形缓冲区溢出:用
ethtool -S eth0 | grep -E "(missed|no_buffer|fifo)"查rx_missed_errors或rx_no_buffer_count。非零说明网卡已收到但驱动来不及取走,DMA 缓冲区满; -
内核套接字队列溢出:运行
netstat -s | grep -A3 "Udp:",重点看UdpOverflows。持续增长 = 应用(rsyslogd / syslog-ng)读得太慢,或rmem_max设得太小; -
应用层未及时 recv:用
ss -nump | grep :514(假设 syslog 走 UDP 514),观察skmem:(r=...,rb=...)中r(已用)是否长期逼近rb(上限)。若接近且UdpOverflows同步上升,就是缓冲区+应用处理双重瓶颈。
rmem_max 必须配合应用层显式设置才生效
net.core.rmem_max 是系统级硬上限,但它本身不给任何 socket 自动分配大缓冲区。syslog 守护进程(如 rsyslogd)默认使用内核 rmem_default(通常仅 212KB),远不够应对突发小包洪流。
- 临时提升上限:
sudo sysctl -w net.core.rmem_max=8388608(8MB); - 同步提高默认值(影响未显式 setsockopt 的新连接):
sudo sysctl -w net.core.rmem_default=4194304(4MB); - 关键一步:修改 rsyslog 配置,强制其 socket 使用大缓冲区。例如在
/etc/rsyslog.conf中添加:
module(load="imudp" ruleset="remote" Threads="4" TimeRequery="200" SockBufSize="4194304");
或对 syslog-ng,在source s_network中加so-rcvbuf(4194304); - 验证:重启 rsyslog 后执行
ss -nump | grep :514,确认rb值已升至 4MB+。
绕过内核 UDP 队列瓶颈的替代方案
即使调大 rmem_max 和应用缓冲区,单个 UDP socket 在极端突发下仍可能因锁竞争或处理延迟丢包。更稳健的做法是分流压力:
- 启用
net.core.netdev_max_backlog(如设为50000),增大网卡中断后暂存数据包的软队列; - 开启 RPS(Receive Packet Steering):用
echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus把中断负载分摊到多个 CPU 核; - 考虑改用 TCP syslog:虽然开销略增,但 TCP 流控天然适配突发,且现代 rsyslog 支持 TCP 多路复用和自动重传,实测在万级 EPS 场景下丢包率反低于 UDP。
配套调优避免副作用
盲目堆大 rmem_max 可能引发内存压力或干扰其他服务:
- 限制 UDP 全局内存:设
net.ipv4.udp_mem="131072 262144 524288"(单位为页,即 512MB),防止 UDP 占尽内存; - 关闭无意义的校验(仅限可信内网):
net.ipv4.udp_l3mdev_accept=1+ 网卡启用rx offload,降低协议栈开销; - 持久化配置写入
/etc/sysctl.d/99-syslog-tune.conf,再sudo sysctl -p生效,避免重启失效。

















