网卡丢包与 ring buffer 溢出
发布时间:2026-06-18 11:17       
更新时间:2026-06-18 17:00
流量一冲高峰就开始丢包,ping 又查不出链路问题,这时该看看内核的收包缓冲区是否溢出。这类丢包的特征很明显:只发生在流量尖峰,闲时完全正常。
原理一句话:网卡收到数据包先放进 ring buffer(环形缓冲区)排队,等内核取走处理;流量突发时内核来不及收,缓冲区写满,新到的包直接丢弃。溢出的包根本没进内核,抓包看不见它们,这个盲区要靠计数器补。备份窗口、爬虫、大文件分发的机器最容易中招。
一、确认丢包位置
ip -s link show eth0 看 RX errors 和 dropped;再 ethtool -S eth0 | grep -iE 'drop|miss|fifo',如果 rx_no_buffer、rx_missed 这类计数在持续增长,基本可以定性为缓冲区溢出。计数器是累计值,看两次采样的差值才有意义。把丢包数和流量曲线放进同一张图,尖峰对齐才能坐实因果。凌晨备份窗口的丢包最容易被漏看,采样要覆盖这些时段。
二、调大缓冲区
ethtool -g eth0 列出当前值与硬件上限;ethtool -G eth0 rx 4096 tx 4096 调大,数值不能超过 Pre-set maximums,不同网卡上限不同,2K、4K、8K 都常见,照上限取值即可。副作用是单包延迟略增,绝大多数业务无感。调整前后各跑一轮同样的压测,对比才有说服力。注意该设置重启失效,写进 /etc/rc.local 或网络启动脚本固化。
三、配合内核参数
sysctl -w net.core.netdev_max_backlog=16384 与 net.core.netdev_budget=600 适当调大,缓解软中断处理压力;多队列网卡确认中断分散在多个核上,cat /proc/interrupts 一眼可见,手工绑核或 irqbalance 服务都行,中断分散才算调到位。UDP 大流量场景还需要调大 net.core.rmem_max。
四、驱动与其他可能
老版本驱动在高流量下丢包的案例不少,云平台或硬件厂商提供新驱动时可以升级对比;虚拟化环境的网卡驱动与平台相关,升级前先查平台文档。缓冲计数不涨但照样丢包,就要回头看 CPU 软中断是否单核打满。排查按顺序来:先计数器,再缓冲,后参数,跳步容易白忙。
验证方式:重放一次高峰流量,溢出计数不再增长即为生效。