为什么你调了 Linux 网络 sysctl 还是卡?一张数据通路全景实操地图
【免费下载链接】linux-network-performance-parametersLearn where some of the network sysctl variables fit into the Linux/Kernel network flow. Translations: 🇷🇺项目地址: https://gitcode.com/gh_mirrors/li/linux-network-performance-parameters
凌晨三点告警群炸了:CPU 才 30%,磁盘也闲着,P99 延迟却翻了倍。登机器一看ethtool -S eth0,rx_missed_errors整晚都在悄悄涨——包在网卡门口就被丢了,应用只是在干等。
这正是开源项目 linux-network-performance-parameters 要解决的问题:把大家最爱引用的 sysctl 变量,钉在 Linux 内核真实的报文通路上,让每次调参都知道自己在改哪个环节。我们先看项目里那张 TCP 入站路径图,把每个参数的坐标找出来。
📡 网卡门口丢包:ethtool rx 环形缓冲与中断合并
症状是突发流量时吞吐掉线,ethtool -S eth0里rx_missed_errors或rx_dropped持续增长,但网卡链路本身是好的。原因通常只有两处:rx ring 太浅接不住突发;或者中断合并窗口太小,CPU 被硬中断淹没,内核来不及把报文取走。
网卡把报文 DMA 进 rx ring,攒够rx-usecs超时或足够帧数才敲一次硬中断,之后由 NAPI 轮询把 ring 里的报文批量取走——所以这两类参数,一类管"门"多深,一类管"敲门"多勤。
# 查:环形缓冲深度与中断合并参数,先看现状再动手 ethtool -g eth0 ethtool -c eth0看到基线之后再改:
# 改:rx ring 4096 吸收突发,rx-usecs 64 降低硬中断频率,代价是少量延迟 ethtool -G eth0 rx 4096 ethtool -C eth0 rx-usecs 64ring 本身就是排队延迟的来源,"越大越好"是陷阱。延迟敏感业务从 1024~2048 起步往往更合适。
效果预期:rx_missed_errors停止增长,10Gbps 线速负载下的丢包率从 ~1% 量级压到 0.1% 以下。
📥 backlog 与 qdisc:netdev_max_backlog 丢包发生在哪一层
网卡不丢包,但cat /proc/net/softnet_stat第二列(per-CPU dropped)在涨,说明包卡在内核的入站 backlog 队列里:netdev_max_backlog限定队列深度,netdev_budget和netdev_budget_usecs限定 NAPI 每轮轮询能处理多少报文、跑多久。
队列太浅,或者轮询预算太小,包在还没走到协议栈时就被丢掉。softnet_stat 第三列是"预算耗尽"计数,它增长说明内核一直在加班没干完活。
# 查:softnet_stat 第二列是 backlog 丢包数,第三列是预算耗尽次数 cat /proc/net/softnet_stat第二列非零时,先加深队列,再谈预算:
# 改:backlog 抬高吸收内核处理滞后,budget 3000 让 NAPI 单轮多干活 sysctl -w net.core.netdev_max_backlog=16384 sysctl -w net.core.netdev_budget=3000netdev_max_backlog 是按 CPU 算的,多队列网卡总容量要乘 CPU 数,别看到小丢包就飙到 100000。
效果预期:峰值时段dropped归零,因重传造成的 P99 尾延迟从几百 ms 量级回到几十 ms。
📦 应用读得慢:tcp_rmem 与 tcp_wmem 缓冲区调优
高带宽高 RTT 链路上吞吐远低于线速,iperf3单连接卡在 2~3Gbps:典型原因是 TCP 缓冲的默认 max 值装不下带宽时延积(BDP)。10Gbps × 20ms RTT 需要约 25MB 的窗口,而默认tcp_rmem/tcp_wmem的 max 通常只有几 MB,TCP 只能小窗口慢慢爬。
动缓冲区之前我们先把 BDP 算出来;cat /proc/net/sockstat的 TRH 列是内存压力下 socket 内存占用,它随负载上涨说明内存已经被挤压。
# 查:收发缓冲 min/default/max 当前值与 socket 内存占用 sysctl net.ipv4.tcp_rmem net.ipv4.tcp_wmem cat /proc/net/sockstat算好 BDP 后抬高 default 和 max,min 保持小(min 是内存吃紧时的保底值,抬高它反而扩大压力面):
# 改:max 提到 64M 覆盖 BDP,min 保持 4096 防止内存压力放大 sysctl -w net.ipv4.tcp_rmem="4096 131072 67108864" sysctl -w net.ipv4.tcp_wmem="4096 262144 67108864"default 值改完对存量连接不生效,不重启业务进程会以为调优无效。
效果预期:10G × 20ms RTT 的跨域链路单连接吞吐从 ~2Gbps 量级提到 9Gbps 以上,大文件传输的卡顿时间肉眼可见缩短。
✅ 验证与回归:iperf3 加 softnet_stat 确认调参生效
判断调优有没有用,只认同一负载跑前后的对比,不认"感觉变快了"。验证分两步:计数器干净,吞吐达标。
# 验证:同负载跑 60 秒,看吞吐与两类丢包计数器 iperf3 -c <server-ip> -t 60 -P 4 cat /proc/net/softnet_stat ethtool -S eth0 | grep -Ei "drop|miss|over" | grep -v ": 0"如果验证不通过(基准吞吐低于调优前,或丢包计数器重新增长),先回滚影响面最大的 TCP 缓冲这一步:
# 回滚:TCP 缓冲恢复内核默认值(验证掉基准时先执行这一步) sysctl -w net.ipv4.tcp_rmem="4096 87380 6291456" sysctl -w net.ipv4.tcp_wmem="4096 65536 4194304"ring 和中断合并参数仍不稳定的话,再用ethtool -G/ethtool -C逐个还原,每次回滚后观察 10 分钟。确认通过的参数统一写进/etc/sysctl.d/99-net.conf,用sysctl --system加载,避免重启失效。
📋 一页纸清单:网络 sysctl 参数推荐值
| 参数 / 命令 | 推荐值 | 什么时候改 | 验证信号 |
|---|---|---|---|
ethtool -G eth0 rx | 1024~4096 | rx_missed_errors增长 | missed 停涨 |
ethtool -C eth0 rx-usecs | 32~128 | top 里 %soft 高、硬中断过频 | 软中断 CPU 下降且 P99 不变 |
net.core.netdev_max_backlog | 16384(按 CPU 计) | softnet_stat 第二列增长 | dropped 归零 |
net.core.netdev_budget | 3000 | softnet_stat 第三列增长 | squeezed 归零 |
net.ipv4.tcp_rmem/tcp_wmem | 4096 131072 67108864 | 单连接吞吐远低于 BDP | iperf3 接近线速 |
持久化/etc/sysctl.d/99-net.conf | 全部已验证参数 | -w验证通过后 | 重启后参数仍在 |
把上表 6 项落进 sysctl 配置和 ethtool 脚本,跑一轮 60 秒 iperf3 基准,基准变好再动下一批参数——上一个没验证过,就不要碰下一个。
【免费下载链接】linux-network-performance-parametersLearn where some of the network sysctl variables fit into the Linux/Kernel network flow. Translations: 🇷🇺项目地址: https://gitcode.com/gh_mirrors/li/linux-network-performance-parameters
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考