你的 Nginx worker 进程数,是不是还卡在 auto 上没动过?
你有没有试过:流量一上来,服务器就变卡,top 里 CPU 利用率忽高忽低,Nginx 日志里开始刷 accept() failed (24: Too many open files)?调了 keepalive_timeout、改了 gzip,结果还是治标不治本——可能问题就藏在那行被你忽略的 worker_processes auto; 里。
worker 进程数设置的核心原则是什么?
一句话:别让它比 CPU 核心数多,也别让它比核心数少太多。
Nginx 的每个 worker 进程,同一时间只能在一个 CPU 核心上跑。设少了,核心空转;设多了,系统忙着来回切换进程,反而耽误干活。
worker_processes auto; 是个好起点——它会读取 /proc/cpuinfo,自动设成逻辑核心数。但这个“自动”,只认得 CPU,不认得你服务器上还蹲着 MySQL、PHP-FPM、甚至一个常驻的 Python 后台任务。它们都在抢同一个 CPU 资源。
比如你有 8 核,但 MySQL 经常吃掉 2~3 个核的算力,这时候还让 Nginx 开 8 个 worker,等于硬塞两拨人挤一条窄道,谁也跑不快。
如何根据你的服务器情况做调整?
先别急着改配置,打开终端,敲两行命令摸清底细:
nproc # 看总共有几个逻辑核
ps aux --sort=-%cpu | head -5 # 看现在谁在 CPU 上最活跃
然后问自己一个问题:这台机器是专干 Nginx 的,还是顺带跑数据库、缓存、API 的?
真实案例:一台 8 核的线上服务器,跑着 WordPress(PHP-FPM + MySQL)+ Nginx。一开始 worker_processes 8;,高峰期 htop 里能看到 3 个核心 CPU 接近 100%,剩下 5 个却只有 20% 利用率,请求延迟直接翻倍。
后来改成 worker_processes 6;,再配上 worker_cpu_affinity 00000011 00000101 00001001 ...(把 6 个 worker 绑定到前 6 个核心),MySQL 和 PHP-FPM 自然落到剩下两个核上。上下文切换少了,响应时间稳定了不少,高峰期也不再频繁超时。
是不是进程数越多,性能就一定越好?
不是。这是很多人踩过的坑。
每个 worker 进程本身要占内存,还要参与系统调度。你给一台 4 核机器配 worker_processes 32;,操作系统光是决定“接下来让哪个 worker 上 CPU”就要花掉大量时间,真正处理 HTTP 请求的时间反而被压缩了。
性能提升不是直线上升的。从 1 到 4 个 worker(对应 4 核),效果通常很明显;但从 4 涨到 8,收益可能微乎其微;再涨到 16,说不定连 nginx -t 都开始报 warning,日志里全是 fork() failed。
你要找的不是一个最大值,而是一个“够用、稳当、不打架”的数字。
如何验证你的设置是否合理?
改完别扔那儿不管。打开 Nginx 状态页,看一眼真实负载:
确保 ngx_http_stub_status_module 已启用(主流发行版编译时默认带上),然后在 nginx.conf 的 server 块里加:
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
重载后访问 http://localhost/nginx_status,重点盯住这一行:
Active connections: 291
server accepts handled requests: 123456 123456 789012
Reading: 6 Writing: 3 Waiting: 282
Waiting数长期接近worker_connections,说明连接排队严重;- 但同时
top里 CPU 利用率才 40%,那瓶颈大概率不在 CPU,可能是磁盘 IO 或后端应用拖慢了响应; - 如果
Waiting很低,CPU 却已飙到 90%+,且htop显示某些核心满载、其他核心闲置——那就该调worker_processes了。
高并发场景下,还需要搭配调整哪些参数?
worker_processes 只是半张牌,另一半是 worker_connections。
理论最大并发 = worker_processes × worker_connections,但系统不会无条件配合你。Linux 默认限制每个进程最多打开 1024 个文件描述符(包括 socket 连接),超过就报错 Too many open files。
所以三件事得一起做:
- 查当前限制:
ulimit -n - 查系统总上限:
cat /proc/sys/fs/file-max - 在
nginx.conf里补上:worker_rlimit_nofile 65535; events { worker_connections 65535; }
真实踩坑记录:一个内部管理后台用了长轮询,worker_connections 设到 20000,但忘了改 ulimit。上线当天下午,所有接口开始随机 502,错误日志里全是 open() failed (24: Too many open files)。补上 limits.conf 和 worker_rlimit_nofile,重启后立刻恢复正常。
今天下班前,你能做的具体操作是什么?
别等“下次大版本重构”,现在就打开终端,按顺序走一遍:
- 执行
nproc,记下数字(比如输出是8); - 执行
grep worker_processes /etc/nginx/nginx.conf,看看现在是auto还是某个固定值; - 执行
top,按P按 CPU 排序,观察前 3 名常驻进程(比如mysqld占 40%,php-fpm占 25%); - 心算预留:8 核 − 2 核(给数据库)− 1 核(给 PHP)= 5 → 把
worker_processes改成5; - 执行
grep worker_connections /etc/nginx/nginx.conf和ulimit -n对比,如果后者 ≤ 前者,马上编辑/etc/security/limits.conf,加上:
nginx soft nofile 65535
nginx hard nofile 65535
- 最后,执行
sudo nginx -s reload—— 不用停服务,配置立刻生效。
做完这六步,你就已经甩开 80% 还在用默认配置的同行了。后续要不要开 worker_cpu_affinity、要不要调 epoll 参数,都建立在这个干净、合理的基础上。