web-dev-qa-db-ja.com

Nginx With PHP FPM-リソースが一時的に利用不可-502エラー

Nginx With PHP FPM-リソースが一時的に利用不可-502エラー

私はいくつかのコードを使用して160を超えるGETリクエストを送信します 非同期でcurlを使用して Ubuntuサーバー16.04でPhp-fpmを使用してNginxを実行しているAPIに送信します。各リクエストは、データベースからさまざまなデータをフェッチしてから、JSONレスポンスとして返します。このリクエストの数は十分に少ないので、さまざまなデフォルト制限(ソケット接続の数、ファイル記述子など)に到達しないはずです。ただし、それらがすべて同時に送信/受信されるという事実が問題を引き起こしているようです。

リクエストの大部分は成功しますが、いくつか(連続したテストでは一貫して同じ数ですが、構成によって異なります)は「502 Bad Gateway」応答。

Nginxエラーログ(/var/log/nginx/error.log)を見ると、次のエラーメッセージが表示されます。

2017/11/21 09:46:43 [error] 29#29: *144 connect() to unix:/run/php/php7.0-fpm.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 192.168.3.7, server: , request: "GET /1.0/xxx HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock:", Host: "my.domain.org"

APIから返されたログの「502 Bad Gateway」エラーメッセージの数は、常に正確に同じです。

一方、テストの実行中に(tail -100f /var/log/php7.0-fpm.logを使用して)fpmログファイルを監視すると、何も起こりません。次のものがあります。

[21-Nov-2017 11:54:29] NOTICE: fpm is running, pid 329
[21-Nov-2017 11:54:29] NOTICE: ready to handle connections
[21-Nov-2017 11:54:29] NOTICE: systemd monitor interval set to 10000ms

私のfpm構成(/etc/php/7.0/fpm/php-fpm.confで)はerror_log = /var/log/php7.0-fpm.logのエラーログを指定していますが、そのようなファイルは表示されていないため、エラーはありません。

動作する構成

Fpm構成を微調整した場合、/etc/php/7.0/fpm/pool.d/www.confファイルをstatic数の15スレッドを使用するように構成すると、Webサーバーを機能させることができます(502エラーなし)。プロセスを動的に生成したり、静的プロセスの数を減らしたりするのではありません。

pm = static
pm.max_children = 15

これは、突然のヒットに対応するための準備ができているスレッドがすでに十分にあり、スレッドの生成またはシャットダウンに遅延が発生しないため、うまくいくと思います。ただし、これは私のWebサーバーが必要以上のメモリを使用することを意味します。理想的には、pm.max_childrenは、サーバー上のvCPUの数の2倍(つまり8以下)に等しい数にしたいです。この場合、クアッドコアサーバーを使用していますが、デュアルコアインスタンスにdownしたい場合があります。理想的には、サーバーがall時間内に要求に応じて合計時間がはるかに長い場合でも、すべての要求に応答します。キューとタイムアウトの調整。

構成設定

デフォルトのphp-fpm listen.backlog値は511ですが、ファクターから除外するために2000に設定しています。 listen.backlog = 2000

Nginxの場合、1024 worker_connectionsworker_processes auto;を設定したので、4になるはずです。

また、次のバッファとタイムアウトの設定を使用して、それらが要因になるのを防ぎます。

##
# Buffere settings
##
client_body_buffer_size 10M;
client_header_buffer_size 1k;
client_max_body_size 512m;
large_client_header_buffers 2 1k;


##
# Timeout settings
##
client_body_timeout 120;
client_header_timeout 120;
keepalive_timeout 120;
send_timeout 120;
fastcgi_connect_timeout 60s;
fastcgi_next_upstream_timeout 40s;
fastcgi_next_upstream_tries 10;
fastcgi_read_timeout 60s;
fastcgi_send_timeout 60s;
fastcgi_cache_lock_timeout 60s;

すべてのリクエスト(502を含む)が約20秒で取得されるため、これらのリクエストには到達しないことに注意してください。また、fastcgi_next_upstream_triesが10に設定されている場合でも、502エラーメッセージごとに1つのリソース使用不可メッセージしか取得されません。

類似/関連する質問

Serverfaultとスタックオーバーフローに関する同様の質問がたくさんあるようです。ここではそれらを詳しく説明しているので、この質問は重複としてマークされません。

Nginxが提供するエラーメッセージで、ソケットファイルと整列しているのを確認できます。

質問

を信じるNginxは、PHP-fpm側が処理するには速すぎる。ある時点でfpmはnginxリクエストに応答しないだけなので、nginxはあきらめて502エラーを返します。 fpmがリクエストをキューに入れるか、nginxが後で再試行するようにこれを修正する方法(おそらく構成変数または2つ)はありますか(fastcgi_next_upstream_triesは効果がないようです)?どのようにlongWebサーバーがすべてのリクエストを処理する(タイムアウトを増やす)かは問題ではありません。プロセスのfpm数を適切な数に設定できます。私のCPU、そしてこれらすべての160リクエストが処理されます。

更新-TCPソケットを使用して正常に動作する

私はちょうどFPMをunixファイルソケットでリッスンすることからTCPソケットの詳細 ここ に)スワップすることを試みました。

例えば。 fpmをListen 127.0.0.1:9000に変更し、nginxを使用するように更新:fastcgi_pass 127.0.0.1:9000;

これは回避策としてトリックを行ったようです。例えば。動的プールまたは2 fpmスレッドのみの静的プールを使用しても、502エラーは発生しません。

ただし、これがローカルのUNIXファイルソケットを使用する代わりに機能する理由と、ファイルソケットベースのソリューションが機能するように構成を変更できるかどうかが知りたいです。使用する。

3
Programster

ngx_http_limit_req_module を使用してそれを達成し、数値を目的のr/sに構成し、バーストを使用してキューサイズを設定すると、次のような構成でできると思います。

limit_req_zone $binary_remote_addr zone=php:10m rate=2r/s;

server {
    location ~ \.php$ {
        limit_req zone=php burst=10;
    }

この例では、平均して1秒あたり2つのリクエストを許可し、3番目から10番目のリクエスト(ある場合)をキューに入れます。 r/sが10を超える場合は503エラーが返されます(limit_req_status

1
ProT-0-TypE