不对。在NUMA架构服务器上,worker_processes应设为单个NUMA节点的逻辑核数(如每节点32核则设32),并配合worker_cpu_affinity按节点分组绑定CPU、numactl强制内存亲和,再通过numastat验证本地内存分配率超95%。

worker_processes 设为 CPU 总核数就对了吗?
不对。在双路或四路 NUMA 架构服务器上,worker_processes 直接设成 auto 或总逻辑核数(比如 128),往往导致跨 NUMA 节点内存访问激增,反而压低吞吐。Nginx 的每个 worker 进程默认不绑定 CPU,OS 调度器可能把它从 node0 迁移到 node1,而该进程的共享内存(如 shared memory zone)和缓存数据却还在 node0 的本地内存里。
实操建议:
- 先用
numactl --hardware确认 NUMA 节点数和各节点 CPU/内存分布 -
worker_processes建议设为单个 NUMA 节点的逻辑核数(例如每节点 32 核 → 设为32),而非总核数 - 配合
worker_cpu_affinity显式绑定——比如双路 64 核(node0: 0–31, node1: 32–63),则写成:worker_cpu_affinity 00000000000000000000000000000001 00000000000000000000000000000010;
- 若使用
auto,Nginx 仅按总核数 fork 进程,不做 NUMA 感知,必须手动干预
为什么 worker_cpu_affinity 的掩码要按 NUMA 节点分组?
因为 Linux 的 sched_setaffinity() 系统调用只管 CPU ID,不管 NUMA 拓扑;但 Nginx 启动时若把多个 worker 绑定到同一 NUMA 节点的不同核上,它们能共用该节点的 L3 缓存和本地内存带宽,避免跨节点 QPI/UPI 链路争抢。
常见错误现象:
- 掩码写成连续长串(如
1111111100000000),结果前 8 个 worker 全挤在 node0 的前 8 核,后 8 个没绑、飘在 node1 —— 负载不均 + 跨节点访问 - 用
auto配合worker_cpu_affinity auto(Nginx ≥ 1.19.10),它只做“轮询绑定”,仍不感知 NUMA 边界,可能把 worker0 绑 core0(node0),worker1 绑 core64(node1),但二者共享的ssl_session_cachezone 在 node0 内存,worker1 访问延迟翻倍 - 忘记检查 BIOS 中是否启用
Node Interleaving = Disabled—— 若开启,numactl --hardware看不出节点隔离,实际内存已交错,亲和性失效
如何验证 NUMA 亲和性真正生效?
不能只看 ps -eo pid,psr,comm | grep nginx 是否显示固定 CPU ID;关键要看内存访问是否落在本地节点。
实操步骤:
- 用
pidof nginx | xargs -I{} taskset -cp {}确认每个 worker 进程绑定的 CPU 列表 - 对任一 worker PID,执行:
numastat -p {}查看numa_hit/numa_miss比值,理想情况numa_miss应趋近于 0 - 压力测试中,用
perf stat -e 'mem-loads,mem-stores,mem-loads-misses,mem-stores-misses' -p {}观察跨节点访存比例(需内核支持mem-loadsevent) - 若
numastat显示某 worker 的numa_foreign高,说明其分配的内存页被映射到了其他节点——可能是启动时未用numactl --membind启动 Nginx,或系统启用了zone_reclaim_mode
除了 affinity,还有哪些 NUMA 相关配置容易被忽略?
很多调优文档只提 worker_cpu_affinity,但 NUMA 效果是端到端的:从进程启动、内存分配、到共享内存区创建,都得对齐节点。
关键补充项:
- 启动 Nginx 前,用
numactl --cpunodebind=0 --membind=0 /usr/sbin/nginx强制主进程及其 fork 出的 worker 全部约束在 node0(或按需指定) - 所有
shared memory zone(如limit_req_zone、ssl_session_cache)必须在http块中定义,不能放在server块里——否则每个 server 可能触发独立 zone 分配,跨节点不可控 - 确认内核参数:
vm.zone_reclaim_mode = 0(默认为 0,但某些云厂商镜像会改),否则当本地内存不足时,内核会主动回收本地 page,反而加剧跨节点分配 - 若使用
reuseport on,注意它依赖内核 SO_REUSEPORT 实现,Linux ≥ 5.0 才对 NUMA 友好;旧内核下多个 socket 可能被 hash 到不同节点的 worker,破坏亲和性
NUMA 调优不是设几个参数就完事——进程、内存、内核、硬件四层必须对齐,漏掉任意一层,性能就卡在非线性区。最常被跳过的其实是 numactl 启动和 vm.zone_reclaim_mode 检查,这两步不做,前面所有 affinity 都可能白配。



















