worker_cpu_affinity单独使用无法优化numa跨节点内存访问,因其仅绑定cpu而不控制内存分配;必须配合numactl启动master进程实现cpu与内存双亲和。

单独配置 worker_cpu_affinity 无法优化跨节点内存访问性能,它只绑定 CPU,不控制内存分配。真正起作用的是让 worker 进程既运行在本地 CPU 上,又只从对应 NUMA 节点分配内存——这必须靠 numactl 启动主进程来实现。
为什么 worker_cpu_affinity 单独用在 NUMA 服务器上会失效
Linux 内核的 sched_setaffinity() 系统调用只设置 CPU 亲和性,完全不干预内存页分配策略。Nginx worker 进程继承 master 进程的内存策略;如果 master 没被限制内存域,哪怕你把 worker 绑定在 Node 0 的核心上,它仍可能从 Node 1 分配内存页。此时 numastat -p <pid></pid> 会显示 numa_miss 持续升高,Mems_allowed 返回类似 00000003(表示两个节点都允许),实际延迟翻倍。
必须配合 numactl 控制内存亲和
Nginx 自身不支持 numa_bind 或 numa_interleave 等内存策略,所有子进程(包括 worker)继承 master 的 NUMA 行为。因此关键动作是:
- 用
numactl --cpunodebind=0 --membind=0 /usr/sbin/nginx -g "daemon off;"启动 master - 确保
worker_processes设为单个 NUMA 节点的逻辑核数(例如 Node 0 有 16 核,就设worker_processes 16) - 对应配置
worker_cpu_affinity掩码,仅覆盖该节点内 CPU 编号(如 Node 0 对应 CPU 0–15,则掩码共 16 组,每组 16 位,第 i 组第 i 位为 1)
双路或多路服务器的分组启动建议
不要用一个 numactl 命令启动全部 worker。更合理的方式是分节点部署:
- Node 0:用
numactl --cpunodebind=0 --membind=0启动一组 Nginx(含 8–12 个 worker) - Node 1:用
numactl --cpunodebind=1 --membind=1启动另一组(同样 8–12 个) - 两组监听不同端口或通过 upstream 做负载分发
- systemd 下可在
/etc/systemd/system/nginx.service.d/override.conf中重写ExecStart实现
验证是否生效的关键命令
配置完成后,不能只看 CPU 是否绑定,必须交叉验证内存行为:
-
taskset -cp <worker_pid></worker_pid>:确认 CPU 绑定正确 -
cat /proc/<pid>/status | grep Mems_allowed</pid>:返回值应为单节点掩码(如00000001表示仅 Node 0) -
numastat -p <pid></pid>:观察numa_hit应 ≥ 95%,numa_miss接近 0 -
perf record -e mem-loads,mem-stores -p <pid></pid>:检查远程内存访问事件是否显著下降










