Nginx+PHP-FPM环境下max_execution_time不生效问题排查
Nginx+PHP-FPM超时不一致问题解决方案
为什么max_execution_time=30未生效
max_execution_time仅统计PHP进程实际占用CPU的运行时间,像sleep()、数据库查询、网络请求这类处于等待状态、不消耗CPU资源的操作,不会被计入超时时长。你的测试代码中每次sleep(1)都不会消耗这个超时额度,因此PHP脚本不会在30秒时终止。
核心需求解决方案:客户端断开后终止PHP执行
要避免Nginx返回504后PHP仍做无用功,同时不重启PHP-FPM worker,可通过以下方法实现:
1. 检测客户端连接状态并主动终止脚本
PHP内置connection_aborted()函数可检测客户端(此处为Nginx)是否已断开连接,配合默认的ignore_user_abort(false)(客户端断开时脚本会终止),在脚本的关键节点插入检测逻辑:
// 显式设置客户端断开时终止脚本(默认已开启,可省略但更清晰) ignore_user_abort(false); foreach (range(1, 50) as $i) { sleep(1); // 每次循环检测连接状态,断开则终止脚本 if (connection_aborted()) { $this->logger->info('Client disconnected, stopping execution'); exit; } if ($i > 40) { $this->logger->error('Processing request', ['i' => $i]); continue; } if ($i > 20) { $this->logger->warning('Processing request', ['i' => $i]); continue; } $this->logger->info('Processing request', ['i' => $i]); } $this->logger->info('Request processed');
原理:Nginx返回504后会主动断开与PHP-FPM的连接,connection_aborted()能捕获这个状态,此时调用exit即可让脚本主动终止,不会影响PHP-FPM worker进程的复用。
2. 生产环境长耗时操作补充优化
- 数据库查询超时:针对MySQL等数据库,可在执行查询前设置语句超时,例如
SET STATEMENT_TIMEOUT=30000;(单位毫秒),让数据库主动终止慢查询,避免PHP长时间等待。 - 定期检测连接:对于无法设置超时的IO操作,在代码的循环、关键步骤后插入
connection_aborted()检测,确保客户端断开后能及时终止脚本。
3. 确保Nginx与PHP的超时配置对齐
- 调整Nginx的
fastcgi_read_timeout(若使用fastcgi_pass连接PHP-FPM)为30秒,与预期超时一致:location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm.sock; fastcgi_read_timeout 30s; # 其他fastcgi配置... }
内容的提问来源于stack exchange,提问作者Bogdan Dubyk
相关产品推荐
相关产品推荐

