NGINX: キュー内のクエリに対するリクエスト制限のタイムアウト動作 (バースト)

NGINX: キュー内のクエリに対するリクエスト制限のタイムアウト動作 (バースト)

現在、キューのサイズは 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 にはカウントされません。


負荷テストを実行する使用してアブまたは包囲

関連情報