我正在使用 Apache2 和 PHP(5.6)的 Bitnami 安装进行工作,我们在处理一个需要超过 60 秒才能完成的脚本时遇到了问题。
该脚本在 60 秒后失败,并发送 504 错误。
我已经检查了所有其他可能性,但它总是回到执行时间。
if(round($mem_usage/1048576,2) > 36)
{
echo "exceded 36mb, aborting<br>";
echo "element: ".$fila." of ".mysql_num_rows($result)."<br>";
echo "memory usage: ".round($mem_usage/1048576,2)."M <br>";
echo "memory limit: ".ini_get('memory_limit')." <br>";
echo "max_execution_time: ".ini_get('max_execution_time')."<br>";
$time_end = microtime(true);
$time = $time_end - $time_start;
echo "time elapsed: ".ceil($time)." seconds";
exit();
}
内存值始终处于正常范围内(我们增加了内存限制以防万一),但是每当时间过去 60 秒时脚本都无法打印此消息,因此我们丢弃了内存使用情况。
我在 StackExchange 问题中搜索了很多内容,并整理了针对此问题的常见答案列表:
- 最大执行时间
我们尝试将其增加到 300,但是没有效果。PHP 似乎忽略了这个值,已经检查了 php_info() 以防它没有设置,但事实确实如此。
- 内存限制
如上所述,RAM 使用率保持在正常范围内。这不是崩溃的原因。
- 执行 try{}catch(){}
脚本暂停并且不执行 catch 块内的代码。
- 检查错误日志
PHP 不会向错误日志中写入任何内容,它只是突然终止脚本,并且没有任何输出,我们已经检查了 php.ini 中的日志选项
- 设置时间限制()
此方法返回 FALSE,根据文档,这意味着无法设置新的时间限制,安全模式是导致这种情况发生的常见原因,这引导我们进入下一步
- 安全模式
根据文档,这是 PHP5.6。
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
- 最大输入时间
我们设置为300,没有效果。
- 默认套接字超时
同上
- 检查.htaccess 的相关配置
完成,但我们没有发现任何东西。
- 在 Apache 配置中设置超时
我们的 Apache 配置中没有超时选项,添加后也没有任何效果。
- 我在答案中收到了更多建议,因此我将它们添加到这里。
对于某些 PHP 脚本来说,这是不可能的,但是您是否尝试过从命令行而不是通过 HTTP 请求运行脚本?这将排除 Apache 或 PHP-FPM 配置是否搞砸了。
该脚本无法在 CLI 中运行,但运行虚拟脚本会导致无限期执行,因此 CLI 不会停止执行。
您的 PHP-FPM 配置中是否为 max_execution_time 或 request_terminate_timeout 设置了任何内容?
request_terminate_timeout 设置为 300,无效。php_admin_value[max_execution_time] 设置为 300,无效。(根据文档,必须这样设置)
您的 Apache 配置中是否为 LimitRequestBody (或任何其他限制) 设置了任何内容?
未在任何地方设置,并且 Apache 配置中没有其他相关限制。
发生这种情况时,您是否正在执行文件上传?如果是,您是否检查过 PHP 配置中的 upload_max_filesize 和 post_max_size?
此请求中未发生任何文件上传,因此这些限制与此特定情况无关。
根据浏览器获得不同的响应是没有意义的,除非您在 PHP 中执行某种浏览器检测并让您的应用程序根据此行为做出不同的行为。如果您没有这样做,并且您可以始终确认这种相关性,那么您可以做的一件事就是查看两个不同的浏览器是否出于某种原因发送了不同的请求。
显然,这就是 Firefox 显示错误的方式,使用网络中的开发者控制台显示 504,与 Chrome 中相同(我提问时犯了错误,因为我不小心输入了 503。)
你尝试过 ignore_user_abort(true) 吗
刚刚启用了 ignore_user_abort(通过 PHP-FPM 设置)。但没有任何效果。
和/或尝试通过 register_shutdown_function() 捕获一些诊断信息?
尝试注册关闭功能没有任何效果,因为代码块从未执行过。
最后要注意的是,该服务器有 PHP-FPM,我们在那里设置 PHP 配置,但是我们所做的一切都没有任何效果,并且相关脚本仍然在 60 秒后终止。
任何关于此问题的帮助都将受到感谢。
答案1
您是直接访问 Apache 服务器还是通过负载平衡器或代理访问?
OP 中的这条评论让我意识到我们正在使用 AWS 负载均衡器。检查文档后,我们发现它的默认空闲超时为 60 秒。
增加此限制可使脚本顺利完成。
答案2
其他需要检查的事项:
- 对于某些 PHP 脚本来说,这是不可能的,但是您是否尝试过从命令行而不是通过 HTTP 请求运行脚本?这将排除 Apache 或 PHP-FPM 配置是否搞砸了。
- 您的 PHP-FPM 配置中有设置任何内容吗
max_execution_time
?request_terminate_timeout
- 您的 Apache 配置中是否设置了任何内容
LimitRequestBody
(或任何其他限制)? - 发生这种情况时,您是否正在执行文件上传?如果是,您是否检查过
upload_max_filesize
PHPpost_max_size
配置? - 根据浏览器获得不同的响应是没有意义的,除非您在 PHP 中执行某种浏览器检测并让您的应用程序根据此行为做出不同的行为。如果您没有这样做,并且您可以始终确认这种相关性,那么您可以做的一件事就是查看两个不同的浏览器是否出于某种原因发送了不同的请求。
答案3
除了 Brad 提出的出色建议之外,您是否尝试过 ignore_user_abort(true) 和/或尝试通过 register_shutdown_function() 捕获一些诊断信息?