尽管进行了配置,NginX 仍会在 60 秒后发出 HTTP 499 错误。(PHP 和 AWS)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15613452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NginX issues HTTP 499 error after 60 seconds despite config. (PHP and AWS)
提问by TFAtTheMoon
At the end of last week I noticed a problem on one of my medium AWS instances where Nginx always returns a HTTP 499 response if a request takes more than 60 seconds. The page being requested is a PHP script
上周末,我注意到我的一个中型 AWS 实例存在问题,如果请求超过 60 秒,Nginx 总是返回 HTTP 499 响应。被请求的页面是一个 PHP 脚本
I've spent several days trying to find answers and have tried everything that I can find on the internet including several entries here on Stack Overflow, nothing works.
我花了几天时间试图找到答案,并尝试了我可以在互联网上找到的所有内容,包括 Stack Overflow 上的几个条目,但没有任何效果。
I've tried modifying the PHP settings, PHP-FPM settings and Nginx settings. You can see a question I raised on the NginX forums on Friday (http://forum.nginx.org/read.php?9,237692) though that has received no response so I am hoping that I might be able to find an answer here before I am forced to moved back to Apache which I know just works.
我已经尝试修改 PHP 设置、PHP-FPM 设置和 Nginx 设置。你可以看到我周五在 NginX 论坛 ( http://forum.nginx.org/read.php?9,237692)上提出的一个问题,尽管没有得到任何回应,所以我希望我能找到一个在我被迫搬回 Apache 之前回答这里,我知道它可以正常工作。
This is notthe same problem as the HTTP 500 errors reported in other entries.
这是不相同的问题,因为HTTP 500错误在其他项目的报道。
I've been able to replicate the problem with a fresh micro AWS instance of NginX using PHP 5.4.11.
我已经能够通过使用 PHP 5.4.11 的 NginX 的新微型 AWS 实例来复制该问题。
To help anyone who wishes to see the problem in action I'm going to take you through the set-up I ran for the latest Micro test server.
为了帮助任何希望看到实际问题的人,我将带您完成我为最新的 Micro 测试服务器运行的设置。
You'll need to launch a new AWS Micro instance (so it's free) using the AMI ami-c1aaabb5
您需要使用 AMI ami-c1aaabb5 启动一个新的 AWS Micro 实例(因此它是免费的)
This PasteBin entry has the complete set-up to run to mirror my test environment. You'll just need to change example.comwithin the NginX config at the end
这个 PasteBin 条目具有完整的设置来运行以反映我的测试环境。最后你只需要在 NginX 配置中更改example.com
Once that's set-up you just need to create the sample PHP file which I am testing with which is
设置完成后,您只需要创建我正在测试的示例 PHP 文件
<?php
sleep(70);
die( 'Hello World' );
?>
Save that into the webroot and then test. If you run the script from the command line using php or php-cgi, it will work. If you access the script via a webpage and tail the access log /var/log/nginx/example.access.log, you will notice that you receive the HTTP 1.1 499 response after 60 seconds.
将其保存到 webroot 中,然后进行测试。如果您使用 php 或 php-cgi 从命令行运行脚本,它将起作用。如果您通过网页访问脚本并跟踪访问日志/var/log/nginx/example.access.log,您会注意到您在 60 秒后收到 HTTP 1.1 499 响应。
Now that you can see the timeout, I'll go through some of the config changes I've made to both PHP and NginX to try to get around this. For PHP I'll create several config files so that they can be easily disabled
现在您可以看到超时,我将通过我对 PHP 和 NginX 所做的一些配置更改来尝试解决这个问题。对于 PHP,我将创建几个配置文件,以便可以轻松禁用它们
Update the PHP FPM Config to include external config files
更新 PHP FPM 配置以包含外部配置文件
sudo echo '
include=/usr/local/php/php-fpm.d/*.conf
' >> /usr/local/php/etc/php-fpm.conf
Create a new PHP-FPM config to override the request timeout
创建一个新的 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
Change some of the global settings to ensure the emergency restart interval is 2 minutes
更改一些全局设置以确保紧急重启间隔为 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
Next, we will change some of the PHP.INI settings, again using separate files
接下来,我们将更改一些 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
As you can see, this is increasing the socket timeout to 3 minutes and will help log errors.
如您所见,这会将套接字超时增加到 3 分钟,并有助于记录错误。
Finally, I'll edit some of the NginX settings to increase the timeout's that side
最后,我将编辑一些 NginX 设置以增加该侧的超时
First I edit the file /etc/nginx/nginx.confand add this to the http directive fastcgi_read_timeout 300;
首先,我编辑文件/etc/nginx/nginx.conf并将其添加到 http 指令 fastcgi_read_timeout 300;
Next, I edit the file /etc/nginx/sites-enabled/examplewhich we created earlier (See the pastebin entry) and add the following settings into the serverdirective
接下来,我编辑我们之前创建的文件/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;
Finally I add the following into the location ~ .php$section of the server dir
最后,我将以下内容添加到服务器目录的location ~ .php$部分
fastcgi_read_timeout 360;
fastcgi_send_timeout 360;
fastcgi_connect_timeout 1200;
Before retrying the script, start both nginx and php-fpm to ensure that the new settings have been picked up. I then try accessing the page and still receive the HTTP/1.1 499 entry within the NginX example.error.log.
在重试脚本之前,启动 nginx 和 php-fpm 以确保已选择新设置。然后我尝试访问该页面,但仍然收到 NginX example.error.log 中的 HTTP/1.1 499 条目。
So, where am I going wrong? This just works on apache when I set PHP's max execution time to 2 minutes.
那么,我哪里出错了?当我将 PHP 的最大执行时间设置为 2 分钟时,这仅适用于 apache。
I can see that the PHP settings have been picked up by running phpinfo()from a web-accessible page. I just don't get, I actually think that too much has been increased as it should just need PHP's max_execution_time, default_socket_timeoutchanged as well as NginX's fastcgi_read_timeoutwithin just the server->location directive.
我可以看到 PHP 设置是通过从 Web 可访问的页面运行phpinfo()来获取的。我只是不明白,我实际上认为已经增加了太多,因为它只需要在 server->location 指令中更改PHP 的max_execution_time、default_socket_timeout以及 NginX 的fastcgi_read_timeout即可。
Update 1
更新 1
Having performed some further test to show that the problem is not that the client is dying I have modified the test file to be
执行了一些进一步的测试以表明问题不在于客户端正在死亡我已将测试文件修改为
<?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');
?>
If I run the script from a web page then I can see the content of the file be set to the first string. 60 seconds later the error appears in the NginX log. 10 seconds later the contents of the file changes to the 2nd string, proving that PHP is completing the process.
如果我从网页运行脚本,那么我可以看到文件的内容被设置为第一个字符串。60 秒后,错误出现在 NginX 日志中。10 秒后,文件内容变为第二个字符串,证明 PHP 正在完成该过程。
Update 2
更新 2
Setting fastcgi_ignore_client_abort on;does change the response from a HTTP 499 to a HTTP 200 though nothing is still returned to the end client.
将fastcgi_ignore_client_abort设置为开启;确实将响应从 HTTP 499 更改为 HTTP 200,但仍然没有任何内容返回给最终客户端。
Update 3
更新 3
Having installed Apache and PHP (5.3.10) onto the box straight (using apt) and then increasing the execution time the problem does appear to also happen on Apache as well. The symptoms are the same as NginX now, a HTTP200 response but the actual client connection times out before hand.
将 Apache 和 PHP (5.3.10) 直接安装到盒子上(使用 apt)然后增加执行时间,这个问题似乎也发生在 Apache 上。现在的症状与 NginX 相同,是 HTTP200 响应,但实际客户端连接提前超时。
I've also started to notice, in the NginX logs, that if I test using Firefox, it makes a double request (like this PHP script executes twice when longer than 60 seconds). Though that does appear to be the client requesting upon the script failing
我也开始注意到,在 NginX 日志中,如果我使用 Firefox 进行测试,它会发出双重请求(就像这个PHP 脚本在超过 60 秒时执行两次)。虽然这似乎是客户端在脚本失败时提出请求
回答by TFAtTheMoon
The cause of the problem is the Elastic Load Balancers on AWS. They, by default, timeout after 60 seconds of inactivity which is what was causing the problem.
问题的原因是 AWS 上的弹性负载均衡器。默认情况下,它们在 60 秒不活动后超时,这就是导致问题的原因。
So it wasn't NginX, PHP-FPM or PHP but the load balancer.
所以它不是 NginX、PHP-FPM 或 PHP,而是负载均衡器。
To fix this, simply go into the ELB "Description" tab, scroll to the bottom, and click the "(Edit)" link beside the value that says "Idle Timeout: 60 seconds"
要解决此问题,只需进入 ELB“描述”选项卡,滚动到底部,然后单击“空闲超时:60 秒”值旁边的“(编辑)”链接
回答by Waheed
I thought I would leave my two cents. First the problem is not related with php(still could be a php related, php always surprises me :P ). Thats for sure. its mainly caused of a server proxied to itself, more specifically hostname/aliases names issue, in your case it could be the load balancer is requesting nginx and nginx is calling back the load balancer and it keeps going that way.
我以为我会留下我的两分钱。首先,问题与 php 无关(仍然可能与 php 相关,php 总是让我感到惊讶 :P )。这是肯定的。它主要是由代理到自身的服务器引起的,更具体地说是主机名/别名问题,在您的情况下,可能是负载均衡器正在请求 nginx,而 nginx 正在回调负载均衡器,并且它一直在以这种方式运行。
I have experienced a similarissue with nginx as the load balancer and apache as the webserver/proxy
我遇到了类似的问题,nginx 作为负载平衡器,apache 作为网络服务器/代理
回答by Rajeev kumar
Actually I faced the same issue on one server and I figured out that after nginx configuration changes I didn't restart the nginx server, so with every hit of nginx url I was getting a 499 http response. After nginx restart it started working properly with http 200 responses.
实际上我在一台服务器上遇到了同样的问题,我发现在 nginx 配置更改后我没有重新启动 nginx 服务器,所以每次点击 nginx url 我都会收到 499 http 响应。nginx 重新启动后,它开始正常工作,并收到 http 200 响应。
回答by Souvik Ray
Not sure if anyone else faced this but for me it happened after I put a /
at the end my instance url.This gave 499error and only after I removed the /
, it gave me 200 and all went good.
不知道是否还有其他人遇到过这个问题,但对我来说,这是在我将/
实例 url放在末尾之后发生的。这给出了499错误,只有在我删除 之后/
,它才给了我 200 并且一切顺利。
回答by gaRex
You need to find in which place problem live. I dont' know exact answer, but just let's try to find it.
您需要找到问题所在的地方。我不知道确切的答案,但让我们试着找到它。
We have here 3 elements: nginx, php-fpm, php. As you told, same php settings under apache is ok. Does it's same no same setup? Did you try apache instead of nginx on same OS/host/etc.?
我们这里有 3 个元素:nginx、php-fpm、php。正如您所说,apache 下的相同 php 设置是可以的。不一样的设置是一样的吗?您是否在同一操作系统/主机/等上尝试过 apache 而不是 nginx?
If we will see, that php is not suspect, then we have two suspects: nginx & php-fpm.
如果我们会看到,那个 php 不是可疑的,那么我们有两个嫌疑人:nginx 和 php-fpm。
To exclude nginx: try to setup same "system" on ruby. See https://github.com/garex/puppet-module-nginxto get idea to install simplest ruby setup. Or use google (may be it will be even better).
要排除 nginx:尝试在 ruby 上设置相同的“系统”。请参阅https://github.com/garex/puppet-module-nginx以了解安装最简单的 ruby 设置。或者使用谷歌(可能会更好)。
My main suspect here is php-fpm.
我的主要嫌疑人是 php-fpm。
Try to play with these settings:
尝试使用这些设置:
- php-fpm`s request_terminate_timeout
- nginx`s fastcgi_ignore_client_abort
- php-fpm 的 request_terminate_timeout
- nginx 的 fastcgi_ignore_client_abort