尽pipeconfigurationNginX 60秒后发出HTTP 499错误。 (PHP和AWS)

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

我花了好几天的时间试图find答案,并尝试了一切,我可以在互联网上find包括堆栈溢出几个条目,没有任何工作。

我已经尝试修改PHP设置,PHP-FPM设置和Nginx设置。 你可以在星期五在Nginx论坛上看到一个问题( http://forum.nginx.org/read.php?9,237692 ),虽然没有收到任何回应,所以我希望能够find在我被迫移回Apache之前,我回答了这个问题。

这与其他条目中报告的HTTP 500错误不是同一个问题。

我已经能够使用PHP 5.4.11将新的微型AWS实例NginX复制到这个问题上。

为了帮助任何希望看到问题的人,我将带领您参加最新的Microtesting服务器的设置。

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

这个PasteBin条目有完整的设置来运行镜像我的testing环境。 你只需要在最后的Nginxconfiguration中改变example.com

http://pastebin.com/WQX4AqEU

一旦设置完成,您只需创build我正在testing的示例PHP文件即可

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

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

现在你可以看到超时了,​​我将通过一些我已经对PHP和NginX进行的configuration更改来尝试解决这个问题。 对于PHP,我将创build几个configuration文件,以便可以轻松禁用它们

更新PHP FPMconfiguration以包含外部configuration文件

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

创build一个新的PHP-FPMconfiguration来覆盖请求超时

 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分钟,并帮助logging错误。

最后,我将编辑一些NginX设置来增加超时的那一面

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

接下来,我编辑之前创build的文件/ 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。

我可以看到PHP设置已经通过从web访问页面运行phpinfo()来获取。 我只是没有得到,我实际上觉得太多了,因为它应该只需要PHP的max_execution_timedefault_socket_timeout以及Nginx的fastcgi_read_timeout在服务器 – >位置指令。

更新1

进行了一些进一步的testing,表明问题不是客户端正在死亡,我已经修改了testing文件

 <?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'); ?> 

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

更新2

设置fastcgi_ignore_client_abort; 会将HTTP 499的响应更改为HTTP 200,尽pipe没有任何内容返回到最终客户端。

更新3

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

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

问题的原因是AWS上的弹性负载平衡器。 他们,默认情况下,超过60秒的不活动,这是导致问题。

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

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

我以为我会离开我的两分钱。 首先问题是与PHP无关(仍然可能是一个PHP相关,PHP总是让我感到惊讶:P)。 这是肯定的。 它主要是由一个服务器代理自己,更具体的主机名/别名名称问题,在你的情况下,它可能是负载平衡器正在请求nginx和nginx正在callback负载平衡器,并保持这样的方式。

我经历了与nginx 类似的问题作为负载平衡器和Apache作为networking服务器/代理

你需要find哪个地方存在问题。 我不知道确切的答案,只是让我们试着find答案。

我们在这里有3个元素:nginx,php-fpm,php。 正如你所说,在Apache下的相同的PHP设置是好的。 这是不是一样的设置? 你在相同的OS /主机/等尝试Apache而不是nginx?

如果我们将看到,这个PHP是不是怀疑,那么我们有两个嫌疑人:nginx和PHP-FPM。

要排除nginx:尝试在ruby上设置相同的“系统”。 看到https://github.com/garex/puppet-module-nginx得到想法安装最简单的ruby设置。; 或者使用谷歌(可能会更好)。

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

尝试玩这些设置:

  • php-fpm的request_terminate_timeout
  • nginx的fastcgi_ignore_client_abort

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