盲目为128核服务器配置128组worker_cpu_affinity掩码会因调度干扰、缓存抖动和NUMA跨节点访问开销导致吞吐下降;必须基于真实物理拓扑(非逻辑核数)、跳过超线程、避开NUMA边界、预留系统核心,并同步调整中断亲和性与reuseport,否则性能不升反降。

128 核服务器上盲目设 worker_cpu_affinity 为 128 组掩码,大概率会让吞吐不升反降——不是核越多越快,而是调度干扰、缓存抖动、NUMA 跨节点访问开销会吃掉所有理论增益。真正有效的深度绑定,必须跳过超线程逻辑核、避开 NUMA 节点边界、预留核心给中断和系统服务,并配合 reuseport 和中断亲和性调整,否则只是把性能瓶颈从“调度混乱”换成“内存带宽打满”或“软中断卡死”。
确认真实物理拓扑,别被逻辑核数骗了
128 个“CPU(s)”不等于 128 个可用物理核心。先跑命令看清楚硬件本质:
lscpu | grep -E "(Socket|Core|Thread|NUMA)"
典型陷阱:某 128 逻辑核机器其实是 2 路 CPU × 32 物理核 × 2 超线程 → 实际只有 64 个物理核;若再叠加 NUMA(如 4 个 node),跨 node 内存访问延迟可能翻倍。此时硬配 128 组 worker_cpu_affinity 掩码,Nginx 启动直接报错 invalid CPU affinity mask,或静默失败后所有 worker 挤在前几个核上。
正确做法:
- 用
nproc --all得到逻辑核总数,但只取物理核数作为worker_processes上限(lscpu | awk '/^Core\(s\) per socket:/ {cores=$NF} /^Socket\(s\):/ {sockets=$NF} END {print cores * sockets}') - 查 NUMA 分布:
numactl --hardware,记录每个 node 的 CPU 列表(如 node0: 0-31, node1: 32-63) - 若启用了超线程(
lscpu | grep "Thread(s) per core"输出为 2),掩码中每组二进制位必须跳过相邻位(如绑物理核 0,就用0001,而不是0011)
写对掩码:128 核 ≠ 128 个 1-bit 掩码
worker_cpu_affinity 每组掩码对应一个 worker 进程,位数必须严格等于系统总逻辑 CPU 数。128 核服务器需要 128 位二进制掩码——但手写 128 位字符串既易错又不可维护。
更可靠的做法:
- 优先用
worker_cpu_affinity auto;(Nginx 1.9.10+),它会自动按物理核顺序分配,跳过超线程对称逻辑核 - 若需精细控制(如只用 node0 的 32 个物理核),用
worker_cpu_affinity auto 00000000000000000000000000000000ffffffffffffffffffffffffffffffff;(前 32 位 0,后 96 位 1 表示允许范围) - 绝对不要写类似
worker_cpu_affinity 1 1 1 ...(128 个 1)——这会让所有 worker 争抢同一个核 - 验证掩码长度:
printf "%0128d\n" 1 | wc -c应输出 129(含换行),确保你写的每组掩码确实是 128 位
绑定只是起点,中断和软中断必须同步对齐
即使每个 Nginx worker 都稳坐指定核心,网卡收包的软中断(softirq)若跑在其他核上,数据要跨核搬运,L3 缓存失效、内存带宽暴涨,吞吐立刻腰斩。
必须做三件事:
- 查网卡中断号:
cat /proc/interrupts | grep eth0(找rx行对应的 IRQ 编号) - 绑定该 IRQ 到与 Nginx worker 相同的 NUMA node 内核心:
echo <code>0-31> /proc/irq/XX/smp_affinity_list(XX替换为实际 IRQ 号) - 启用
reuseport消除 accept 锁竞争:listen 443 ssl reuseport;,否则 128 个 worker 仍要排队抢新连接
漏掉任意一项,压测时 pidstat -t -p $(pgrep nginx) 1 会显示大量 worker 在 PSR 列频繁跳变,perf top 则暴露出大量 __softirqentry_text_start 占用 CPU。
验证不是“有绑定”,而是“绑定生效且稳定”
重载 Nginx 后不能只看配置文件有没有报错。必须逐层验证:
- 查 worker 进程 PID 和当前运行核:
ps -eo pid,args,psr | grep 'nginx: worker'—— PSR 列必须是稳定数字,且分布覆盖你期望的核范围 - 查某 PID 的实际亲和掩码:
taskset -cp <code>PID—— 输出应为类似pid <code>PID's current affinity list: 0,而非0-127 - 查底层内核允许列表:
grep Cpus_allowed_list /proc/<code>PID/status —— 值应为单个数字(如0)或紧凑范围(如0-1),绝不能是全集 - 压力下观察:
htop→ F2 → Columns → 添加PROCESSOR列,持续 5 分钟,确认无 worker 迁移
最容易被忽略的是:即使绑定成功,若未调高 worker_rlimit_nofile 和系统级 fs.file-max,高并发时连接会堆积在少数 worker 上,表现为部分核 100%、其余核空闲——这不是绑定失败,而是资源瓶颈转移了。


















