.png)
現在、キューのサイズは 3000 リクエストです。
location /api/v2 {
limit_req zone=bursted burst=3000;
include /etc/nginx/proxy.conf;
}
レート制限は 1 秒あたり 10 リクエストです。
limit_req_zone $limit zone=api_slow:10m rate=1r/s;
limit_req_zone $server_name zone=bursted:10m rate=10r/s;
キープアライブ タイムアウトは 30 秒です。つまり、キューがいっぱいになると、30 秒ごとに 2700 件のリクエストがエラー コード 408 で拒否されることになります。
reset_timedout_connection on;
client_body_timeout 10;
send_timeout 2;
keepalive_timeout 30;
ラッシュアワー時には、リクエストがサーブレット コンテナへの転送をキューで待機している間に、タイムアウトが原因で NGINX によってエラー コード 408 で拒否されたリクエストがログに見つかりませんでした。リクエスト レートのオーバーヘッドに対応する 503 エラー コードでのみ拒否されます。
delaying request, excess: 2958.320, by zone "bursted"
limiting requests, excess: 3000.730 by zone "bursted"
NGINX は、このようなキュー内のリクエストが長時間ハングした場合、タイムアウトによってリクエストを拒否しますか? このタイムアウトとは何ですか? その設定はどこにありますか?
答え1
nginxのレート制限とタイムアウトの仕組みについて、少し混乱があるようです。タイムアウトレート制限用です。レートとキューのサイズを設定するだけです。レートを超えるリクエストはキューに追加され、後で処理されます。キューが完全にいっぱいになると、追加のリクエストは 503 ステータス コードで拒否されます。
あなたの例ではレートを 1 秒あたり 10 リクエスト (10r/s)、バースト サイズを 3000、ゾーンを 10 メガバイトのサイズで「バースト」するように設定しました。このレート制限は、定義されたサーバーごとに個別のカウントとして適用されます。
つまり、サーバーは 0.1 秒ごとに 1 つのリクエストを受け入れて処理し、最大 3000 の超過リクエストをキューに入れることができ、その後、定義された速度 (0.1 秒ごとに 1 つ) で処理されます。また、バースト ゾーンには約 160,000 個の IP アドレスを保存できます。
つまり3011 のリクエストが 1 秒以内に到着すると、nginx は最初の 10 のリクエストをすぐに処理し、別の 3000 のリクエストをキューに入れ、3011 番目のリクエストは 503 ステータス コードで拒否されます。キューは、0.1 秒ごとに 1 つのリクエストという定義されたレートで処理されます。新しいリクエストが到着しない限り、キューは短くなり、新しいリクエストを再びキューに追加できます。ただし、キューがすでに 3000 のリクエストを保持している間は、追加のリクエストはすべて 503 ステータス コードで拒否されます。
バースト キューのこの動作による線形処理により、サイトが遅く見える場合があります。これを防ぐには、nodelay
にパラメータを追加しますlimit_req zone=bursted burst=3000 nodelay;
。これにより、バースト キューからのすべてのリクエストが即時に処理され、キュー内のスロットが「取得済み」としてマークされ、その後、定義されたレートでスロットごとに再び「解放」されるため、時間の経過とともに定義されたレート制限が満たされます。
limit_req_status 444;
ところで: 設定ブロックに追加することで、拒否されたリクエストのステータス コードを 503 から 444 に変更できますhttp
。
詳細については以下を参照してください。
設定からの2つのタイムアウト:
リクエスト後、クライアント本体が送信されるまでサーバーclient_body_timeout 10;
は最大 10 秒間待機します。この時間内にクライアントから本体が送信されない場合、サーバーは 408 ステータス コードで接続を閉じます。
これkeepalive_timeout 30;
により、サーバーは 30 秒後にまだ開いているクライアントへの接続をすべて閉じます。ただし、私のテストによると、リクエストがバースト キューで待機している時間は keepalive_timeout にはカウントされません。