高并发场景下 PHP-FPM 如何配合 Nginx 调整 worker_connections?
核心结论:单独调高 worker_connections 无法解决高并发问题,在 8GB 内存服务器上,若 PHP 进程平均占用 40MB,pm.max_children 安全上限约为 50,需同步调整 worker_rlimit_nofile 至 65535 才能避免"accept() failed (24: Too many open files)"报错。
原因分析
Nginx 处理 PHP 请求需经过三个步骤:接受请求、通过 socket 连接 PHP-FPM 的 FastCGI、返回处理结果。根据木桶效应,这三步中最小的一环决定最终并发能力。很多用户误以为调大 worker_connections 就能提升并发,但实际上系统文件描述符限制(ulimit -n)、PHP-FPM 的 pm.max_children、内核网络参数(net.core.somaxconn)任何一项不足都会成为瓶颈。
典型报错场景:当 worker_connections 设为 4096 但 ulimit -n 仍为 1024 时,Nginx 会在错误日志中出现"accept() failed (24: Too many open files)",随后拒绝新连接。另一个常见问题是 PHP-FPM 的 pm.max_children 设得过高,如 8GB 内存服务器设为 300,每个进程占 40MB 时总内存需求达 12GB,直接触发 OOM killer 导致 Nginx 返回 502 Bad Gateway。
解决方案
第一步:同步调整系统级文件描述符限制
编辑/etc/security/limits.conf,添加以下内容:
* soft nofile 65535
* hard nofile 65535
确保/etc/pam.d/common-session 包含session required pam_limits.so,然后重启登录或重载 PAM。同时检查系统级最大文件数:cat /proc/sys/fs/file-max,确保远大于总连接需求(例如 10 万以上)。
第二步:配置 Nginx 进程级限制
在 nginx.conf 的主上下文(http 块外)添加:
worker_rlimit_nofile 65535;
该值应≥worker_connections,推荐设为相同数值。在 events 块内设置:
worker_connections 4096;
use epoll;
multi_accept on;
根据业务类型调整数值:普通中型网站(日活 10 万以内)设为 2048~4096 已足够;API 服务或短连接高频场景可设为 16384~65535。
第三步:优化 PHP-FPM 进程模型
根据内存计算 pm.max_children:用ps aux --sort=-%mem | grep php-fpm查看单个进程内存占用。若平均占 40MB,服务器有 2GB 可用内存,则 max_children 安全上限≈(2048 MB ÷ 40 MB)≈51,设为 50 更稳妥。8GB 内存服务器保守建议≤120,16GB 可设到 200-250。
dynamic 模式下配套参数同步调整:
pm.start_servers = max_children × 0.3(如 50→15)
pm.min_spare_servers至少等于 start_servers
pm.max_spare_servers = max_children × 0.8(如 50→40)
pm.max_requests调至 5000–10000(PHP7.3 及以上版本内存管理较稳定)
第四步:调整内核网络参数
修改/etc/sysctl.conf:
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 25000
执行sysctl -p生效。若使用 systemd 管理 Nginx,需在 nginx.service.d/override.conf 中添加LimitNOFILE=65536防止 systemd 截断限制。
注意事项
1. phpenv 等版本管理工具对高并发无直接影响:phpenv 是纯用户态 shell 工具,只通过修改$PATH 和 PHP_VERSION 环境变量切换 CLI 下 PHP 版本,不介入 Nginx worker 进程启动流程、PHP-FPM 进程模型、系统文件描述符限制及内核网络参数配置。切换 PHP 版本后必须重启 PHP-FPM 服务(systemctl restart php-fpm),否则 Nginx 仍在用旧进程处理请求。
2. pm.start_servers 设置陷阱:该值必须≤pm.max_children × 2,否则启动时会报"WARNING: pm.start_servers is not set"类警告。宝塔面板默认 start_servers 是 5,不要一上来就把 max_children 设成 300。
3. Keepalive 连接占用评估:若启用大量 keepalive(如超时设为 300s),每个长连接会持续占用一个连接槽位,此时需评估真实并发连接峰值而非 QPS。单个 worker 进程能处理的连接数受限于可用内存(每个连接约占用 2–4KB),8GB 内存服务器不建议单 worker 超过 65535。
4. 测试验证方法:不要使用单个客户端不断重复请求,应该是 N 个客户端的轮询。可用ss -s或netstat -ant | wc -l查看当前 ESTABLISHED 连接总数,对比 worker_processes × worker_connections 理论上限。
参考来源
来源:CSDN 博客 - Nginx 与 PHP-FPM 协同调优实战 (高负载场景下的稳定之道),2025 年 10 月 28 日收录
来源:宝塔面板官方文档 - 如何限制并发数_配置 Nginx 限流防止资源耗尽,2026 年 3 月 25 日
来源:技术社区 - phpEnv 配置 Nginx 处理大量并发请求 phpEnv 内核参数优化,2026 年 4 月 26 日
来源:博客园 - 如何提高宝塔面板 PHP7.3 的高并发处理能力,2026 年 4 月 7 日