nginxリバースプロキシを使用するときに長時間接続を維持する方法

nginxリバースプロキシを使用するときに長時間接続を維持する方法

・【シーン説明】

HTTP1.1 以降、HTTP プロトコルは永続的な接続 (長い接続とも呼ばれます) をサポートします。その利点は、複数の HTTP 要求と応答を 1 つの TCP 接続で送信できるため、接続の確立と終了にかかる消費量と遅延が削減されることです。

nginx をリバース プロキシまたはロード バランサーとして使用すると、クライアントからの長い接続要求は短い接続に変換され、サーバーに送信されます。

長い接続をサポートするには、nginx サーバーでいくつかの設定を行う必要があります。

・【必要とする】

nginx を使用する場合、長い接続を実現したい場合は、次の 2 つのことを実行する必要があります。

  • クライアントからnginxへの接続は長い
  • nginxからサーバーへの接続は長い

クライアントにとって、nginx は実際にはサーバーの役割を果たします。逆に、サーバーにとって、nginx はクライアントです。

[クライアントとの長期的な関係を維持する]

クライアントと Nginx 間の接続を長時間維持したい場合は、次の操作が必要です。

  • クライアントから送信されたリクエストには、「keep-alive」ヘッダーが含まれます。
  • Nginx設定はキープアライブをサポート

HTTP 構成

デフォルトでは、nginx はクライアント接続の keepalive サポートを有効にしています。特別なシナリオでは、関連するパラメータを調整できます。

http {

keepalive_timeout 120s; #クライアント接続タイムアウト。 0 の場合、長時間接続は無効になります。

keepalive_requests 10000; #長い接続で処理できるリクエストの最大数。

                         #リクエストの最大数に達し、既存のリクエストがすべて完了すると、接続は閉じられます。

                         #デフォルト値は100です

}

ほとんどの場合、keepalive_requests = 100 で十分ですが、QPS が高いシナリオでは、多数の接続が生成されて放棄されるのを防ぎ、TIME_WAIT を減らすために、このパラメータを増やす必要があります。

QPS=10000 の場合、クライアントは 1 秒あたり 10,000 件のリクエストを送信し (通常は複数の長い接続を確立します)、各接続は最大 100 件のリクエストしか実行できません。つまり、平均して 1 秒あたり 100 件の長い接続が nginx によって閉じられることになります。

これは、QPS を維持するために、クライアントが 1 秒あたり 100 の接続を再確立する必要があることも意味します。

したがって、netstat コマンドを使用してクライアント マシンを表示すると、多数の TIME_WAIT ソケット接続が見つかります (クライアントと NGINX の間でキープアライブがすでに有効になっている場合でも)。

[サーバーとの接続を長時間維持する]

Nginx とサーバー間の永続的な接続を維持するための最も簡単な設定は次のとおりです。

http {

アップストリームバックエンド{

  サーバー 192.168.0.1:8080 重み=1 max_fails=2 fail_timeout=30s;

  サーバー 192.168.0.2:8080 重み=1 max_fails=2 fail_timeout=30s;

  keepalive 300; // これは重要です!

}

   サーバー{

8080 default_server をリッスンします。

サーバー名 "";



   位置 / {

proxy_pass http://backend;

proxy_http_version 1.1; # http バージョンを 1.1 に設定

proxy_set_header Connection ""; # 接続を長い接続に設定します (デフォルトは no)}

}

}

}

【上流構成】

アップストリームには、特に重要なパラメータである keepalive があります。

このパラメータは、以前の http の keepalive_timeout とは異なります。

このパラメータの意味は、接続プール内のアイドル接続の最大数です。

分かりませんか?それは問題ではありません。例を見てみましょう。

シナリオ:

応答時間が 100 ミリ秒のアップストリーム サーバーとしてリクエストを受信する HTTP サービスがあります。

10,000 QPS のパフォーマンスを達成するには、nginx とアップストリーム サーバーの間で約 1,000 件の HTTP リクエストを確立する必要があります。 (1000/0.1秒=10000)

最良のケース:

リクエストが非常に均一かつ安定していると仮定すると、各リクエストには 100 ミリ秒かかり、リクエストはすぐに接続プールに配置され、アイドル状態に設定されます。

単位として 0.1 秒を使用します。

1. キープアライブ値を10に設定し、0.1秒ごとに1000接続します。

2. 0.1秒で合計1,000件のリクエストを受信して​​リリースしました

3. 0.2 秒後に、さらに 1,000 件のリクエストを受信し、0.2 秒後に解放されました。

リクエストとレスポンスは比較的均一で、0.1 秒ごとに解放される接続で十分であり、新しい接続を確立する必要はなく、接続プールにアイドル接続はありません。

最初のケース:

応答は非常に安定しているが、リクエストは安定していない

4. 0.3秒では、500件のリクエストしか受信できず、ネットワークの遅延などの理由で500件のリクエストが受信されなかった。

このとき、Nginx は接続プールに 500 個のアイドル接続があることを検出するため、(500-10) 個の接続を直接閉じます。

5. 0.4 秒時点で 1500 件のリクエストを受信しましたが、プールには (500+10) 件の接続しかないため、Nginx は (1500-510) 件の接続を再確立する必要があります。

手順 4 で 490 個の接続が閉じられていない場合は、500 個の接続のみを再確立する必要があります。

2番目のケース:

リクエストは非常に安定しているが、レスポンスが安定していない場合

4. 0.3秒で合計1500件のリクエストを受け取りました

しかし、プールには1000の接続しかありません。この時点で、Nginxはさらに500の接続を作成し、合計1500の接続を作成します。

5. 0.3秒ですべての接続が解放され、500件のリクエストを受信しました。

Nginx はプール内に 1000 個のアイドル接続があることを検出したため、(1000-10) 個の接続を解放する必要がありました。

接続数が繰り返し変動する理由の 1 つは、keepalive によって設定されたアイドル接続の最大数です。

上記の 2 つの状況は、不合理なキープアライブ設定によるもので、Nginx が接続を複数回解放および作成し、リソースが浪費される原因となります。

特に QPS 要件が高いシナリオやネットワーク環境が不安定なシナリオでは、keepalive パラメータを設定する際に注意してください。通常、必要な長い接続の数は、QPS 値と平均応答時間に基づいて大まかに見積もることができます。

次に、キープアライブ値を永続的な接続数の 10% ~ 30% に設定します。

【ロケーション構成】

http {

サーバー{

位置 / {

proxy_pass http://backend;

proxy_http_version 1.1; # http バージョンを 1.1 に設定

proxy_set_header Connection ""; # 接続を長い接続に設定します (デフォルトは no)

}

}

}

HTTP プロトコルでの永続的な接続のサポートはバージョン 1.1 以降でのみ利用可能であるため、proxy_http_version ディレクティブを 1.1 に設定するのが最適です。

HTTP1.0 はキープアライブ機能をサポートしていません。HTTP1.1 が使用されていない場合、バックエンド サービスは 101 エラーを返して切断します。

「Connection」ヘッダーをクリーンアップできるため、クライアントと Nginx 間の接続が短い場合でも、Nginx とアップストリーム間で長い接続を開くことができます。

[もう一つの高度な方法]

http {

マップ $http_upgrade $connection_upgrade {

デフォルトのアップグレード。

'' 近い;

}

   アップストリームバックエンド{

サーバー 192.168.0.1:8080 重み=1 max_fails=2 fail_timeout=30s;

サーバー 192.168.0.2:8080 重み=1 max_fails=2 fail_timeout=30s;

キープアライブ300;

}

   サーバー{

8080 default_server をリッスンします。

サーバー名 "";

位置 / {

proxy_pass http://backend;



   proxy_connect_timeout 15; #上流サーバーとの接続タイムアウト (単位なし、最大値は 75 秒を超えることはできません)

proxy_read_timeout 60s; #nginx がリクエストへの応答を受け取るまで待機する時間 proxy_send_timeout 12s; #上流サーバーにリクエストを送信する際のタイムアウト

   プロキシ_http_バージョン 1.1;

proxy_set_header アップグレード $http_upgrade;

proxy_set_header 接続 $connection_upgrade;

}

}

}

http における map の機能は次のとおりです。

プロキシ サーバーに転送される「Connection」ヘッダー フィールドの値が、クライアント要求ヘッダーの「Upgrade」フィールドの値に依存するようにします。

$http_upgrade が一致しない場合は、「Connection」ヘッダー フィールドの値はアップグレードされます。

$http_upgrade が空の文字列の場合、「Connection」ヘッダー フィールドの値は閉じます。

【補充】

NGINX は WebSocket をサポートしています。

NGINX がクライアントからバックエンド サーバーにアップグレード要求を送信するには、Upgrade ヘッダーと Connection ヘッダーを明示的に設定する必要があります。

これは、上記の状況では非常に一般的なシナリオでもあります。

HTTP アップグレード プロトコル ヘッダー メカニズムは、接続を HTTP 接続から WebSocket 接続にアップグレードするために使用されます。アップグレード メカニズムでは、アップグレード プロトコル ヘッダーと接続プロトコル ヘッダーが使用されます。

Nginx がクライアントからバックエンド サーバーにアップグレード要求を送信するには、Upgrade ヘッダーと Connection ヘッダーを明示的に設定する必要があります。

【知らせ】

nginx 設定ファイルでは、現在のモジュールに proxy_set_header 設定がない場合、設定は上位レベルから継承されます。

継承順序は、http、サーバー、場所です。

次のレイヤーで proxy_set_header を使用してヘッダー値を変更すると、すべてのヘッダー値が変更され、以前に継承されたすべての構成が破棄される可能性があります。

したがって、同じ場所で proxy_set_header を実行するようにしてください。そうしないと、他の問題が発生する可能性があります。

·【参照】

Nginx 中国語公式ドキュメント: http://www.nginx.cn/doc/

テスト参考ドキュメント: https://www.lijiaocn.com/问题/2019/05/08/nginx-ingress-keep-alive-not-work.html

キープアライブリファレンスドキュメント: https://wglee.org/2018/12/02/nginx-keepalive/

上記は、nginx リバースプロキシを使用する際に長時間接続を維持する方法の詳細です。nginx で長時間接続を維持する方法の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • プレフィックスケースを削除する Nginx リバース プロキシ構成のチュートリアル
  • grpc のリバース プロキシとして nginx を使用する場合の落とし穴の概要
  • Nginx リバース プロキシ構成の完全なプロセス記録
  • 複数のサーバーにNginxリバースプロキシを実装する方法
  • nginx を介してローカルでリバースプロキシを構成するプロセス全体
  • nginx リバース プロキシでの proxy_pass の実装
  • Nginx リバースプロキシの例の詳細な説明
  • Nginx リバース プロキシから go-fastdfs へのケースの説明

<<:  MySQL で binlog を使用する際のフォーマットの選択方法

>>:  シンプルなカウントダウン効果を実現するJavaScript

推薦する

Centos7 から Centos8 へのアップグレードに関するチュートリアル (画像とテキスト付き)

正式な環境でアップグレードする場合は、データと重要な設定をバックアップしてください。アップグレードに...

CSSは2つの要素をブレンドする効果(スティッキー効果)を実現します。

数年前、Taobaoのモバイル版の左下隅に面白い丸いボタンがあったことを覚えています。それをクリック...

vue-cli4.5.xはプロジェクトを素早く構築します

1. vue-cliをインストールする vue.js で vue.js を実行します。 2. プロジ...

ウェブ理論: 考えさせない読書ノート

第 1 章<br /> Web ページをユーザーにとって使いやすいものにするための最も重...

sbinディレクトリを生成せずにNginxをインストールするソリューション

エラーの説明: 1. Linux (CentOS 7 64) システムに Nginx (1.18.0...

LeetCode の SQL 実装 (184. 部門内で最も高い給与)

[LeetCode] 184. 部門最高給与従業員テーブルにはすべての従業員が保存されます。すべて...

Vue プロジェクトで axios をカプセル化する方法 (http リクエストの統合管理)

1. 要件Vue.js フレームワークを使用してフロントエンド プロジェクトを開発する場合、サーバ...

Vue の動的コンポーネントと非同期コンポーネントの詳細な理解

1. 動的コンポーネント <!DOCTYPE html> <html> &l...

CSSはボックスコンテナ(div)の高さを常に100%に設定します。

序文ブラウザをどのようにズームしても、ボックス コンテナーの高さを常に 100% に保つ必要がある場...

JavaScript parseInt() と Number() の違いのケーススタディ

学習目標: parseInt() と Number() という 2 つの関数は、文字列をデータ型に変...

HTMLコードに基づく画像断片化読み込み機能の実装

今日は断片化された画像の読み込み効果を実装します。効果は次のとおりです。 これを 3 つのステップで...

Mysql の一時テーブルとパーティションテーブルの違いの詳細な説明

一時テーブルとメモリテーブルメモリ テーブルとは、メモリ エンジンを使用するテーブルを指します。テー...

DockerでJavaプログラムを起動する方法

シンプルなSpring Boot Webプロジェクトを作成するアイデア ツールを使用して、Sprin...

クラウドサーバーはBaotaを使用してPython環境を構築し、Djangoプログラムを実行します。

目次PagodaをインストールするPythonランタイム環境を構成するPythonをインストールする...

js でオブジェクトとオブジェクト メソッドを作成するいくつかの方法の詳細な説明

この記事は、JS レッドブックの第 8 章に記載されているオブジェクトに関する 2 番目の記事です。...