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

时间:2013-03-25 11:09:18

标签: php http nginx amazon-web-services

在上周末,我注意到我的一个中型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的新的微型AWS实例来复制问题。

为了帮助那些希望在行动中看到问题的人,我将带您完成我为最新的Micro测试服务器运行的设置。

您需要使用AMI ami-c1aaabb5启动新的AWS Micro实例(因此它是免费的)

此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;

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

fastcgi_read_timeout 360;
fastcgi_send_timeout 360;
fastcgi_connect_timeout 1200;

在重试脚本之前,启动nginx和php-fpm以确保已经选择了新设置。然后我尝试访问该页面,仍然在NginX example.error.log中收到HTTP / 1.1 499条目。

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

我可以看到,通过从Web可访问页面运行 phpinfo()来获取PHP设置。我只是没有得到,我实际上认为太多了,因为它应该只需要PHP的 max_execution_time default_socket_timeout 改变以及NginX的 fastcgi_read_timeout 只在server-&gt; location指令中。

更新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 on; 会将响应从HTTP 499更改为HTTP 200,但仍然没有任何内容返回给最终客户端。

更新3

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

我也开始注意到,在NginX日志中,如果我使用Firefox测试,它会发出双重请求(如PHP script executes twice when longer than 60 seconds)。虽然这似乎是客户端请求脚本失败

5 个答案:

答案 0 :(得分:61)

问题的原因是AWS上的Elastic Load Balancers。默认情况下,它们会在60秒不活动后超时,这是造成问题的原因。

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

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

答案 1 :(得分:1)

我以为我会留下两分钱。首先问题与php无关(仍然可能是php相关,php总是让我感到惊讶:P)。这是肯定的。它主要是由服务器代理自身引起的,更具体地说是主机名/别名名称问题,在你的情况下可能是负载均衡器正在请求nginx而nginx正在回调负载均衡器并且它继续这样做。

我遇到了nginx作为负载均衡器的类似问题,而apache作为webserver / proxy

答案 2 :(得分:0)

你需要找到问题所在的地方。我不知道确切的答案,但只是让我们试着找到它。

我们这里有3个元素:nginx,php-fpm,php。如你所知,apache下的相同php设置是可以的。没有相同的设置是否相同?您是否在相同的操作系统/主机/等上尝试使用apache而不是nginx?

如果我们看到,那个php不可疑,那么我们有两个嫌疑人:nginx&amp; PHP-FPM。

要排除nginx:尝试在ruby上设置相同的“系统”。请参阅https://github.com/garex/puppet-module-nginx以了解安装最简单的ruby设置。或者使用谷歌(可能会更好)。

我的主要嫌疑人是php-fpm。

尝试使用这些设置:

  • php-fpm的request_terminate_timeout
  • nginx`s fastcgi_ignore_client_abort

答案 3 :(得分:0)

实际上我在一台服务器上遇到了同样的问题,我发现在nginx配置更改之后我没有重启nginx服务器,所以每次点击nginx url我都得到了499的http响应。在nginx重启后,它开始正常使用http 200响应。

答案 4 :(得分:0)

不确定是否还有其他人遇到此问题,但对我来说,这是在我将/放在最后我的实例网址后发生的。这只会在我删除{{> 499 后出现错误1}},它给了我200,一切都很顺利。