必须查运行时状态确认实际启用的RX/TX队列数:ls /sys/class/net/eth0/queues/看rx-/tx-子目录数量,ethtool -l eth0查Current hardware settings值,cat /proc/interrupts | grep eth0 | grep rx统计RX中断行数,三者需一致;Pre-set maximum仅为硬件上限,非当前生效值。

网卡队列数不是“默认就合理”的,必须查、必须验、必须调 —— 不查直接调可能让性能更差。
怎么确认当前网卡实际启用的 RX/TX 队列数
别信文档或驱动默认值,得看运行时状态。最直接的方式是检查 sysfs 队列目录和 ethtool -l 输出是否一致:
-
ls /sys/class/net/eth0/queues/:应看到rx-0、rx-1、tx-0、tx-1等子目录;总数 =rx-N最大编号 + 1 +tx-N最大编号 + 1 -
ethtool -l eth0:关注Current hardware settings行,Rx和Tx后面的数字才是当前生效值;若显示Combined列,则表示启用了合并队列(常见于 virtio 或部分 Intel 驱动) -
cat /proc/interrupts | grep eth0 | grep rx:每行对应一个 RX 队列中断,行数即 RX 队列数;注意有些驱动(如mlx5)会把 TX 中断也混在同名 irq 里,需结合ethtool -S eth0查rx_queue_0_packets类计数器验证是否真有流量
常见坑:ethtool -l eth0 显示 Pre-set maximum 是硬件上限,不代表已启用;KVM 虚拟机中 virtio-net 默认只开 1 队列,即使宿主机开了 8 个也没用。
为什么 ethtool -L 设置后没生效
设置失败通常不是命令写错,而是被内核或驱动拦截了。关键检查点:
- 目标值不能超过网卡硬件支持上限:
ethtool -l eth0中Pre-set maximum值;例如i40e卡最大支持 64,但某些固件版本实际只允许 ≤16 - 不能超过 CPU 核心数(尤其 NUMA 多路系统):设 32 队列但只有 16 个在线 CPU,内核会静默截断为 16;用
nproc --all和lscpu | grep "CPU\(s\)"核对 - 部分驱动要求先关闭接口:
ip link set eth0 down && ethtool -L eth0 combined 8 && ip link set eth0 up;否则返回Operation not supported - 云服务器(如阿里云 ENI、AWS Elastic Network Adapter)可能禁用该接口,
ethtool -L直接报错;此时需改用厂商工具(如aliyun-cli)或确认实例规格是否支持手动调优
IRQ 亲和性绑定不生效的典型原因
写了 echo 2 > /proc/irq/XX/smp_affinity_list 却发现中断还在 CPU 0 上跑?问题往往出在干扰源:
-
irqbalance服务正在运行:它会周期性覆盖你手动写的 affinity;停掉再试:systemctl stop irqbalance,且确认systemctl is-enabled irqbalance返回disabled - 用了十进制值(如
echo 2)但内核期望十六进制位掩码:CPU 1 对应0x2,CPU 0–3 对应0xf;错误写成echo 2实际绑到 CPU 1,但你以为绑的是 CPU 2 - 未触发软中断重调度:绑定 IRQ 后,需强制刷新一次软中断负载分布,执行
echo 1 > /proc/sys/net/core/dev_weight或重启网络子系统(modprobe -r your_driver && modprobe your_driver) - NUMA 节点错配:把 RX 队列绑到远端 NUMA 节点的 CPU,延迟反而升高;用
lscpu看每个 CPU 所属 node,再用cat /sys/class/net/eth0/device/numa_node确认网卡所在 node
RPS/RFS 开启前必须厘清的边界
RPS 是软件模拟多队列,仅在硬件不支持或多队列数不足时补位。但它不是万能的,滥用反而拖慢性能:
- RPS 不能替代硬件 RSS:它在软中断上下文做包分发,增加额外拷贝和调度开销;实测在 10G+ 吞吐下,RPS 启用后 CPU softirq 占用可能反超硬件队列方案
-
rps_sock_flow_entries必须设够:默认 32768 太小,高并发短连接场景易哈希冲突,导致连接乱序;建议 ≥ 连接峰值 × 2,写入/proc/sys/net/core/rps_sock_flow_entries - RFS 需配对启用:只开 RPS 不开 RFS,同一 TCP 流的包可能被轮询打到不同 CPU,cache miss 激增;启用 RFS 需同时设置各
rx-N/rps_flow_cnt(如echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt) - 虚拟化环境慎用:KVM 中 guest 内 RPS 与 host 的 vCPU 调度层叠加,可能引发不可预测的 cache 损耗;优先调
vhost_net的tx_queue_len和rx_queue_len
真正关键的一点:所有队列调优的前提,是确认瓶颈确实在网络栈 —— 先用 perf record -e 'net:*' -a sleep 10 看事件热点,再决定动哪一层。盲目堆队列数,不如先关掉 irqbalance 并绑死 IRQ 看效果。



















