如何优化 PHP-FPM 的 pm.max_requests 防止内存泄漏?

文章导读
设置 PHP-FPM 的 pm.max_requests 参数可以强制子进程在处理指定数量请求后重启,从而释放累积的内存。该方案适用于因第三方扩展或代码习惯导致进程驻留内存缓慢增长的场景,但设置过低会增加进程创建带来的 CPU 开销。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

设置 PHP-FPM 的 pm.max_requests 参数可以强制子进程在处理指定数量请求后重启,从而释放累积的内存。该方案适用于因第三方扩展或代码习惯导致进程驻留内存缓慢增长的场景,但设置过低会增加进程创建带来的 CPU 开销。

先说结论:pm.max_requests 是防止 PHP-FPM 进程长期运行导致内存缓慢增长的有效配置,但并非解决代码级内存泄漏的根本方案。

  • 先定位:通过监控工具确认 PHP-FPM 子进程 RSS 内存是否随请求数增加而持续上升。
  • 先做:在 pool 配置文件中设置合理的重启阈值,避免设置为 0 导致无限运行。
  • 再验证:观察重启频率与系统负载,确保不会因频繁重启导致 CPU 使用率异常升高。

命令速用版

查找配置文件位置并修改参数,完成后平滑重载配置。

grep -r "pm.max_requests" /etc/php*/fpm/pool.d/
php-fpm -t && systemctl reload php-fpm

若无法确定配置路径,可查看 phpinfo() 输出中的 "Loaded Configuration File" 或 "Additional .ini files" 附近信息,FPM 配置通常独立于 php.ini。

为什么会这样

PHP-FPM 采用多进程模型,子进程处理完请求后不会立即退出,而是保留在内存中等待下一个请求。

虽然 PHP 脚本执行结束后会释放大部分内存,但底层 C 扩展、第三方库或操作系统内存分配机制可能导致少量内存未被归还给操作系统。随着子进程处理请求数量增加,驻留内存(RSS)会逐渐累积。设置 pm.max_requests 后,子进程达到指定请求数会自动重启,新进程会重新分配内存,从而切断内存累积链条。

分步处理

步骤 1:确认当前配置

查看当前 pool 配置文件,通常位于 /etc/php-fpm.d/www.conf/etc/php/版本/fpm/pool.d/www.conf。搜索 pm.max_requests 项,若值为 0 或被注释,表示子进程默认不会主动重启。

步骤 2:设定初始值

如何优化 PHP-FPM 的 pm.max_requests 防止内存泄漏?

根据服务器内存大小和业务请求复杂度设置初始值。公开资料中没有看到可靠的量化数据表明统一的最佳值,常见实践范围在 500 到 2000 之间。内存较小或扩展较多的环境建议取较低值,内存充足且追求性能的环境可适当调高。

步骤 3:应用配置

修改配置文件后,先执行语法检查,再重载服务。

php-fpm -t
systemctl reload php-fpm

避免使用 restart 命令,以免中断正在处理的请求。

步骤 4:监控调整

观察运行一段时间后的进程状态。若发现进程重启过于频繁(如每分钟多次),说明值设置过低;若内存仍持续增长直至 OOM,说明值设置过高或存在严重泄漏。

怎么验证是否生效

检查配置是否加载

使用 php-fpm -i 或查看 FPM 状态页(需启用 pm.status_path),确认 max_requests 显示为设定值。

如何优化 PHP-FPM 的 pm.max_requests 防止内存泄漏?

观察进程内存变化

使用 ps 命令配合排序查看内存占用最高的 PHP-FPM 进程。

ps aux | grep php-fpm | sort -nk6

正常现象是进程内存占用在一定范围内波动,达到请求阈值后进程 PID 会变更,新进程内存占用回归基线。

检查系统日志

查看 FPM 日志文件(通常在 /var/log/php-fpm/ 或系统日志),确认是否有进程退出的记录,且退出原因为正常达到请求上限而非信号终止。

常见坑

设置过低导致 CPU 飙升

若 pm.max_requests 设置过小,进程频繁创建和销毁会消耗大量 CPU 资源,导致响应延迟增加。适用场景为内存敏感型环境,风险边界是需监控 CPU 负载。

如何优化 PHP-FPM 的 pm.max_requests 防止内存泄漏?

忽略 OPcache 重置成本

进程重启会导致该进程内的 OPcache 缓存失效,频繁重启可能降低脚本执行效率。操作动作是配合使用全局 OPcache 或适当调大 max_requests。

混淆代码泄漏与进程泄漏

该参数仅缓解进程驻留内存增长,无法修复代码中单次请求内的内存泄漏。验证结果是单次请求内存占用依然异常时,需检查代码逻辑。

常见问题

pm.max_requests 默认值是多少?

不同发行版和编译选项默认值不同,常见为 0(不限制)或 500,需查看具体配置文件确认。

设置该参数能修复代码内存泄漏吗?

不能,它只能定期重启进程释放累积内存,代码层面的泄漏仍需修复逻辑。

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

不需要,执行 php-fpm 平滑重载命令即可生效,不会中断现有连接。

如何确定具体的最佳数值?

公开资料中没有看到可靠的量化数据,建议从 500 开始,根据内存监控曲线和 CPU 负载逐步调整。

参考来源

  • PHP Official Documentation, "FPM Configuration", https://www.php.net/manual/en/install.fpm.configuration.php
  • PHP FPM Status Documentation, "pm.max_requests", https://www.php.net/manual/en/install.fpm.configuration.php#pm.max-requests