57

先週の終わりに、中規模の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を変更する必要があります

http://pastebin.com/WQX4AqEU

それが設定されたら、私がテストしているサンプル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_timedefault_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回実行されます)。それは、スクリプトが失敗したときにクライアントが要求しているように見えますが

4

6 に答える 6

80

問題の原因は、AWSのElasticLoadBalancerです。デフォルトでは、60秒間非アクティブになるとタイムアウトになり、これが問題の原因でした。

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

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

于 2013-03-25T17:37:28.930 に答える
1

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

ロードバランサーとしてのnginxとウェブサーバー/プロキシとしてのApacheで同様の問題が発生しました

于 2016-03-09T16:13:34.693 に答える
1

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

于 2016-10-18T10:18:12.677 に答える
0

私の場合、nginxはAWS ALBにリクエストを送信し、499ステータスコードでタイムアウトを取得していました。

解決策は、次の行を追加することでした。

proxy_next_upstream off;

nginxの現在のバージョンでのこれのデフォルト値はproxy_next_upstream error timeout;-タイムアウト時に次の「サーバー」を試行することを意味します-ALBの場合、解決されたIPのリストの次のIPです。

于 2021-10-18T14:18:18.887 に答える
-1

問題がどこにあるかを見つける必要があります。正確な答えはわかりませんが、見つけてみましょう。

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

phpが疑わしくないことがわかる場合は、nginxとphp-fpmの2つの容疑者がいます。

nginxを除外するには:rubyで同じ「システム」をセットアップしてみてください。最も簡単なrubyセットアップをインストールするためのアイデアを得るには、 https://github.com/garex/puppet-module-nginxを参照してください。またはグーグルを使用してください(それはさらに良いかもしれません)。

ここでの私の主な容疑者はphp-fpmです。

次の設定で遊んでみてください。

  • php-fpm`s request_terminate_timeout
  • nginxのfastcgi_ignore_client_abort
于 2013-03-25T14:18:58.610 に答える
-3

他の誰かがこれに直面したかどうかはわかりませんが、私にとっては/、インスタンスのURLを最後に付けた後に発生しました。これにより499エラーが発生し、を削除した後にのみ/200が発生し、すべてうまくいきました。

于 2018-04-04T07:24:11.677 に答える