如何配置 PHP-FPM 的 request_terminate_timeout 防止脚本死锁?

文章导读
在 PHP-FPM 的池配置文件(通常是 www.conf)中设置 request_terminate_timeout 参数,可以强制终止运行超过指定秒数的脚本,防止单个慢脚本占满所有 worker 进程导致服务不可用。该配置优先于 php.ini 中的 max_execution_time,适用于 CGI/FPM 环境。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

在 PHP-FPM 的池配置文件(通常是 www.conf)中设置 request_terminate_timeout 参数,可以强制终止运行超过指定秒数的脚本,防止单个慢脚本占满所有 worker 进程导致服务不可用。该配置优先于 php.ini 中的 max_execution_time,适用于 CGI/FPM 环境。

先说结论:配置 request_terminate_timeout 是防止 PHP-FPM 进程池因脚本死锁或长时间运行而耗尽的有效手段,能在进程层面回收资源。

  • 适合:PHP-FPM 模式下防止 worker 进程被慢脚本占满的场景。
  • 先准备:确认业务脚本的最大正常执行耗时,避免误杀合法长任务。
  • 验收:通过 sleep 测试脚本验证超时终止是否生效,并检查错误日志。

命令速用版

在池配置文件中添加或修改以下参数,然后重载服务。

request_terminate_timeout = 30s

重载命令示例(根据实际服务名调整):

systemctl reload php-fpm

为什么会这样

PHP-FPM 的 request_terminate_timeout 是在进程管理器层面强制杀死脚本,而 php.ini 中的 max_execution_time 仅在脚本执行层面抛出错误。

当脚本因数据库锁、外部 API 超时或死循环卡住时,max_execution_time 可能无法及时释放进程资源,导致 FPM 子进程处于僵死状态。设置 FPM 层面的超时能确保操作系统层面回收该进程,防止连接池耗尽。

分步处理

1. 找到池配置文件,常见路径为 /etc/php-fpm.d/www.conf 或 /etc/php/8.x/fpm/pool.d/www.conf。

如何配置 PHP-FPM 的 request_terminate_timeout 防止脚本死锁?

2. 搜索 request_terminate_timeout,取消注释并设置秒数,例如 request_terminate_timeout = 30s。

3. 执行语法检查命令 php-fpm -t 或 php-fpm -tt 确保配置无误。

4. 重载 PHP-FPM 服务,避免直接 kill 导致当前请求中断。

怎么验证是否生效

创建一个包含 sleep 函数的测试脚本,例如 sleep(40),然后通过浏览器访问。

如果配置为 30 秒,请求应在 30 秒后被切断,返回 502 Bad Gateway 或 504 Gateway Time-out。

检查 PHP-FPM 错误日志,通常位于 /var/log/php-fpm/error.log,确认是否有脚本终止记录。

常见坑

1. 设置过短:正常业务逻辑(如大文件导出)可能超过阈值,导致合法请求被杀。

如何配置 PHP-FPM 的 request_terminate_timeout 防止脚本死锁?

2. 配置未生效:修改了 php.ini 而非 FPM 池配置,或者修改后未重载服务。

3. CLI 模式无效:该参数仅对 FPM SAPI 生效,命令行脚本不受此限制。

常见问题

request_terminate_timeout 和 max_execution_time 有什么区别?

max_execution_time 是 PHP 脚本层面的限制,抛出 fatal error;request_terminate_timeout 是 FPM 进程层面的限制,直接杀死进程。

超时后日志在哪里查看?

主要查看 PHP-FPM 的错误日志,路径通常在 php-fpm.conf 中配置的 error_log 项,常见于 /var/log/php-fpm/ 目录。

这个配置会影响 CLI 脚本吗?

不会,request_terminate_timeout 仅适用于 PHP-FPM 模式,命令行运行的 PHP 脚本不受此参数控制。

参考来源

PHP.net - FPM Configuration: https://www.php.net/manual/en/install.fpm.configuration.php