NUMA架构下Nginx调优需绑定worker进程至本地CPU与内存:先用lscpu、numactl --hardware等确认拓扑,worker_processes设为单节点物理核数(非auto或总数),worker_cpu_affinity分段配置,并用numactl --cpunodebind --membind启动,确保numastat中本地内存占比>95%、numa_foreign≈0。

在多路 CPU 服务器上,worker_processes 不是简单设为总核数或 auto 就能发挥性能——NUMA 架构下,错配会直接导致内存访问延迟翻倍、QPS 腰斩。
看清 NUMA 拓扑是调优前提
别凭“双路 32 核”这种说法配置。必须实测确认物理布局:
- lscpu | grep -E "(Socket|Core|NUMA)" → 查清插槽数(Sockets)、每槽物理核数、NUMA 节点总数
- numactl --hardware → 看每个 node 的 CPU 编号范围和本地内存容量(例如 node 0:CPUs 0–15,64GB)
- cat /sys/devices/system/node/node*/cpulist → 精确到每个核心归属,避免掩码错位
若 BIOS 中启用了 Node Interleaving,numactl 会显示单个大节点——这等于关闭了 NUMA 局部性,必须进 BIOS 关掉。
worker_processes 必须匹配单节点物理核数
设为 auto 是常见错误:它只读 /proc/cpuinfo 总逻辑核数,完全不感知 NUMA 边界。实测中一半 worker 会被调度到远端 node,numa_foreign 指标飙升。
- 双路服务器,每路 16 物理核 → 推荐设 worker_processes 16(而非 32 或 64)
- 更稳妥可设为 8~12,留出资源给系统中断、日志、监控等后台任务
- 绝对不要设为总物理核数(如 32)或超线程总数(如 64),后者会加剧 L3 缓存争抢
CPU 与内存绑定必须同步生效
仅靠 worker_cpu_affinity 绑定 CPU 不够。Nginx 自身无法控制 malloc 分配的内存落在哪个 node,必须从进程启动层强制亲和。
- worker_cpu_affinity 要按节点分段写:比如 node 0 有 CPU 0–15,则用 16 组 16 位掩码(对应 16 个 worker)
- 必须用 numactl 启动主进程:
/usr/bin/numactl --cpunodebind=0 --membind=0 /usr/sbin/nginx -g 'daemon on; master_process on;' - 若需双节点部署,可用
--cpunodebind=0,1 --membind=0,1,但更推荐单节点部署 + 外部负载分发,避免跨节点共享内存区
验证是否真正落地
不能只看 ps -eo pid,psr,comm | grep nginx 输出的 CPU ID——那只是当前调度快照。
- 运行 numastat -p $(pgrep nginx),重点看 local_node 占比是否 >95%,numa_foreign 是否接近 0
- 配合 pidstat -w -p $(pgrep nginx) 观察上下文切换是否平稳,perf top -p $(pgrep nginx) 看热点是否集中在预期指令路径
- 检查 cat /proc/$(pgrep nginx)/status | grep -E "(Cpus_allowed|MMU)",确认 Cpus_allowed_mask 与 membind 设置一致


















