NginX在60秒后发出HTTP 499错误,尽管配置。(PHP 和 AWS)

2022-08-30 09:46:49

在上周结束时,我注意到我的一个中型AWS实例出现问题,如果请求超过60秒,Nginx总是返回HTTP 499响应。请求的页面是 PHP 脚本

我花了几天时间试图找到答案,并尝试了我在互联网上能找到的所有内容,包括Stack Overflow上的几个条目,没有任何效果。

我尝试过修改PHP设置,PHP-FPM设置和Nginx设置。你可以看到我周五(http://forum.nginx.org/read.php?9,237692)在NginX论坛上提出的一个问题,尽管这个问题没有得到任何回应,所以我希望在我被迫搬回Apache之前,我可能能够在这里找到答案,我知道这只是有效的。

此问题与其他条目中报告的 HTTP 500 错误不同

我已经能够使用PHP 5.4.11使用NginX的新micro AWS实例复制这个问题。

为了帮助任何希望看到问题的实际应用的人,我将带您完成我为最新的Micro测试服务器运行的设置。

您需要使用 AMI-c1aaabb5 启动新的 AWS 微型实例(因此免费)

此 PasteBin 条目具有完整的设置,可以运行以镜像我的测试环境。您只需要在最后更改NginX配置中的 example.com

http://pastebin.com/WQX4AqEU

一旦设置好了,你只需要创建一个示例PHP文件,我正在测试哪个是

<?php
sleep(70);
die( 'Hello World' );
?>

将其保存到 webroot 中,然后进行测试。如果您使用php或php-cgi从命令行运行脚本,它将起作用。如果您通过网页访问脚本并跟踪访问日志 /var/log/nginx/example.access.log,您会注意到在 60 秒后收到 HTTP 1.1 499 响应。

现在你可以看到超时,我将通过我对PHP和NginX所做的一些配置更改来尝试解决这个问题。对于PHP,我将创建几个配置文件,以便可以轻松禁用它们

更新 PHP FPM 配置以包含外部配置文件

sudo echo '
include=/usr/local/php/php-fpm.d/*.conf
' >> /usr/local/php/etc/php-fpm.conf

创建新的 PHP-FPM 配置以覆盖请求超时

sudo echo '[www]
request_terminate_timeout = 120s
request_slowlog_timeout = 60s
slowlog = /var/log/php-fpm-slow.log ' >
/usr/local/php/php-fpm.d/timeouts.conf

更改某些全局设置以确保紧急重启间隔为 2 分钟

# Create a global tweaks
sudo echo '[global]
error_log = /var/log/php-fpm.log
emergency_restart_threshold = 10
emergency_restart_interval = 2m
process_control_timeout = 10s
' > /usr/local/php/php-fpm.d/global-tweaks.conf

接下来,我们将更改一些 PHP。INI 设置,再次使用单独的文件

# Log PHP Errors
sudo echo '[PHP]
log_errors = on
error_log = /var/log/php.log
' > /usr/local/php/conf.d/errors.ini

sudo echo '[PHP]
post_max_size=32M
upload_max_filesize=32M
max_execution_time = 360
default_socket_timeout = 360
mysql.connect_timeout = 360
max_input_time = 360
' > /usr/local/php/conf.d/filesize.ini

如您所见,这会将套接字超时增加到 3 分钟,并有助于记录错误。

最后,我将编辑一些NginX设置,以增加超时侧的超时

首先,我编辑文件/etc/nginx/nginx.conf,并将其添加到http指令fastcgi_read_timeout 300;

接下来,我编辑我们之前创建的文件/etc/nginx/sites-enabled/example(请参阅 pastebin 条目),并将以下设置添加到服务器指令中。

client_max_body_size    200;
client_header_timeout   360;
client_body_timeout     360;
fastcgi_read_timeout    360;
keepalive_timeout       360;
proxy_ignore_client_abort on;
send_timeout            360;
lingering_timeout       360;

最后,我将以下内容添加到服务器目录的位置〜.php$部分

fastcgi_read_timeout 360;
fastcgi_send_timeout 360;
fastcgi_connect_timeout 1200;

在重试脚本之前,请同时启动nginx和php-fpm,以确保已选取新设置。然后,我尝试访问该页面,但仍然在NginX示例中收到HTTP / 1.1 499条目.log。

那么,我哪里出错了呢?当我将PHP的最大执行时间设置为2分钟时,这仅适用于apache。

我可以看到PHP设置是通过从Web可访问的页面运行phpinfo()来获取的。我只是不明白,我实际上认为已经增加了太多,因为它只需要PHP的max_execution_timedefault_socket_timeout改变以及NginX fastcgi_read_timeout仅在服务器>位置指令中。

更新 1

在执行了一些进一步的测试以表明问题不在于客户端正在死亡之后,我已将测试文件修改为

<?php
file_put_contents('/www/log.log', 'My first data');
sleep(70);
file_put_contents('/www/log.log','The sleep has passed');
die('Hello World after sleep');
?>

如果我从网页运行脚本,那么我可以看到文件的内容被设置为第一个字符串。60秒后,错误出现在NginX日志中。10秒后,文件的内容变为第二个字符串,证明PHP正在完成该过程。

更新 2

fastcgi_ignore_client_abort打开;确实会将响应从 HTTP 499 更改为 HTTP 200,尽管仍不会向最终客户端返回任何内容。

更新 3

将Apache和PHP(5.3.10)直接安装到盒子上(使用apt),然后增加执行时间,问题似乎也发生在Apache上。症状与现在的NginX相同,HTTP200响应,但实际的客户端连接在手之前超时。

我也开始注意到,在NginX日志中,如果我使用Firefox进行测试,它会发出双重请求(就像这个PHP脚本在超过60秒时执行两次)。尽管这似乎是客户端在脚本失败时请求


答案 1

问题的原因是 AWS 上的弹性负载均衡器。默认情况下,它们在 60 秒不活动后超时,这就是导致问题的原因。

所以它不是NginX,PHP-FPM或PHP,而是负载均衡器。

要解决此问题,只需进入ELB“描述”选项卡,滚动到底部,然后单击值旁边的“(编辑)”链接,该值显示“空闲超时:60秒”


答案 2

实际上,我在一台服务器上遇到了同样的问题,我发现在nginx配置更改后,我没有重新启动nginx服务器,因此每次点击nginx url时,我都会得到499 http响应。在nginx重新启动后,它开始正常工作,并带有http 200响应。


推荐