PHP-FPM 日志显示 max_children reached 警告如何优化进程数?

文章导读
当日志出现"WARNING: [pool www] server reached pm.max_children setting (5)"时,按实际内存倒推计算,4GB 服务器建议将 max_children 设为 70 左右(预留 30% 系统内存后,2800MB÷32MB≈87,再打八折)。
📋 目录
  1. A 原因分析
  2. B 计算合理的 max_children 值
  3. C 调整 start_servers 避免高并发卡顿
  4. D 启用状态监控排查真因
  5. E 注意事项
  6. F 参考来源
A A

PHP-FPM 日志显示 max_children reached 警告如何优化进程数?

核心结论:当日志出现"WARNING: [pool www] server reached pm.max_children setting (5)"时,按实际内存倒推计算,4GB 服务器建议将 max_children 设为 70 左右(预留 30% 系统内存后,2800MB÷32MB≈87,再打八折)。

原因分析

PHP-FPM 通过预启动多个 PHP 进程处理请求,当并发访问超过最大进程数限制时,新请求会排队等待,导致响应延迟飙升到 2s+ 甚至出现 502 Bad Gateway 或 503 Service Temporarily Unavailable 错误。每个子进程平均占用 20–50MB 内存(取决于扩展加载量和脚本复杂度),若 max_children 设成 100 意味着可能占用 2–5GB 物理内存。真实报错信息通常为:"WARNING: [pool www] server reached pm.max_children setting (5), consider raising it",同时伴随"ERROR: unable to read what child say: Bad file descriptor (9)"。

计算合理的 max_children 值

第一步:查当前 PHP 进程平均内存占用,执行命令ps aux --sort=-%mem | grep php-fpm | head -n 5查看 RSS 列取中间值(实测案例中为 32MB)。第二步:留出 30% 内存给系统、MySQL、宝塔自身,若总内存 4GB,可用约 2.8GB 给 PHP-FPM。第三步:计算上限 floor(2800 / 32) ≈ 87,再打八折取 70 作为 max_children。不同规模网站参考值:小型网站 pm.max_children 10~30,中型网站 50~200,大型高并发需结合压测和内存监控动态调整。若服务器 8GB 内存、单个 PHP 进程最大占用 50MB,则 8GB / 50MB ≈ 160,建议 pm.max_children 设为 120~140。

调整 start_servers 避免高并发卡顿

宝塔默认使用 pm = dynamic 模式,但很多人把 pm.start_servers 设成 2 或 5,结果高并发一来新请求排队等进程启动。该值应反映「日常最低稳定负载」下的活跃进程数:在宝塔「网站」→「PHP 设置」→「性能调整」查看「当前运行中进程数」的 5 分钟低谷值(实测常在 12–18 之间波动),start_servers 建议设为该区间的下限(如 12),min_spare_servers 设为 8–10。如果站点有定时任务或早高峰突增流量,start_servers 可比低谷值高 2–3 个,但别超过 max_children * 0.3。配置示例:pm = dynamicpm.max_children = 80pm.start_servers = 10pm.min_spare_servers = 5pm.max_spare_servers = 20pm.max_requests = 500

PHP-FPM 日志显示 max_children reached 警告如何优化进程数?

启用状态监控排查真因

502 错误或 Nginx 的 upstream timed out 往往不是 max_children 不够,而是其他环节堵住。首先检查 pm.status_path 是否启用(宝塔默认关闭),启用后可用curl http://127.0.0.1/status?full查看真实进程状态,确认是否真达到 max_children。Nginx 配置示例:location ~ ^/(status|ping)$ { fastcgi_pass 127.0.0.1:9000; include fastcgi_params; allow 127.0.0.1; deny all; }。其次查看 slowlog,宝塔在/www/wwwlogs/php_slow.log 记录>1 秒的脚本,大量慢请求会占满进程池,此时加 max_children 只会让内存更快耗尽。最后检查 Nginx 的 fastcgi_read_timeout 默认 60 秒,若 PHP 脚本真要跑 90 秒,得同步调大。

注意事项

真实用户踩过的坑:1)改完配置必须重启 PHP-FPM,执行bt restart php或在宝塔界面点「重载配置」,仅「保存」不生效。2)有用户反馈服务器内存 2GB 但可用内存只剩下 70m,内存使用率高达 92%,发现 php-fpm 服务池开启了太多子进程占用超过大半内存,导致数据库服务(占用 15.2% 内存)被挤掉。3)pm = static 模式下进程数自始至终都是 pm.max_children 指定的数量,pm.start_servers 等配置将没有作用。4)日志中若出现"WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle",说明空闲进程不足而非最大进程数不够。5)每个进程处理请求数建议设置 pm.max_requests = 500 防止内存泄漏。

参考来源

来源:宝塔面板官方文档 - 如何优化宝塔面板 PHP-FPM 并发性能_调整 max_children 与启动进程数(收录于 2026 年 4 月 8 日)

PHP-FPM 日志显示 max_children reached 警告如何优化进程数?

来源:腾讯云开发者社区 - 解决 Linux 下 php-fpm 进程过多导致内存耗尽问题(2026 年 4 月 6 日)

来源:Webcore Community - How To: Solve PHP-FPM server reached max_children(2022 年 11 月 22 日发布)

来源:腾讯云开发者社区 - PHP-FPM 性能优化配置方法参考(2025 年 9 月 11 日)