FrankenPHP在worker模式下忽略max_execution_time,因PHP常驻内存,超时由Caddy的timeout/read_timeout或应用层手动计时控制,php.ini和set_time_limit()设置无效。

FrankenPHP 脚本最大执行时间设置不生效,通常不是因为配置写错了,而是因为它的运行模型和传统 PHP-FPM 完全不同——它默认以常驻内存(worker 模式)运行,不再受 max_execution_time 控制。
FrankenPHP 的超时机制本质已改变
在传统 Nginx+PHP-FPM 架构中,每个请求启动一个独立的 PHP 进程,max_execution_time 是针对单次请求生命周期的硬性限制。而 FrankenPHP 启用 worker 模式后:
- PHP 应用常驻内存,一次启动、长期服务多个请求;
- 脚本本身不会因“执行太久”被终止,max_execution_time 参数在 worker 模式下被忽略;
- 真正起作用的是 HTTP 层的请求超时(如 Caddy 的 timeout 设置)或应用层逻辑控制(如手动检测耗时、主动退出)。
常见误操作导致“设置不生效”
很多人仍按老习惯修改 php.ini 或调用 set_time_limit(),结果无效,原因如下:
- php.ini 中的 max_execution_time=0 或 ini_set('max_execution_time', 0) 在 worker 模式下无意义——进程不销毁,该限制不触发;
- set_time_limit() 只对当前请求上下文有效,且仅在非 worker 模式下起作用;
- FrankenPHP 默认使用 Caddy 作为 HTTP 服务器,实际请求中断由 Caddy 的 read_timeout / write_timeout 决定,而非 PHP 自身;
- 如果启用了 FrankenPHP 的
php-worker模式(即通过frankenphp:run启动),整个生命周期由 Go 主进程管理,PHP 层面的超时配置基本失效。
正确控制执行时长的方式
要限制某段脚本的实际运行时间,需转向应用层或 HTTP 层干预:
立即学习“PHP免费学习笔记(深入)”;
-
在代码中手动计时并退出:用
microtime(true)记录起点,在循环/关键步骤中判断是否超限,主动 return 或 throw; -
调整 Caddy 配置中的超时参数(适用于 HTTP 请求场景):
timeout 60s(全局)或read_timeout 120s(针对特定路由); -
对 CLI 类型的长时间任务(如队列消费者),应脱离 HTTP 生命周期,改用 FrankenPHP 的
frankenphp:job或单独的 PHP CLI 进程,并在其中用set_time_limit()或信号监听控制; -
禁用 worker 模式临时验证:在
frankenphp.yaml中关闭workers,改用 classic 模式,此时 max_execution_time 会恢复作用——但这会失去常驻优势,仅用于调试。
还要检查是否被其他层拦截
即使 FrankenPHP 内部不限制,外部网关或反向代理也可能提前切断连接:
- Nginx 前置时,
proxy_read_timeout和fastcgi_read_timeout仍可能中断长请求; - 云服务商(如 Cloudflare、AWS ALB)有默认 30–60 秒的空闲超时,需单独调整;
- 浏览器自身也会在无响应时终止请求(尤其 Safari 对长连接较敏感)。



















