NGINX Plus と NGINX Open Source を使用して Web サイトとアプリの負荷を分散し、可用性と信頼性を最適化する方法については、これまで多くの記事を書いてきました。 負荷分散は、アプリのパフォーマンスを向上させ、大規模にアプリを配信し、コンテナとマイクロサービスをデプロイするための基本的なツールです。
これまで、NGINX Plus をデータセンター(従来のアプリケーション配信コントローラーと併用)、コンテナー、 Amazon Web Services (AWS)、 Google Cloud Platform 、 Microsoft Azureなどのクラウド環境に導入する方法を説明してきました。
この記事では、NGINX Plus と NGINX の負荷分散技術 (負荷分散方法またはアルゴリズムとも呼ばれます) に焦点を当て、さまざまなユースケースに適した方法を選択する方法についてアドバイスを提供します。 NGINX は 4 つの負荷分散手法 (ラウンドロビン、ハッシュ、 IP ハッシュ、最小接続) を提供し、NGINX Plus ではさらに 1 つ (最小時間) が追加されます。 IP ハッシュを除く、HTTP トラフィックのすべてのメソッドは、TCP (および NGINX Plus リリース 9 以降では UDP) でも使用できます。
[編集者注– NGINX Plus R16およびNGINX Open Source 1.15.1では、追加の負荷分散アルゴリズムとして Random with Two Choices が導入されました。 詳細については、弊社のブログの「NGINX と「2 つの選択肢のパワー」負荷分散アルゴリズム」をご覧ください。
ここでは、負荷分散を構成する方法の基本を理解していることを前提としていますが、復習したい場合は次のリソースを確認してください。
簡単にするために、 http
コンテキストで構成する HTTP ロード バランシングに焦点を当てます。 代わりに、TCP ロード バランシングはストリーム
コンテキストで構成されます (NGINX Plus リリース 9 以降の UDP ロード バランシングも同様です)。 HTTP ロードバランサと TCP/UDP ロードバランサは機能が同等ですが、プロトコル間の本質的な違いにより、使用可能なディレクティブとパラメータは多少異なります。詳細については、 HTTPおよびTCP/UDPの Upstream モジュールに関するドキュメントを参照してください。
負荷分散を有効にするには、オプションのパラメーターや補助機能のない基本形式で 2 つの構成ブロックを示します。
サーバー
ブロックは、定義した特性を持つトラフィックをリッスンし、それを上流サーバーの名前付きグループにプロキシする仮想サーバーを定義します。 この例では、仮想サーバーはwww.example.comに送信される HTTP トラフィックをデフォルト ポート (80) でリッスンし、それをbackend と呼ばれるアップストリーム サーバー グループにプロキシします。 このブロックはすべての例で同じです。
サーバー { server_name www.example.com;
location / {
proxy_pass http://backend;
}
}
(NGINX Plus と NGINX は、FastCGI、memcached、SCGI、および uwsgi バックエンド サーバーの負荷分散も実行できます。 proxy_pass を
適切なディレクティブ ( fastcgi_pass
、 memcached_pass
、 scgi_pass
、またはuwsgi_pass
) に置き換えます。
アップストリーム
ブロックは、アップストリーム グループに名前を付け、ホスト名、IP アドレス、または UNIX ドメイン ソケット パスで識別される、そのグループに属するサーバーを一覧表示します。 この例では、 backendというアップストリーム グループに、 web1 、 web2 、 web3 の3 つのサーバーが含まれています。
アップストリーム
ブロックは負荷分散手法を指定する場所なので、以降のセクションではこれについて詳しく説明します。 例として、デフォルトの方法であるラウンドロビンのブロックを次に示します。
アップストリーム バックエンド { サーバー web1;
サーバー web2;
サーバー web3;
}
ラウンドロビンは、NGINX Plus と NGINX の両方のデフォルトの負荷分散手法です。ロード バランサーは上流サーバーのリストを順番に実行し、次の接続要求を各サーバーに順番に割り当てます。
バックエンドアップストリーム グループの次のサンプル構成では、ロード バランサは最初の 3 つの接続要求をweb1 、 web2 、 web3に順番に送信し、4 番目をweb1に、5 番目をweb2に、というように送信します。
アップストリーム バックエンド { サーバー web1;
サーバー web2;
サーバー web3;
}
サーバー {
server_name www.example.com;
location / {
proxy_pass http://backend;
}
}
ハッシュ方式では、ロード バランサーはリクエストごとに、指定したテキストとNGINX 変数の組み合わせに基づいてハッシュを計算し、そのハッシュをいずれかのサーバーに関連付けます。 このメソッドは、そのハッシュを持つすべてのリクエストをそのサーバーに送信するため、基本的な種類のセッション永続性を確立します。
次の例では、ハッシュ
ディレクティブは、リクエストのスキーム ( httpまたはhttps ) と完全な URI をハッシュの基礎として使用します。
アップストリームバックエンド {ハッシュ$scheme$request_uri; サーバー web1; サーバー web2; サーバー web3; } サーバー { server_name www.example.com; 場所 / { proxy_pass http://backend; } }
IP ハッシュ (HTTP のみで使用可能) は、ハッシュがクライアントの IP アドレスに基づいているハッシュ メソッドの定義済みバリアントです。 ip_hash
ディレクティブで設定します。
アップストリームバックエンド { ip_hash ; サーバー web1; サーバー web2; サーバー web3; } サーバー { server_name www.example.com; 場所 / { proxy_pass http://backend; } }
クライアントが IPv6 アドレスを持っている場合、ハッシュはアドレス全体に基づきます。 IPv4 アドレスの場合、ハッシュはアドレスの最初の 3 オクテットのみに基づきます。 これは、サブネットワーク (/24) 範囲から IP アドレスが動的に割り当てられる ISP クライアントを最適化するように設計されています。 再起動または再接続の場合、クライアントのアドレスは /24 ネットワーク範囲内の別のアドレスに変更されることがよくありますが、接続は依然として同じクライアントを表しているため、サーバーへのマッピングを変更する理由はありません。
ただし、サイトへのトラフィックの大部分が同じ /24 ネットワーク上のクライアントから来ている場合、IP ハッシュはすべてのクライアントを同じサーバーにマッピングするため意味がありません。 その場合 (または別の理由で 4 つのオクテットすべてをハッシュする場合)、代わりに$remote_addr
変数を使用して Hash メソッドを使用します。
ハッシュ $remote_addr;
最小接続方式では、ロード バランサは各サーバーとの現在のアクティブな接続数を比較し、接続数が最も少ないサーバーに要求を送信します。 least_conn
ディレクティブを使用して設定します。
アップストリームバックエンド { least_conn ; サーバー web1; サーバー web2; サーバー web3; } サーバー { server_name www.example.com; 場所 / { proxy_pass http://backend; } }
最小時間方式(NGINX Plus でのみ利用可能)では、ロードバランサーは各サーバーの 2 つのメトリック(現在のアクティブ接続数と過去のリクエストの加重平均応答時間)を数学的に組み合わせ、最も低い値を持つサーバーにリクエストを送信します。
least_time
ディレクティブのパラメータの選択によって、応答ヘッダー ( header
) を受信する時間または完全な応答 ( last_byte
) を受信する時間のどちらを追跡するかが制御されます。
アップストリームバックエンド { least_time (header | last_byte) ;サーバー web1;
サーバー web2; サーバー web3; } サーバー { server_name www.example.com; location / { proxy_pass http://backend; } }
注:
TCP および UDP 負荷分散 (ストリーム
コンテキスト内) の場合、 least_time
ディレクティブの次のパラメータを使用して、3 種類の応答時間から選択できます。
connect
– 上流サーバーに接続する時間first_byte
– 応答データの最初のバイトを受信するまでの時間last_byte
– 応答データの最後のバイトを受信するまでの時間NGINX Plus R12以降では、HTTP トラフィックと TCP/UDP トラフィックの両方について、各メトリックに不完全な接続を含めるためにinflight
パラメータが追加されました。以前のリリースでは、このような接続はデフォルトで含まれています。
では、どの負荷分散技術が Web サイトやアプリに最適かをどのように判断すればよいのでしょうか?
トラフィック パターンはサイトごとに大きく異なり、単一サイト内でも時間帯によって大きく異なるため、負荷分散手法の選択を単一の特性 (バースト トラフィックと安定したトラフィック、短命の接続と長命の接続など) に基づいて行うことは意味がありません。 とはいえ、各方法の長所と短所を検討して、検討すべき選択肢の範囲を絞り込むのに役立ちます。
どの負荷分散方法のサブセットを検討する場合でも、テストを行って、トラフィックに最適な方法を確認することをお勧めします。 「最良」とは通常、クライアントに応答を提供する最短時間を意味しますが、異なる基準がある場合もあります。
アプリケーション パフォーマンス管理ツールは、このようなテストに非常に便利です。アップストリーム グループ内の各サーバーのグラフを含むカスタム画面を作成し、テスト中に値が変化したときにそれらをリアルタイムで比較することができます。 AppDynamics 、 Datadog 、 Dynatrace 、 New Relicなど、いくつかの APM では、NGINX Plus および NGINX 用のカスタム プラグインが提供されています。
すべてのサーバーの容量が同じであれば、テストは最も簡単です。 そうでない場合は、容量が大きいマシンがより多くのリクエストを受信できるようにサーバーの重みを設定する必要があります。 以下の「サーバーが同一でない場合に重みを設定する」を参照してください。
テスト中に確認するメトリックは次のとおりです。
404
(ファイル
ない
見つかった
たとえば、ファイルが存在する場合、サーバーは実際のファイルを配信するよりもはるかに速くエラーを返す可能性があります。 最小接続および最小時間負荷分散アルゴリズムを使用すると、ロード バランサーが実際には正常に動作していないサーバーを優先する可能性があります。それでは、各負荷分散手法の利点と欠点を確認し、それらが特に適した使用例をいくつか説明しましょう。 大多数のユースケースに適合する順に説明します。 簡単にプレビューすると、最も幅広いユースケースでは、最小接続数(および NGINX Plus の場合は最小時間)が最適な選択肢であると考えられます。
ハッシュおよび IP ハッシュの負荷分散技術は、特定のタイプのクライアント要求 (ハッシュ値でキャプチャ) と特定のサーバーの間に固定された関連付けを作成します。 これはセッションの永続性として認識されるかもしれません。つまり、特定のハッシュ値を持つすべてのリクエストは常に同じサーバーに送信されます。
これらの方法の最大の欠点は、負荷を均等に分散するどころか、サーバー間でリクエストを均等に分散することが保証されないことです。 ハッシュ アルゴリズムは、すべての可能なハッシュ値のセットを、上流グループ内の各サーバーごとに 1 つずつ「バケット」に均等に分割しますが、実際に発生する要求のハッシュが均等に分散されるかどうかを予測する方法はありません。 たとえば、10 台のクライアントがサイトにアクセスしていて、IP ハッシュ アルゴリズムによって、IP アドレスのハッシュのうち 7 個がweb1に、1 個がweb2に、2 個がweb3にそれぞれ関連付けられているとします。 web1サーバーは、他のサーバーの合計よりも 2 倍以上のリクエストを受信することになります。
したがって、セッションを維持する利点が、不均衡な負荷による悪影響を上回る場合は、ハッシュまたは IP ハッシュを使用するのが合理的です。 これらは、NGINX で使用できる唯一のセッション永続化形式です。NGINX Plus は、より洗練され、実際の負荷分散と組み合わせて機能する 3 つの他のセッション永続化メカニズムを提供します ( sticky
ディレクティブを使用して設定します)。 ただし、次の場合には 3 つのメカニズムが機能しないため、NGINX Plus でもハッシュまたは IP ハッシュを選択する場合があります。
ブラウザまたはクライアント アプリは Cookie を受け入れず、アプリケーションには Cookie なしでセッション永続化メカニズムを操作する方法がありません。 IP ハッシュ方式を使用して、各クライアント (具体的には IP アドレス) を特定のサーバーに関連付けます。
サーバー自体のキャッシュを活用するために、特定の URL に対するリクエストを毎回同じサーバーに送信します。 $request_uri
変数を使用した Hash メソッドを使用して、毎回同じサーバーからファイルを取得します。
たとえば、特定の.phpファイルを提供するには時間のかかるデータベース呼び出しが数回必要だが、取得されたデータは頻繁に変更されないためキャッシュ可能であることがわかっているとします。 ファイルに対するすべての要求を同じサーバーに送信すると、データベース呼び出しのために最初のクライアントのみに長い遅延が発生します。 後続のすべてのクライアントでは、データがキャッシュからすぐに取得されます。 もう 1 つの利点は、特定のデータ セットをキャッシュする必要があるのは 1 つのサーバーだけであるということです。 すべてのサーバーで同じデータを重複してキャッシュすることがないため、より小さなキャッシュを使用できます。
IP ハッシュ (およびクライアント IP アドレスがキーに含まれている場合のハッシュ) が機能しないケースがいくつかあります。
ハッシュは決定論的です (ハッシュ アルゴリズムは毎回同じ結果を生成します)。 これには、いくつかのプラスの副作用があります。デプロイメント内のすべての NGINX Plus または NGINX インスタンスがまったく同じ方法でリクエストをロード バランシングし、ハッシュとサーバーのマッピングはロード バランサーの再起動後も維持されます。 (実際には再起動後に再計算されますが、結果は常に同じなので、実質的には保持されます。)
一方、アップストリーム サーバーのセットを変更すると、通常、少なくとも一部のマッピングの再計算が強制され、セッションの永続性が失われます。 再計算されるマッピングの数をいくらか減らすことができます。
ハッシュ
ディレクティブに一貫性のある
パラメータを含めます。NGINX Plus はketamaハッシュ アルゴリズムを使用するため、再マッピングが少なくなります。IP ハッシュ方式の場合、アップストリーム グループからサーバーを一時的に削除する前に、次の例のweb2のように、そのサーバー
ディレクティブにdown
パラメーターを追加します。 サーバーがすぐにサービスに戻ると想定して、マッピングは再計算されません。
アップストリームバックエンド { ip_hash; サーバー web1; サーバー web2ダウン; サーバー web3; }
前述のとおり、ラウンドロビンは NGINX Plus と NGINX のデフォルトの負荷分散方法です。そのため、これは最も簡単に選択できる方法であり、アップストリーム グループ自体以外に何も構成する必要はありません。
一般的に、ラウンドロビンは、サーバーとリクエストの特性により、一部のサーバーが他のサーバーに比べて過負荷になる可能性が低い場合に最も効果的に機能します。 条件の一部は次のとおりです。
ラウンドロビンは、リクエストがすべてのサーバーに均等に(または適切に重み付けされた割合で)分散されることを保証するため、テストシナリオに特に適しています。 他の方法では、トラフィック量が少ない場合に必ずしもトラフィックが均等に分散されないため、テスト結果が歪む可能性があります。
分散の均一性により、キャッシュが適切に機能し、最大容量が使用されているかどうかも明らかになります。ラウンドロビンでは特定のファイルに対するリクエストを同じサーバーに送信する方法がないため、すべてのサーバーがさまざまなファイル(通常はピアと同じファイルの多く)を提供してキャッシュすることになり、キャッシュがいっぱいになる可能性が高くなります。
最後に、均一な初期配布は、NGINX Plus のセッション永続性に関する問題を明らかにするのに役立ちます ( sticky
ディレクティブで設定)。
上で述べたように、最小接続は、幅広いユースケース、特に本番トラフィックに最適な負荷分散手法です。 これは、当社の顧客からの事例証拠によって裏付けられています。 パフォーマンスは安定しており、予測可能です。
最小接続は、サーバーの容量に応じてサーバー間でワークロードを効果的に分散します。 より強力なサーバーはリクエストをより速く処理するため、特定の時点でまだ処理中の接続数(または処理の開始を待機中の接続数)は、容量の小さいサーバーよりも少なくなる可能性があります。 「Least Connections」では、現在の接続数が最も少ないサーバーに各リクエストが送信されるため、強力なサーバーにリクエストが送信される可能性が高くなります。 (ただし、以下の「サーバーが同一でない場合に重みを設定する」で説明されているように、重みを設定すると、リクエストの分散がさらに効率的になります。)
「Least Time(NGINX Plus のみ)」は、「Least Connections」のより感度の高いバージョンと考えることができます。 平均応答時間を含めることで、サーバーの最近のパフォーマンス履歴が考慮されます (実際には指数的に加重された移動平均であるため、古い応答時間は最近の応答時間よりも平均に与える影響が少なくなります)。
最小時間は、上流サーバーの平均応答時間が大きく異なる場合に特に適しています。 たとえば、災害復旧の目的で複数のデータ センターにサーバーがある場合、Least Time ではローカル サーバーの方が応答が速いため、より多くのリクエストがローカル サーバーに送信される傾向があります。 もう 1 つのユースケースは、サーバーのパフォーマンスが予測不可能なことが多いクラウド環境です。
アップストリーム グループ内のサーバーの容量が異なる場合にサーバーの重みを設定することの重要性については、これまで何度も説明してきました。 これは、各サーバーに同じ数のリクエストを送信するラウンドロビン ロード バランサにとって特に重要です。 その結果、より強力なサーバーが部分的にアイドル状態になっている一方で、より強力でないサーバーが過負荷状態になる可能性が高くなります。
重みを設定するには、 upstream
ブロック内の 1 つ以上のサーバー
ディレクティブにweight
パラメータを含めます。 デフォルト値は 1 です。
さまざまな負荷分散手法の重み設定の効果については、次のように考えることができます。 説明は概念的には正しいですが、NGINX Plus コードの実装では必ずしも示された数学演算が使用されるわけではないことに注意してください。 例のアップストリーム グループは次のとおりです。
アップストリーム バックエンド { サーバー web1 重み = 6;
サーバー web2 重み = 3;
サーバー web3;
}
ラウンドロビン– 各サーバーは、その重みを重みの合計で割った値に等しい受信リクエストの割合を取得します。 この例では、10 回のリクエストのうち、 web1 は6 回 (60%)、 web2 は3 回 (30%)、 web3 は1 回 (10%) を受け取ります。
ハッシュとIP ハッシュ– 重み付けがない場合、ハッシュ アルゴリズムは、すべての可能なハッシュ値のセットを、上流グループ内の各サーバーごとに 1 つずつ「バケット」に均等に分割することを思い出してください。 重みを使用すると、代わりに重みを合計し、可能なハッシュのセットをその数のバケットに分割し、各サーバーをその重みに相当する数のバケットに関連付けます。
この例では、バケットが 10 個あり、各バケットには可能なハッシュの 10% が含まれています。 6 つのバケット (可能なハッシュの 60%) はweb1に関連付けられ、3 つのバケット (30%) はweb2に関連付けられ、1 つのバケット (10%) はweb3に関連付けられています。
最小接続と最小時間– 重み付けがなくても、これらのアルゴリズムはサーバーの容量に応じてサーバー間でワークロードを分散するのに非常に効果的であることは以前に説明しました。 重みを設定すると、この点でのパフォーマンスがさらに向上します。
Least Connections と Least Time では、各リクエストが最も低い「スコア」(それぞれ接続数、または接続と時間の数学的組み合わせ)を持つサーバーに送信されることに注意してください。 重みを割り当てると、ロード バランサーは各サーバーのスコアを重みで割り、最も低い値を持つサーバーにリクエストを再度送信します。
以下は、サンプルの重みとアクティブな接続の示された数を使用した最小接続数の例です。web1 のスコアは 100 で最低であり、接続数が 600 でweb2の 1.5 倍、 web3 の4 倍以上であるにもかかわらず、リクエストを受け取ります。
NGINX Plus と NGINX で利用可能な負荷分散技術の長所と短所を検討した結果、最も幅広いユースケースには、最小接続 (NGINX Plus の場合は最小時間) が最も適していると考えました。 ただし、トラフィックとサーバーの特性の独自の組み合わせによっては、別の方法の方が適している可能性があるため、展開時に複数の方法をテストすることが重要です。
NGINX Plus のロード バランシングを実際に試すには、今すぐ30 日間の無料トライアルを開始するか、弊社にお問い合わせの上、ユースケースについてご相談ください。
さまざまなユースケースでの負荷分散に関するご経験をぜひお聞かせください。 下のコメント欄に追加してください。
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"