私はいくつかのコードを使用して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_connections
とworker_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とスタックオーバーフローに関する同様の質問がたくさんあるようです。ここではそれらを詳しく説明しているので、この質問は重複としてマークされません。
Serverfault-NginxおよびPHP-FPMを使用したpm.max_childrenの後に要求がキューに入れられることはありません 。非常によく似た質問のように見えますが、3年前に投稿されたにもかかわらず回答はなく、詳細はここよりもはるかに少なくなっています。また、私のリクエストの一部は、最大数に達するとすぐにすべてのリクエストがドロップされることを示唆する質問とは異なり、正常にキューに入れられている必要があります。
ServerFault-nginx ERROR 502&リソースは一時的に利用不可)アップストリーム、クライアントに接続中 。この投稿は似ているようですが(彼は同じ問題について説明しています)、答えの1つが指摘したように、彼のソケットファイルは一致していませんでした。私の/etc/php/7.0/fpm/pool.d/www.conf
設定ファイルには以下が含まれています:
listen = /run/php/php7.0-fpm.sock
Nginxが提供するエラーメッセージで、ソケットファイルと整列しているのを確認できます。
ServerFault-上流のUNIXソケットへのnginxスループットを増やす必要がある— Linuxカーネルのチューニング? ここでの答えは、net.core.somaxconn
とnet.core.netdev_max_backlog
を設定することをお勧めします。問題はまだ解決しません。
ServerFault-php-fpm.sockが失敗しました(11:リソースは一時的に使用不可)アップストリームへの接続中 -ここでの提案は、pm = ondemandを設定し、max_childrenを4000に設定することです。これは私には適していません。その結果、クアッドコアサーバーに4000のスレッドが存在し、メモリを消費する可能性があります。
私を信じるNginxは、PHP-fpm側が処理するには速すぎる。ある時点でfpmはnginxリクエストに応答しないだけなので、nginxはあきらめて502エラーを返します。 fpmがリクエストをキューに入れるか、nginxが後で再試行するようにこれを修正する方法(おそらく構成変数または2つ)はありますか(fastcgi_next_upstream_tries
は効果がないようです)?どのようにlongWebサーバーがすべてのリクエストを処理する(タイムアウトを増やす)かは問題ではありません。プロセスのfpm数を適切な数に設定できます。私のCPU、そしてこれらすべての160リクエストが処理されます。
私はちょうどFPMをunixファイルソケットでリッスンすることからTCPソケットの詳細 ここ に)スワップすることを試みました。
例えば。 fpmをListen 127.0.0.1:9000
に変更し、nginxを使用するように更新:fastcgi_pass 127.0.0.1:9000;
これは回避策としてトリックを行ったようです。例えば。動的プールまたは2 fpmスレッドのみの静的プールを使用しても、502エラーは発生しません。
ただし、これがローカルのUNIXファイルソケットを使用する代わりに機能する理由と、ファイルソケットベースのソリューションが機能するように構成を変更できるかどうかが知りたいです。使用する。
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
)