Nginx worker_processes 应设为物理CPU核心数,而非逻辑核数;需配合worker_cpu_affinity auto绑定物理核、关闭accept_mutex、启用reuseport,并通过vmstat、mpstat等指标验证调度健康度。

核心思路是控制并发执行单元数量、减少任务切换频次、让每个核专注处理更少但更连续的任务,而不是堆线程或 worker 去“填满”CPU 数字。
Worker 或线程数别超物理核心数
逻辑核(如超线程)不是独立计算单元。在 16 核 32 线程的机器上设 32 个 Nginx worker,等于让两组任务争抢同一套寄存器、L1 缓存和执行单元,结果是频繁换上下文、缓存失效、部分核心过热降频。真实物理核心数可用命令获取:
lscpu | awk '/Core\(s\) per socket:/ {cores=$4} /Socket\(s\):/ {sockets=$2} END {print cores * sockets}'
worker_processes 或线程池大小应直接设为该数值,不乘线程数;Go 服务需同步设置 GOMAXPROCS 与容器 CPU limit 对齐。
绑定 CPU 核心,避免跨核调度抖动
启用 worker_cpu_affinity auto(Nginx ≥1.9.10),系统会自动将每个 worker 绑定到独立物理核,跳过逻辑核干扰。Linux 下也可用 taskset 手动绑定关键进程,防止内核调度器把同一个 worker 在不同核间来回迁移——这会清空各级缓存,每次切换都得重新预热。
Java 应用可配合 -XX:+UseThreadPriorities 和 -XX:ThreadPriorityPolicy=1 辅助调度,但根本仍是控制线程总数 ≤ 物理核 × 2,并通过压测确认拐点(例如 8 核机器从 12 开始试)。
绕过用户态锁竞争,卸载连接分发压力
旧版 Nginx 若开启 accept_mutex on,多个 worker 会争一把全局锁来调用 accept(),高并发下大量时间片耗在排队等锁上,而非处理请求。解决方案很明确:
- Nginx ≥1.11.3:默认关闭,无需操作
- 更低版本:events 块中显式写 accept_mutex off
- 同时启用 reuseport on,让内核在 socket 层就哈希分发新连接,彻底消除用户态锁和唤醒竞争
盯紧指标,别被 CPU 使用率骗了
CPU 利用率 100% 不代表高效,可能是“忙于切换、无暇干活”。真正要关注的是调度健康度:
- vmstat 1 看 cs 列:持续 > 10000 是明显过载信号
- mpstat -P ALL 1 看各核 %usr/%sys 是否严重不均——某核飙高而其他核闲置,说明负载没打散或存在锁瓶颈
- pidstat -w -p [pid] 1 定位具体进程的每秒自愿/非自愿切换次数(cswch/s vs nvcswch/s)
不复杂但容易忽略


















