Nginx在NUMA服务器上worker_processes必须设为单节点物理核心数(如双路16核/节点则设16),禁用auto;需结合worker_cpu_affinity分组绑定CPU与numactl强制本地内存亲和,否则跨节点访问致延迟翻倍、吞吐下降,实测静态QPS可提升90%以上。

Nginx 在 NUMA 架构服务器上,进程总数(即 worker_processes)不能按总核数设,必须严格按单个 NUMA 节点的物理核心数来定。否则,一半 worker 会跨节点访问内存,延迟翻倍,吞吐反而下降。
确认真实 NUMA 拓扑是前提
先执行三组命令看清硬件布局:
-
lscpu | grep -E "(Socket|Core|NUMA)"→ 查清插槽数、每槽物理核数、NUMA 节点总数 -
numactl --hardware→ 看每个 node 的 CPU 编号范围和本地内存容量(例如 node 0: CPUs 0–15, 64GB) -
cat /sys/devices/system/node/node*/cpulist→ 精确到每个核心归属,避免掩码错位
若 BIOS 中启用了 Node Interleaving,numactl --hardware会显示单个大节点,实际已失去 NUMA 局部性——必须进 BIOS 关闭该选项。
worker_processes 必须等于单节点物理核心数
比如双路 32 核服务器(每路 16 物理核),应设:
-
worker_processes 16(不是 32、64,更不能auto)auto只读/proc/cpuinfo总数,不感知 NUMA 边界,实测易导致一半 worker 跑在远端节点,numa_foreign指标翻倍。
保守起见可设为 8~12,留出资源余量给系统、日志、SSL 握手等后台任务。
CPU 绑定与内存绑定必须同步生效
仅靠 worker_cpu_affinity 不够,Nginx 自身无法控制内存分配位置:
-
worker_cpu_affinity要按节点分段写:双路 16 核/插槽示例:- node 0 的 16 个核心:
worker_cpu_affinity 0000000000000001 0000000000000010 ...(共 16 位掩码) - node 1 的 16 个核心:另起一行,用对应 CPU 编号的掩码
- node 0 的 16 个核心:
- 必须用
numactl启动主进程:修改 systemd 服务文件,ExecStart改为:/usr/bin/numactl --cpunodebind=0 --membind=0 /usr/sbin/nginx -g 'daemon on; master_process on;'
如需双节点负载,可用--cpunodebind=0,1 --membind=0,1,但更推荐单节点部署 + 外部负载分发,避免共享内存区跨节点访问。
验证是否真正落地,只看内存路径
不能只看 ps 或 taskset 输出的 CPU ID。关键指标是内存访问是否落在本地节点:
- 运行
numastat -p $(pgrep nginx) -
local_node应 >95%,foreign应接近 0 - 若
foreign明显偏高,说明有 worker 访问了远端内存,需检查 BIOS 设置、掩码位数、numactl参数是否一致。


















