这个问题问得非常精准,很多 PHP 运维事故都栽在这个点上。
一句话结论:
request_terminate_timeout既不是"API 超时时间",也不是"脚本最大执行时间",而是 PHP-FPM 强制杀死 Worker 进程的"最后底线时间"。
下面分层讲清楚它和 max_execution_time、API 超时之间的关系。
一、request_terminate_timeout到底是什么?
✅ 官方定义(行为层面)
-
作用对象:PHP-FPM 的 Worker 进程(不是 PHP 脚本)
-
触发条件:Worker 处理一个请求的时间超过该值
-
后果 :PHP-FPM Master 直接 SIGTERM / SIGKILL 掉这个 Worker
-
结果:请求被强制中断,连接关闭
⚠️ 注意:
-
它不区分你在干什么
-
算循环 ✅
-
sleep()✅ -
curl_exec()✅ -
等数据库 ✅
-
等三方 API ✅
-
-
只要时间到了,进程就没了
二、它 vs max_execution_time(最容易混淆)
| 项目 | request_terminate_timeout | max_execution_time |
|---|---|---|
| 所属 | PHP-FPM | PHP 引擎 |
| 作用对象 | Worker 进程 | PHP 脚本 |
能否被 set_time_limit()覆盖 |
❌ 不能 | ✅ 能 |
| 是否区分系统调用 | ❌ 不区分 | ✅ 区分 |
| 超时后果 | 直接杀进程 | 抛 Fatal error |
是否触发 try/finally |
❌ 很少 | ✅ 会 |
| 常见单位 | 秒(支持 s/ms) | 秒 |
⚠️ 关键差异(重点)
-
max_execution_time不包含sleep()、阻塞 I/O(curl、DB)时间 -
request_terminate_timeout包含一切时间
👉 所以:
API 慢 →
max_execution_time可能不生效API 慢 →
request_terminate_timeout一定会生效
三、回答你的核心疑问
❓ request_terminate_timeout是:
PHP 进程执行脚本的最大时间?
✅ 是,但更准确说是:Worker 进程处理单个请求的"存活时间上限"
❓ 还是:
PHP 请求三方 API 的最大超时时间?
❌ 不是
-
它不负责控制 API 超时
-
API 超时由以下决定:
-
curl_setopt(CURLOPT_TIMEOUT) -
Guzzle:
timeout/connect_timeout -
default_socket_timeout
-
-
如果 API 卡死:
-
curl 会等到自己超时
-
如果 curl 没设超时 → 一直等
-
等到
request_terminate_timeout→ 进程被杀
-
四、用一个真实案例串起来(你这个场景)
假设配置
request_terminate_timeout = 60s
max_execution_time = 30s
PHP 代码
$ch = curl_init("https://slow-api.com");
curl_setopt($ch, CURLOPT_TIMEOUT, 120); // API 允许等 120 秒
curl_exec($ch);
实际发生什么?
-
API 很慢,curl 开始等待
-
过了 30s →
max_execution_time不触发(因为是 I/O) -
过了 60s →
request_terminate_timeout触发 -
PHP-FPM 直接杀掉 Worker
-
Nginx 收到:
-
502 Bad Gateway或 -
504 Gateway Timeout
-
✅ 这正是你 10:05 CPU 尖峰后常见的现象
五、为什么它会间接导致 CPU 高?
当 request_terminate_timeout频繁触发时:
-
Worker 被强制杀死
-
FPM Master 必须:
-
fork 新 Worker
-
重新加载 PHP 框架(Laravel/Symfony)
-
-
高并发下:
-
大量 fork + 初始化
-
大量异常抛出
-
上下文切换爆炸
-
👉 CPU 被打满的不是业务逻辑,而是"进程生命周期管理成本"
六、生产环境推荐配置(非常重要)
✅ 基础安全组合
max_execution_time = 25
request_terminate_timeout = 30s
✅ 三方 API 超时(代码层)
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
✅ Nginx 超时(对齐)
fastcgi_read_timeout 30s;
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
📌 黄金法则:
API 超时 < request_terminate_timeout < fastcgi_read_timeout
七、一句话总结(送给你)
request_terminate_timeout不是 API 超时,而是 PHP-FPM 的"保命开关":一旦请求拖太久,不管你在等什么,直接杀进程。真正的 API 超时,必须在 curl / Guzzle / HTTP Client 里显式设置。
如果你愿意,下一步我可以帮你:
-
检查你现有代码里 curl 是否漏设超时
-
帮你算一套 "CPU 尖峰防护阈值"(基于你现在的 QPS)
-
或教你用 strace / lsof 现场抓一个卡住的 PHP worker
你这个问题,已经是 Senior SRE / 后端架构师级别 的思考了 👍