先週の終わりに、リクエストが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を変更するだけです
セットアップが完了したら、サンプルを作成する必要があります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_time、default_socket_timeoutが変更され、NginXのfastcgi_read_timeoutが必要になるだけなので、実際にはあまりにも多くなりすぎていると思います。 ->ロケーションディレクティブ。
問題がクライアントが死にかけているということではないことを示すために、さらにテストを実行して、テストファイルを次のように変更しました。
<?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がプロセスを完了していることが証明されます。
fastcgi_ignore_client_abort on;を設定すると、応答はHTTP 499からHTTP 200に変更されますが、エンドクライアントには何も返されません。
ApacheとPHP(5.3.10))をボックスに(aptを使用して)まっすぐにインストールし、実行時間を長くすると、問題はApacheでも発生するように見えます。症状は同じです。現在のNginXのように、HTTP200応答ですが、実際のクライアント接続は事前にタイムアウトします。
また、NginXログで、Firefoxを使用してテストすると、2回のリクエストが行われることに気付き始めました(このように 60秒を超えるとPHPスクリプトが2回実行されます )。それはスクリプトが失敗したときにクライアントが要求しているように見えますが
問題の原因は、AWS上のElastic Load Balancerです。デフォルトでは、それらは問題の原因となっている60秒間の非アクティブ後にタイムアウトします。
そのため、NginX、PHP-FPM、またはPHPではなく、ロードバランサーでした。
これを修正するには、ELBの「説明」タブに移動し、一番下までスクロールして、「アイドルタイムアウト:60秒」という値の横にある「(編集)」リンクをクリックします。
私は2セントを残すと思った。最初に、問題はphpに関連していません(まだphpに関連している可能性がありますが、phpは常に私を驚かせます:P)。それは確かだ。その主な原因は、それ自体にプロキシされたサーバー、より具体的にはホスト名/エイリアス名の問題です。あなたの場合、ロードバランサーがnginxを要求していて、nginxがロードバランサーをコールバックしている可能性があります。
ロードバランサーとしてのnginxとWebサーバー/プロキシとしてのApacheでsimilarの問題が発生しました
他の誰かがこれに直面したかどうかはわかりませんが、私にとっては/
最後に私のインスタンスのURL。これは499エラーを与え、/
、それは私に200を与え、すべてがうまくいった。
実際、1つのサーバーで同じ問題に直面し、nginxの構成を変更した後、nginxサーバーを再起動しなかったため、nginx urlがヒットするたびに499のHTTP応答が返ってきました。 nginxを再起動すると、http 200応答で正常に動作し始めました。
問題が発生している場所を見つける必要があります。正確な答えはわかりませんが、見つけてみましょう。
ここには、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です。
これらの設定で遊んでみてください: