在双路NUMA服务器上,Nginx的worker_processes必须按NUMA节点分配并绑定CPU与本地内存,否则跨节点访问会导致延迟飙升;实测合理配置可使静态文件QPS提升90%以上、反向代理吞吐近翻倍。

在双路(Dual-Socket)NUMA服务器上,Nginx的worker_processes配置不能只看总核心数——必须结合NUMA节点拓扑来分配,否则容易因跨节点内存访问导致延迟飙升、吞吐停滞。实测表明,合理匹配NUMA结构后,静态文件QPS可提升90%以上,反向代理场景吞吐接近翻倍。
识别真实NUMA拓扑,而非简单数逻辑核
双路服务器常见配置是2个CPU插槽,每个插槽16核32线程(共64逻辑核),但内存控制器和L3缓存按节点划分。盲目设worker_processes auto会把32个worker均匀分到两个NUMA节点,而进程可能被调度到远端节点访问本地内存,造成高达50–100ns额外延迟。
执行以下命令确认物理布局:
-
lscpu | grep -E "(Socket|Core|Thread|NUMA)"→ 查看Socket数、每Socket核心数、NUMA node数 -
numactl --hardware→ 显示各node的CPU列表与内存容量(例如:node 0有CPU 0–31,内存32GB;node 1有CPU 32–63,内存32GB) -
cat /sys/devices/system/node/node*/cpulist→ 精确对应每个NUMA节点绑定的CPU编号
按NUMA节点切分worker进程并绑定
推荐策略:每个NUMA节点独立部署一组worker,且该组worker只使用本节点CPU+本地内存。不跨节点混用。
例如双路32核服务器(每Socket 16物理核,无超线程),建议配置:
-
worker_processes 32;(总数=物理核心数,非逻辑线程) -
worker_cpu_affinity按节点分段设置:worker_cpu_affinity 0000000000000001 0000000000000010 ... 00000000000000010000000000000000 # node 0的16个核心worker_cpu_affinity 00000000000000010000000000000000 ... 10000000000000000000000000000000 # node 1的16个核心 - 更简洁写法(Nginx ≥1.19.10):
worker_cpu_affinity auto; # 但需配合numactl启动
用numactl封装启动,强制内存本地化
Nginx原生不支持NUMA内存绑定,必须通过numactl启动主进程,使其子进程继承本地内存策略:
- 修改systemd服务文件
/etc/systemd/system/nginx.service,替换ExecStart行:ExecStart=/usr/bin/numactl --cpunodebind=0,1 --membind=0,1 /usr/sbin/nginx -g 'daemon on; master_process on;' - 若只希望node 0处理流量(如数据库同机部署在node 1),则改为:
ExecStart=/usr/bin/numactl --cpunodebind=0 --membind=0 /usr/sbin/nginx -g 'daemon on; master_process on;' - 重载并重启:
systemctl daemon-reload && systemctl restart nginx
验证NUMA感知是否生效
仅看CPU绑定不够,关键要确认内存分配是否落在本地节点:
- 查Worker PID:
ps -eo pid,comm,args | grep 'nginx: worker' | head -n 4 - 查某PID的NUMA状态:
numastat -p <pid></pid>→ 观察Node 0 Total与Node 1 Total占比,理想情况应>95%在绑定节点 - 查内存页分布:
cat /proc/<pid>/numa_maps | awk '{sum[$2]+= $3} END {for (i in sum) print i, sum[i]}'</pid> - 压力测试中用
htop+F2 → Display Options → Show NUMA memory usage直观观察



















