先週の終わりに、中規模のAWSインスタンスの1つで、リクエストに60秒以上かかる場合にNginxが常にHTTP499応答を返すという問題に気づきました。要求されているページはPHPスクリプトです
私は答えを見つけるために数日を費やし、ここStack Overflowのいくつかのエントリを含め、インターネットで見つけることができるすべてのものを試しましたが、何も機能しません。
PHP設定、PHP-FPM設定、Nginx設定を変更してみました。金曜日にNginXフォーラム(http://forum.nginx.org/read.php?9,237692)で私が提起した質問を見ることができますが、応答はありません。私がちょうどうまくいくことを知っているApacheに戻ることを余儀なくされる前に、ここで答えてください。
これは、他のエントリで報告されているHTTP500エラーと同じ問題ではありません。
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秒後にHTTP1.1499応答を受信することがわかります。
タイムアウトが表示されたので、これを回避するために、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_timeout300に追加します。
次に、前に作成したファイル/ 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;
最後に、サーバーディレクトリの場所〜.php$セクションに以下を追加します
fastcgi_read_timeout 360;
fastcgi_send_timeout 360;
fastcgi_connect_timeout 1200;
スクリプトを再試行する前に、nginxとphp-fpmの両方を起動して、新しい設定が取得されていることを確認してください。次に、ページにアクセスしてみても、NginXexample.error.log内のHTTP/1.1499エントリを受け取ります。
それで、私はどこで間違っているのですか?これは、PHPの最大実行時間を2分に設定した場合にapacheで機能します。
Webアクセス可能なページからphpinfo()を実行すると、PHP設定が取得されたことがわかります。PHPのmax_execution_time、default_socket_timeoutの変更、およびserver- > locationディレクティブ内の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をオンに設定します。エンドクライアントには何も返されませんが、応答はHTTP499からHTTP200に変更されます。
アップデート3
ApacheとPHP(5.3.10)をボックスに直接インストールして(aptを使用)、実行時間を長くすると、Apacheでも問題が発生するようです。症状は現在NginX、HTTP200応答と同じですが、実際のクライアント接続は事前にタイムアウトになります。
また、NginXログで、Firefoxを使用してテストすると、二重の要求が発生することに気付き始めました(たとえば、このPHPスクリプトは60秒を超えると2回実行されます)。それは、スクリプトが失敗したときにクライアントが要求しているように見えますが