必须用numactl启动Nginx主进程以实现CPU与内存双重本地性,仅靠worker_cpu_affinity无法避免跨NUMA节点内存访问导致的性能下降。

在多路 NUMA 服务器上,仅靠 worker_cpu_affinity 无法真正提升 Nginx 性能——它只绑 CPU,不控内存。跨 NUMA 节点访问内存会导致延迟翻倍,numastat -p 显示 numa_miss 持续升高,QPS 卡在瓶颈。必须用 numactl 启动主进程,让 worker 继承 CPU + 内存双重本地性策略。
为什么 worker_cpu_affinity 单独配置会失效
它只是告诉内核“这个 worker 可以在哪几个 CPU 上跑”,但内存页仍可能从任意允许的 NUMA 节点分配。哪怕你用 0001 0010 0100 1000 把前 4 个 worker 全绑在 Node 0 的物理核上,只要主进程没限制内存域,这些 worker 依然会从 Node 1 分配内存。验证方式:
- cat /proc/<pid>/status | grep Mems_allowed</pid> 返回 00000003(两个节点都开)→ 说明未生效
- taskset -cp <pid></pid> 显示绑定成功,但 perf record -e mem-loads,mem-stores 仍有大量远程访存事件
正确启动方式:numactl 必须作用于 master 进程
Nginx worker 进程继承 master 的 NUMA 策略,所以控制点只有一个:master 启动时加 numactl。Nginx 自身不支持 numa_bind 或 numa_interleave 配置项。
- 双路服务器(Node 0 和 Node 1),推荐分两组部署:
- Node 0 组:
numactl --cpunodebind=0 --membind=0 /usr/sbin/nginx -g "daemon off;" - Node 1 组:
numactl --cpunodebind=1 --membind=1 /usr/sbin/nginx -g "daemon off;" - systemd 用户,在
/etc/systemd/system/nginx.service.d/override.conf中重写ExecStart,避免被默认服务覆盖
worker_processes 数量必须与 NUMA 节点对齐
设成 auto 或总逻辑核数(如 32)是常见误区。真实有效的是按节点均分:
- Node 0 有 16 核 + 64GB 内存 → 建议
worker_processes 8–12(留出 2–4 核给中断、I/O、监控等) - Node 1 同理 → 总数建议设为 16,而非 32
- 若用
worker_cpu_affinity auto,仍需配合numactl;否则 auto 只在全系统范围内调度,完全无视 NUMA 边界
CPU 掩码顺序必须严格匹配内核编号
worker_cpu_affinity 0001 0010 0100 1000 中的每一位,对应 lscpu 或 cat /proc/cpuinfo 输出的 CPU 编号顺序。该顺序由物理插槽位置决定,不是简单按 0~N 排列。错误配置会导致 worker 实际绑定到远端节点核心,性能反而下降。
- 先运行
numactl --hardware查清节点拓扑 - 再用
lscpu | grep "CPU\(s\)"和lscpu | grep "NUMA node"确认每个节点包含哪些 CPU ID - 例如 Node 0 包含 CPU 0–15,则
worker_cpu_affinity的前 16 位应覆盖这组核心,掩码长度与 worker 数一致



















