pm.max_children设太高会因内存超载引发OOM或swap,导致PHP-FPM进程卡在D状态、触发内核killer;应先测算单进程真实内存(如42MB),按可用内存÷单进程内存×0.8取安全值(如2GB→设45),并同步调整dynamic模式下start_servers=15、min_spare_servers=15、max_spare_servers=36,且需调大pm.max_requests至5000–10000、Nginx worker_connections至4096、系统ulimit至65535。

pm.max_children 设太高反而压垮服务器
进程积压不是因为子进程太少,而是 pm.max_children 超出内存承载能力,导致频繁 OOM 或 swap,PHP-FPM 进程卡在不可中断状态(D 状态),ps aux | grep php-fpm 里能看到大量 R 或 D 状态进程。此时调大参数只会让系统更慢,甚至触发内核 killer 杀掉 MySQL 或 Nginx。
必须先算单进程真实内存占用:ps -ylC php-fpm --sort:rss | awk '{sum+=$8} END {print int(sum/NR/1024)" MB"}'。比如结果是 42 MB,服务器可用内存 2GB,则 pm.max_children 安全上限 ≈ 2048 / 42 ≈ 48,设成 45 更稳妥。
- 别信“别人家的配置”,宝塔默认给的 100 是典型踩坑值
- 如果用的是宝塔,进「网站 > 设置 > PHP > 配置文件」搜
pm.max_children直接改,改完必须systemctl restart php73-fpm(不是 reload) - 改完立刻用
free -h和top观察内存是否回落、swap 是否归零
dynamic 模式下 start_servers 和 spare_servers 必须配套调
只改 pm.max_children 不动其他参数,pm.start_servers 太小(如默认 5),冷启动后新请求进来要等进程 fork,pm.min_spare_servers 又没跟上,就会出现 “空闲进程为 0,活跃进程逼近 max_children,但新请求还在排队” 的假性积压。
推荐比例(以 pm.max_children=45 为例):
立即学习“PHP免费学习笔记(深入)”;
-
pm.start_servers = 15(≈ max_children × 0.3) -
pm.min_spare_servers = 15(等于 start_servers,防抖动) -
pm.max_spare_servers = 36(≈ max_children × 0.8,留缓冲空间)
注意:这三者必须满足 min_spare_servers ≤ start_servers ≤ max_spare_servers ≤ max_children,否则 PHP-FPM 启动失败,日志里报 Invalid value for pm.min_spare_servers。
pm.max_requests 设太小会加剧积压
PHP7.3 内存管理已较稳定,但宝塔默认 pm.max_requests = 1000,高并发下子进程每处理千次请求就重启一次,fork 开销 + OPCache 重建 + 扩展重载,CPU 被大量吃掉,实际吞吐反而下降,表现为 active processes 高频波动、slowlog 里全是 “process exited with code 0 after X requests”。
建议直接调到 5000–10000,但有两个前提:
- 确认代码无内存泄漏:加
memory_get_usage()日志跑半天,看单进程 RSS 是否持续上涨 - 如果用了 PDO 长连接,确保每次请求结束前显式调用
$pdo->close(),否则max_requests加大会让连接堆积更明显
修改位置同上,在 PHP 配置文件里搜 pm.max_requests,改完同样要完整重启 php73-fpm。
别漏掉 Nginx 和系统层的并发瓶颈
即使 PHP-FPM 参数全调对,Nginx 的 worker_connections 还卡在默认 512,或系统 ulimit -n 只有 1024,照样会看到大量 connect() failed (11: Resource temporarily unavailable) 错误,本质是 socket 连接数不够,请求根本发不到 PHP-FPM。
检查和修复步骤:
- 查 CPU 核数:
nproc,然后在/www/server/nginx/conf/nginx.conf的events块里设worker_processes auto;和worker_connections 4096; - 查当前文件描述符限制:
ulimit -n,临时提至 65535:ulimit -n 65535;永久生效需改/etc/security/limits.conf,加两行:* soft nofile 65535和* hard nofile 65535 - 验证 PHP-FPM backlog 是否够:在 pool 配置里确认
listen.backlog = 1024(默认 511 太小)
真正难调的从来不是数字本身,而是你得同时盯着 php-fpm status 页面的 idle/active、ss -s 的 socket 统计、nginx error.log 的错误类型,三者对不上,光调 pm 参数就是蒙眼走路。



















