Nginx worker进程需与网卡RSS队列对齐才能真正受益:先启用多队列并绑定RX中断到指定CPU,再通过worker_cpu_affinity将worker绑定至对应核心,配合accept_mutex off和multi_accept on实现“谁收包、谁处理”,避免跨核数据搬运。

要让 Nginx 的 worker 进程真正受益于网卡多队列(RSS),不能只设 worker_processes auto 就完事。关键在于让每个 worker 处理的网络包,尽可能来自它绑定的 CPU 上运行的 RX 队列——否则中断在 CPU0,worker 却跑在 CPU3,数据就得跨核搬运,缓存失效、延迟飙升。
先确认网卡多队列已就绪
网卡队列是硬件层基础,Nginx 无法驱动它:
- 查当前队列数:
ethtool -l eth0,看 Current hardware settings 中 RX/TX channel 是否 ≥2 - 若不足,启用:sudo ethtool -L eth0 combined 4(建议设为物理 CPU 核数,非逻辑核)
- 验证目录生成:
ls /sys/class/net/eth0/queues/应出现rx-0、rx-1等子目录
把 RX 中断绑定到特定 CPU
每个 rx-N 队列对应一个独立中断号,必须手动绑定,否则全落在 CPU0:
- 查中断映射:
grep "eth0-rx" /proc/interrupts,找到类似45: ... eth0-rx-0 - 按队列轮询绑定(以 4 队列为例):
echo 1 > /proc/irq/45/smp_affinity_list(rx-0 → CPU0)echo 2 > /proc/irq/46/smp_affinity_list(rx-1 → CPU1)echo 4 > /proc/irq/47/smp_affinity_list(rx-2 → CPU2)echo 8 > /proc/irq/48/smp_affinity_list(rx-3 → CPU3) - 避免跨 NUMA 节点:用
lscpu查节点拓扑,优先将同一节点内 CPU 分配给同组队列
让 Nginx worker 与网卡队列对齐
目标是“谁收包,谁处理”,减少跨核数据拷贝:
- 设
worker_processes 4(匹配队列数),并启用亲和:worker_cpu_affinity 0001 0010 0100 1000;(4 核场景,每位对应一个 CPU) - 更推荐自动模式(Nginx ≥ 1.9.10):
worker_processes auto;worker_cpu_affinity auto;
它会感知 NUMA 节点,并将 worker 均匀分到各本地节点的连续核心上 - 验证是否生效:
ps -eo pid,psr,comm | grep nginx,观察各 worker 的 CPU 编号是否与 RX 中断绑定的 CPU 一致
补足软中断与连接调度协同
即使硬中断分散了,软中断(ksoftirqd)和 accept 锁仍可能成为瓶颈:
- 开启 RPS(软件层面再均衡):
for i in /sys/class/net/eth0/queues/rx-*/rps_cpus; do echo f > $i; done(f = 0xf = CPU0–3) - 关闭 accept 锁:
accept_mutex off;(Nginx ≥ 1.11.3 默认已关) - 启用一次多连:
multi_accept on;,降低事件唤醒频次 - 确保
worker_connections × worker_processes ≤ ulimit -n × 0.7,避免文件描述符耗尽










