PHP-FPM pm.max_children 参数如何根据内存大小计算?

文章导读
PHP-FPM pm.max_children 参数应根据服务器可用物理内存除以单个 PHP 进程平均占用内存来计算,适用于需要控制并发进程数量的场景。风险边界是数值过高会触发系统 OOM 杀死进程,数值过低会导致请求排队引发 502 错误。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

PHP-FPM pm.max_children 参数应根据服务器可用物理内存除以单个 PHP 进程平均占用内存来计算,适用于需要控制并发进程数量的场景。风险边界是数值过高会触发系统 OOM 杀死进程,数值过低会导致请求排队引发 502 错误。

先说结论:计算公式为(总内存 - 系统预留内存)/ 单个 PHP 进程平均内存,结果向下取整。

  • 先测量:使用命令查看当前 PHP 进程实际内存占用,不要直接套用经验值。
  • 留余量:必须扣除操作系统和其他服务所需的内存,防止系统卡死。
  • 再验证:修改配置后观察日志和内存变化,确认无 OOM 或排队现象。

命令速用版

以下命令用于快速获取计算所需的内存数据,直接在终端执行即可。

# 查看系统总内存和可用内存(单位 MB)
free -m

# 查看 PHP-FPM 进程平均内存占用(单位 KB,需转换为 MB)
ps aux | grep php-fpm | awk '{sum+=$6} END {print sum/NR}'

为什么会这样

pm.max_children 限制了 PHP-FPM 同时能 spawn 的最大子进程数量,直接决定并发处理能力。

每个 PHP 进程都会占用独立的内存空间,如果设置的子进程数乘以单进程内存超过物理内存上限,操作系统会触发 OOM Killer 强制杀死进程。公开资料中没有统一的单进程内存标准值,因为不同框架、代码质量和扩展加载情况会导致内存差异巨大,因此必须基于实际测量值计算。

分步处理

按照以下步骤计算并配置参数,确保操作可回滚。

第一步:确认总内存
执行 free -m,记录 total 列的数值。如果是云服务器,注意区分独享内存和共享内存。

第二步:测量单进程内存
在生产环境低峰期或测试环境,执行 ps aux | grep php-fpm。观察 RSS%MEM 列,计算多个进程的平均值。注意区分 master 进程和 worker 进程,仅计算 worker 进程。

第三步:确定系统预留
扣除操作系统、数据库、Web 服务器等其他服务所需的内存。公开资料中没有可靠的量化比例,通常建议预留至少 20%-30% 或固定预留 512MB 以上,具体取决于运行的其他服务。

第四步:计算并修改配置
应用公式:(总内存 - 预留内存) / 单进程平均内存。编辑 PHP-FPM 配置文件(通常位于 /etc/php-fpm.d/www.conf/etc/php/版本/fpm/pool.d/www.conf),修改 pm.max_children 值。

第五步:平滑重载
执行 systemctl reload php-fpmservice php-fpm reload,避免直接 restart 导致当前请求中断。

PHP-FPM pm.max_children 参数如何根据内存大小计算?

怎么验证是否生效

修改配置后,通过以下指标确认设置是否合理。

检查进程数
执行 ps aux | grep php-fpm | wc -l,确认运行中的 worker 进程数不超过设定值。

检查系统日志
执行 dmesg | grep -i kill 或查看 /var/log/messages,确认没有 OOM Killer 杀死 PHP 进程的记录。

检查错误日志
查看 PHP-FPM 慢日志或错误日志(通常位于 /var/log/php-fpm/error.log),确认没有频繁的 server reached max_children setting 警告。

检查内存状态
持续观察 free -m 中的 available 值,确保系统未频繁使用 Swap 分区。

常见坑

  • 内存泄漏:如果 PHP 代码存在内存泄漏,单进程内存会随时间增长,导致原本合理的 pm.max_children 后期引发 OOM,建议配合 pm.max_requests 定期重启进程。
  • Swap 干扰:如果系统开启了 Swap,内存计算会变得复杂,Swap 读写会严重拖慢 PHP 响应速度,不应依赖 Swap 作为内存不足缓冲。
  • 动态模式差异:如果 pm 设置为 dynamicpm.max_children 是上限,实际进程数会在 pm.start_servers 和上限之间波动,计算时仍需以上限为准。
  • 不同脚本差异:后台脚本和 Web 请求的内存占用可能不同,如果混合运行,需按占用最高的场景计算。

常见问题

pm.max_children 设置多少合适?

没有固定值,必须根据(可用内存/单进程内存)计算得出。

出现 502 Bad Gateway 是 max_children 不够吗?

可能是,如果日志显示达到最大进程数限制,则需要增加该值或优化单进程内存占用。

动态模式 pm=dynamic 需要计算吗?

需要,pm.max_children 在动态模式下同样作为硬上限生效,超过该值请求会排队。

修改后需要重启服务器吗?

不需要,重载 PHP-FPM 服务即可生效,重启服务器会影响其他服务。

参考来源