web-dev-qa-db-ja.com

NginXは、設定にもかかわらず60秒後にHTTP 499エラーを発行します。 (PHPおよびAWS)

先週の終わりに、リクエストが60秒以上かかるとNginxが常にHTTP 499応答を返すという、中規模のAWSインスタンスの1つで問題に気付きました。要求されているページはPHPスクリプトです

私は答えを見つけるために数日を費やし、スタックオーバーフローに関するいくつかのエントリを含むインターネットで見つけることができるすべてを試しましたが、何も機能しません。

PHP設定、PHP-FPM設定、およびNginx設定を変更しようとしました。金曜日にNginXフォーラムで提起した質問を見ることができます( http:// forum。 nginx.org/read.php?9,237692 )応答がありませんが、Apacheに戻ることを余儀なくされる前に、ここで答えを見つけられることを望んでいます。

これは、他のエントリで報告されるHTTP 500エラーと同じ問題ではありません

PHP 5.4.11。を使用して、NginXの新しいマイクロAWSインスタンスで問題を再現することができました。

問題の実際の動作を確認したい人を支援するために、最新のマイクロテストサーバー用に実行したセットアップについて説明します。

AMI ami-c1aaabb5を使用して、新しいAWS Microインスタンスを起動する必要があります(無料です)。

このPastebinエントリには、テスト環境をミラーリングするために実行する完全なセットアップが含まれています。変更する必要があるのは、最後にNginX構成内でexample.comを変更するだけです

http://Pastebin.com/WQX4AqE

セットアップが完了したら、サンプルを作成する必要がありますPHP

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

それをwebrootに保存してからテストします。 phpまたはphp-cgiを使用してコマンドラインからスクリプトを実行すると、動作します。 Webページを介してスクリプトにアクセスし、アクセスログの末尾を/ var/log/nginx/example.access.logにすると、60秒後にHTTP 1.1 499応答を受け取ることに気付くでしょう。

タイムアウトを確認できたので、これを回避するためにPHPとNginXの両方に行った設定の変更をいくつか行います。ForPHP簡単に無効にできるように、いくつかの設定ファイルを作成します

PHP FPM Configを更新して外部構成ファイルを含める

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エントリを参照)、次の設定をserverディレクティブ

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

問題がクライアントが死にかけているということではないことを示すために、さらにテストを実行して、テストファイルを次のように変更しました。

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

Webページからスクリプトを実行すると、ファイルのコンテンツが最初の文字列に設定されていることがわかります。 60秒後、NginXログにエラーが表示されます。 10秒後にファイルの内容が2番目の文字列に変更され、PHPがプロセスを完了していることが証明されます。

更新2

fastcgi_ignore_client_abort on;を設定すると、応答はHTTP 499からHTTP 200に変更されますが、エンドクライアントには何も返されません。

アップデート3

ApacheとPHP(5.3.10))をボックスに(aptを使用して)まっすぐにインストールし、実行時間を長くすると、問題はApacheでも発生するように見えます。症状は同じです。現在のNginXのように、HTTP200応答ですが、実際のクライアント接続は事前にタイムアウトします。

また、NginXログで、Firefoxを使用してテストすると、2回のリクエストが行われることに気付き始めました(このように 60秒を超えるとPHPスクリプトが2回実行されます )。それはスクリプトが失敗したときにクライアントが要求しているように見えますが

53
TFAtTheMoon

問題の原因は、AWS上のElastic Load Balancerです。デフォルトでは、それらは問題の原因となっている60秒間の非アクティブ後にタイムアウトします。

そのため、NginX、PHP-FPM、またはPHPではなく、ロードバランサーでした。

これを修正するには、ELBの「説明」タブに移動し、一番下までスクロールして、「アイドルタイムアウト:60秒」という値の横にある「(編集)」リンクをクリックします。

61
TFAtTheMoon

私は2セントを残すと思った。最初に、問題はphpに関連していません(まだphpに関連している可能性がありますが、phpは常に私を驚かせます:P)。それは確かだ。その主な原因は、それ自体にプロキシされたサーバー、より具体的にはホスト名/エイリアス名の問題です。あなたの場合、ロードバランサーがnginxを要求していて、nginxがロードバランサーをコールバックしている可能性があります。

ロードバランサーとしてのnginxとWebサーバー/プロキシとしてのApacheでsimilarの問題が発生しました

1
Waheed

他の誰かがこれに直面したかどうかはわかりませんが、私にとっては/最後に私のインスタンスのURL。これは499エラーを与え、/、それは私に200を与え、すべてがうまくいった。

0
Souvik Ray

実際、1つのサーバーで同じ問題に直面し、nginxの構成を変更した後、nginxサーバーを再起動しなかったため、nginx urlがヒットするたびに499のHTTP応答が返ってきました。 nginxを再起動すると、http 200応答で正常に動作し始めました。

0
Rajeev kumar

問題が発生している場所を見つける必要があります。正確な答えはわかりませんが、見つけてみましょう。

ここには、nginx、php-fpm、phpの3つの要素があります。あなたが言ったように、Apacheの下で同じPHP設定はOKです。同じ設定でも同じですか?同じOS /ホスト/などでnginxの代わりにApacheを試しましたか?

Phpが疑わない場合は、nginxとphp-fpmの2つの容疑者がいます。

Nginxを除外するには:Rubyで同じ「システム」をセットアップしてください。 https://github.com/garex/puppet-module-nginx を参照して、最も単純なRuby setup。またはgoogleを使用してください。さらに良い)。

ここでの主な疑いはphp-fpmです。

これらの設定で遊んでみてください:

  • php-fpmのrequest_terminate_timeout
  • nginxのfastcgi_ignore_client_abort
0
gaRex