今日のインターネット時代では、ユーザー数の増加とビジネス規模の拡大に伴い、単一サーバーでは高い同時実行性と大規模なトラフィックのニーズを満たすことができなくなりました。この問題を解決するために、負荷分散技術が登場しました。負荷分散により、大量のネットワーク要求を複数のサーバーに分散して処理できるため、システムの処理能力が向上し、サービスの高可用性が確保されます。負荷分散の中核は、さまざまなサーバーに要求を分散する方法を決定する負荷分散アルゴリズムです。この記事では、負荷分散アルゴリズムの原理を詳細に紹介し、実際のアプリケーション シナリオに基づいてその応用を実際に検討します。
記事ディレクトリ
1. 負荷分散の概要
1.1. 大規模な Web サイトの開発上の課題
インターネットの初期の頃、大規模な Web サイトは大きな課題に直面していました。ユーザー数が増加し、データ量が爆発的に増加すると、単一のサーバーではそのような大きな圧力に耐えられなくなることがよくあります。これにより、パフォーマンスのボトルネックが発生し、サーバーの応答時間が長くなり、ユーザー エクスペリエンスが低下します。同時に、単一サーバーの拡張性にも限界があり、ビジネスの発展に伴ってトラフィックが大幅に増加する可能性があり、単一サーバーでハードウェア リソースを追加して需要を満たすことが困難になります。さらに深刻なのは、すべてのリクエストが同じサーバーに送信され、そのサーバーに障害が発生すると、サービス全体が中断されてしまうことです。
これらの問題を解決するために、Webサイトでは縦方向の拡張と横方向の拡張を試みるようになりました。
垂直拡張はサーバーのハードウェア性能を高めることで処理能力を向上させますが、この方法には性能のボトルネックと高コストが伴います。
水平拡張では、サーバーの数を増やし、複数のサーバーに負荷を分散することで、システムの処理能力が向上します。しかし、各サーバーの負荷を適切な範囲内に保つために、ユーザーのリクエストを異なるサーバーに効果的に分散する方法が新たな問題となっています。
ここで、今日議論したいトピックである負荷分散について説明します。
1.2. ロードバランシングとは何ですか?
Wikipedia: 負荷分散 (英語: 負荷分散) は、複数のコンピューター (コンピューター クラスター)、ネットワーク接続、CPU、ディスク ドライブ、またはその他のリソース間で負荷を分散し、リソースの使用を最適化し、スループットを最大化し、応答時間を最小限に抑えながら負荷を分散するために使用されるコンピューター テクノロジです。過負荷。単一コンポーネントの代わりに負荷分散を行う複数のサーバー コンポーネントを使用すると、冗長性によって信頼性が向上します。負荷分散サービスは通常、専用のソフトウェアとハードウェアによって実行されます。その主な機能は、実行のために多数のジョブを複数のオペレーティング ユニットに合理的に割り当てることであり、インターネット アーキテクチャにおける高い同時実行性と高可用性の問題を解決するために使用されます。
Baidu Encyclopedia: 負荷分散は既存のネットワーク構造に基づいて構築されており、ネットワーク デバイスとサーバーの帯域幅を拡張し、スループットを向上させ、ネットワーク データ処理機能を強化し、ネットワークの柔軟性と可用性を向上させる、安価で効果的かつ透過的な方法を提供します。
負荷分散は、複数のコンピュータ (コンピュータ クラスタなど)、ネットワーク接続、CPU、ハード ドライブ、またはその他のリソース間でワークロードを分散するために使用されるコンピュータ テクノロジです。その主な目標は、リソースの使用量を最適化し、スループットを最大化し、応答時間を最小化し、1 つのリソースの過負荷を回避することです。
実際のアプリケーションでは、負荷分散では通常、単一コンポーネントではなく複数のサーバー コンポーネントを使用して、システムの信頼性と冗長性を向上させます。これらのサーバー コンポーネントは、物理サーバーまたは仮想マシンにすることができます。負荷分散サービスは通常、専用のソフトウェアとハードウェア (ロード バランサーなど) によって実行されます。
インターネット アーキテクチャでは、負荷分散は主に、高同時実行性と高可用性の問題を解決するために使用されます。たとえば、Web サイトへのアクセス数が突然増加した場合、負荷分散によってこれらのアクセス要求が複数のサーバーに分散され、Web サイトが正常に動作するようになります。
ユーザーがリモート サービスを要求すると、その要求はまず DNS サーバーに送信されます。DNS サーバーはドメイン名を対応する IP アドレスに解決し、要求はこの IP アドレス (通常はゲートウェイまたはロード バランサー) に送信されます。ロード バランサーは、何らかのアルゴリズム (ラウンド ロビン、最小接続数など) に基づいてリクエストをバックエンドのサーバーにルーティングします。このようにして、ユーザーのリクエストをさまざまなサーバーに効果的に分散できるため、負荷分散が実現され、システムのパフォーマンスと可用性が向上します。
1.2. ロードバランシングが必要な理由
負荷分散は現代のコンピュータ システムにおいて重要な役割を果たしており、その主な機能は次のとおりです。
- パフォーマンスとスループットの向上: 負荷分散により、リクエストを複数のバックエンド サーバーに分散し、各サーバーで処理される負荷のバランスを高めることができます。これにより、システムの全体的なパフォーマンスとスループットが向上し、ユーザーの待ち時間が短縮され、ユーザー エクスペリエンスが向上します。
- システムの可用性の向上: たとえば、負荷を複数のサーバーに分散することで、1 つのサーバーに障害が発生した場合でも、他のサーバーが引き続きリクエストを処理できるため、システムの可用性と信頼性が向上します。ロード バランサーは障害を自動的に検出し、利用可能なサーバーにリクエストを転送することで、サービス中断のリスクを軽減します。
- システムのスケーラビリティの実現: ロード バランサは、実際の負荷状況に基づいてバックエンド サーバーを動的に追加または削除し、システムの弾力的な拡張を実現します。負荷が増加すると、より多くのサーバーを追加して負荷を共有でき、負荷が減少すると、サーバーの数を減らしてリソースを節約できます。
- 高同時実行性と高可用性の問題を解決する: インターネット アーキテクチャでは、負荷分散によって高同時実行性と高可用性の問題を効果的に解決できます。リクエストを複数のサーバーに分散すると、負荷のバランスが取れ、単一サーバーの過負荷を回避できるため、ユーザー エクスペリエンスが向上します。
- リソース使用率の向上: 負荷分散により、サーバーのパフォーマンス指標と負荷状態に基づいてリクエストを最適なサーバーに分散できます。これにより、サーバー リソースが有効に活用され、リソースの使用率が向上します。
要約すると、負荷分散はパフォーマンス、可用性、信頼性、リソース使用率の向上に重要な役割を果たしており、効率的で信頼性の高いコンピュータ システムを構築するための重要なテクノロジの 1 つです。
1.4. 負荷分散の動作原理
負荷分散の動作原理は、次の手順のように簡単に要約できます。
- リクエストの受信: ユーザーがリクエストを行うと、そのリクエストはまずロードバランサーに送信されます。
- リクエストの分散: ロード バランサーは、ラウンド ロビン、最小接続、ソース アドレス ハッシュなどの特定のロード バランシング アルゴリズムに基づいて、バックエンドのサーバーにリクエストを分散します。このプロセス中、ロード バランサーはバックエンド サーバーの現在の負荷を考慮して、すべてのサーバーの負荷が妥当な範囲内に収まるようにします。
- 応答の返信: バックエンド サーバーはユーザーのリクエストを処理した後、ロード バランサーに応答を返し、ロード バランサーはユーザーに応答を返します。
- ヘルス チェック: ロード バランサーは、バックエンド サーバーのヘルス チェックを定期的に実行します。サーバーに障害があることが判明した場合、ロード バランサーはそのサーバーをサービス リストから削除し、リクエストを分散しません。サーバーが正常に戻ると、ロード バランサーはそのサーバーをサービス リストに再度追加します。
上記の手順を通じて、ロード バランサーはユーザーのリクエストを複数のサーバーに効果的に分散できるため、ロード バランシングが実現され、システムのパフォーマンスと可用性が向上します。
2. 負荷分散の分類
負荷分散をサポートする多くのテクノロジーを多次元から分類できます。
2.1. DNS ロードバランシング
DNS 負荷分散は、シンプルで一般的な負荷分散方法であり、主に地理レベルの負荷分散を実現するために使用されます。DNS 負荷分散を通じて、ユーザーのリクエストを地理的に最も近いサーバーに送信できるため、ネットワーク遅延が短縮され、ユーザー エクスペリエンスが向上します。具体的には、DNS サーバーは、ユーザーの地理的位置に基づいて、同じドメイン名を異なる IP アドレスに解決します。
たとえば、同じドメイン名 www.baidu.com の場合、北部のユーザーは北京のコンピューター室の IP アドレスを取得し、南部のユーザーは上海のコンピューター室の IP アドレスを取得する可能性があります。このようにして、ユーザーのリクエストをさまざまなサーバーに効果的に分散して負荷分散を実現できます。
DNS 負荷分散により、グローバルな負荷分散を実現できます。DNS サーバーは、クライアントの地理的位置、ネットワーク状態、その他の要因に基づいて、最適なサーバー IP を選択してクライアントに返すことができるため、グローバルなトラフィック分散が実現されます。たとえば、ヨーロッパからのユーザー要求はヨーロッパのサーバーに分散され、米国からのユーザー要求は米国のサーバーに分散されます。
ただし、DNS 負荷分散にはいくつかの制限もあります。たとえば、DNS クエリの結果がクライアントまたは中間ネットワーク デバイスによってキャッシュされると、負荷分散ポリシーがリアルタイムで有効にならなくなる場合があります。さらに、DNS 負荷分散はセッションの永続性を実現できず、サーバーのリアルタイムの負荷状態に基づいて動的に調整できません。したがって、DNS 負荷分散は通常、他の負荷分散テクノロジー (4 層負荷分散、7 層負荷分散など) と組み合わせて使用され、より効率的な負荷分散を実現します。
2.2. 実装方法による分類
実装方法に応じて、負荷分散は主にハードウェア負荷分散とソフトウェア負荷分散の 2 つのカテゴリに分類できます。
-
ハードウェア ロード バランサ: ハードウェア ロード バランサは特殊な物理デバイスです。これらのデバイスは強力で強力、高性能、および信頼性が高く、大規模なネットワーク トラフィックの処理に適しています。ただし、安価ではなく、通常は次のユーザーのみが使用できます。このような機器の使用を検討するのは企業だけです。
-
ソフトウェア負荷分散: ソフトウェア負荷分散装置は、通常のサーバー上で動作するソフトウェアであり、低コストで拡張性に優れています。ソフトウェア ロード バランサーは、必要に応じて簡単にスケールアップまたはスケールダウンできるため、クラウド コンピューティングや仮想化環境に適しています。一般的なのは Nginx と LVS で、Nginx は 7 層の負荷分散ソフトウェア、LVS は Linux カーネルの 4 層の負荷分散ソフトウェアです。
2.3. 作業レベルによる分類
負荷分散は、作業レベルの分類に応じて、主に 4 層負荷分散と 7 層負荷分散の 2 つのカテゴリに分類できます。
- 4 層負荷分散: 4 層負荷分散は、ネットワーク モデルのトランスポート層で動作し、主に要求された IP アドレスとポート番号に基づいて負荷分散を実行します。レイヤ 4 ロード バランサは、リクエストの特定の内容を考慮せず、単にリクエストをバックエンドのサーバーに転送します。したがって、4 層の負荷分散は処理速度は速くなりますが、柔軟性は低くなります。
- 7 層負荷分散: 7 層負荷分散は、ネットワーク モデルのアプリケーション層で機能し、リクエストの特定の内容 (URL、リクエスト ヘッダー、リクエスト メソッドなど) に基づいて負荷分散を実行できます。7 層のロード バランサーはリクエストの特定の内容を理解できるため、URL ベースのロード バランシング、セッション ベースのロード バランシングなど、より複雑なロード バランシング戦略を実装できます。ただし、リクエストの特定の内容を処理する必要があるため、7 層の負荷分散の処理速度は比較的遅くなります。
実際のアプリケーションでは、多くの大規模な Web サイトやクラウド サービス プロバイダーは、レイヤー 4 の負荷分散とレイヤー 7 の負荷分散の両方を使用して、より効率的で柔軟な負荷分散を実現しています。
2.4. 作業範囲による分類
ロード バランシングは、作業範囲に応じて、主にグローバル ロード バランシングとローカル ロード バランシングの 2 つのカテゴリに分類できます。
- グローバル ロード バランシング: グローバル ロード バランシングは、主に世界中の複数のデータ センター間のロード バランシングに使用されます。各データセンターの負荷状況、ネットワーク状況、クライアントの地理的位置などの要因に基づいて、ユーザーのリクエストを最も適切なデータセンターにインテリジェントに分散できます。これにより、ネットワーク遅延が短縮され、サービスのパフォーマンスと可用性が向上します。
- 部分負荷分散: 部分負荷分散は主に、単一のデータセンター内の複数のサーバー間の負荷分散に使用されます。通常、ポーリング、最小接続、ソース アドレス ハッシュなど、より詳細な負荷分散戦略を使用して、より効率的なリソース利用とより優れたパフォーマンスを実現します。
2.5. 実施主体による分類
負荷分散は、実装者の分類に応じてサーバー側負荷分散とクライアント側負荷分散に分けられ、作業範囲と目的が異なります。
- サーバー側ロード バランシング: この方法では、ロード バランサーがサーバー側に配置され、すべてのクライアント リクエストが最初にロード バランサーに送信されます。ロード バランサーは、負荷分散アルゴリズムに基づいてバックエンドのサーバーにリクエストを分散します。この方法の利点は、実装が簡単で透明性が高く、クライアント側で特別な処理が必要ないことです。ただし、すべてのリクエストはロード バランサーを通過する必要があるため、パフォーマンスのボトルネックになる可能性があります。
- クライアント負荷分散: このアプローチでは、負荷分散ロジックがクライアント側に実装されます。クライアントは、サービス登録センターから利用可能なすべてのサービスのリストを取得し、負荷分散アルゴリズムに基づいて要求するサービスを選択します。この方法の利点は、サーバー側のロード バランサーがパフォーマンスのボトルネックになるのを回避できることですが、クライアントにロード バランシング ロジックを実装する必要があるため、クライアントの複雑さが増大します。
3. 負荷分散アルゴリズム
3.1. ポーリングアルゴリズム
ラウンド ロビンは、非常にシンプルな負荷分散アルゴリズムです。このアルゴリズムでは、ロード バランサーは受信したリクエストをあらかじめ決められた順序でバックエンド サーバーに振り分けます。
具体的には、ロード バランサーはサーバーのリストを維持します。新しいリクエストを受信すると、ロード バランサーはそのリクエストをリスト内の次のサーバーに割り当て、そのサーバーをリストの最後に移動します。このようにして、各サーバーに順番にリクエストを処理する機会が与えられ、負荷分散が実現されます。
たとえば、3 つのサーバー A、B、C があるとします。最初のリクエストが来ると、ロード バランサーはそれをサーバー A に割り当てます。2 番目のリクエストが来ると、ロード バランサーはそれをサーバー B に割り当てます。3 番目のリクエストが来ると、ロード バランサーはそれをサーバー C に割り当てます。 4 番目のリクエストが来ると、ロード バランサーはそのリクエストを再びサーバー A に割り当てる、というようになります。
擬似コードの単純な実装:
// 定义一个类 RoundRobinLoadBalancer
public class RoundRobinLoadBalancer {
// 定义一个服务器列表 servers
private List<String> servers;
// 定义一个当前索引 currentIndex
private int currentIndex;
// 定义一个构造函数,接收一个服务器列表作为参数
public RoundRobinLoadBalancer(List<String> servers) {
this.servers = servers;
this.currentIndex = 0;
}
// 定义一个方法 getNextServer,返回下一个服务器
public synchronized String getNextServer() {
// 如果 currentIndex 大于等于 servers 的长度,将 currentIndex 设置为 0
if (currentIndex >= servers.size()) {
currentIndex = 0;
}
// 获取 servers 中 currentIndex 对应的服务器
String server = servers.get(currentIndex);
// 将 currentIndex 加 1
currentIndex++;
// 返回 server
return server;
}
}
この疑似コードでは、
getNextServer
メソッドが呼び出されるたびに、サーバー リスト内の次のサーバーが返され、現在のインデックスが更新されます。現在のインデックスがサーバー リストの長さを超えると、ポーリングを実装するために 0 にリセットされます。スレッドの安全性を確保するために、ここでキーワードを使用していることに注意してくださいsynchronized
。
ポーリング アルゴリズムの利点は、実装が簡単で、サーバーのパフォーマンスが同等であれば、より優れた負荷分散を実現できることです。ただし、サーバーのパフォーマンスが均一でない場合、またはリクエストの処理時間が大きく異なる場合は、ポーリング アルゴリズムが適切な負荷分散効果を達成できない可能性があります。
3.2. 加重ポーリングアルゴリズム
加重ラウンド ロビンは、バックエンド サーバーの処理能力が異なる可能性があることを考慮したポーリング アルゴリズムの変形です。
重み付けポーリング アルゴリズムでは、各サーバーにはサーバーの処理能力を反映する重みが割り当てられます。重みが大きいサーバーには、より多くのリクエストが割り当てられます。
具体的には、ロード バランサーは、それぞれに重みを付けたサーバーのリストを維持します。新しいリクエストが受信されると、ロード バランサーはサーバーの重みに従ってリクエストを分散します。たとえば、サーバー A の重みが 3、サーバー B の重みが 2 の場合、5 つのリクエストのうち、サーバー A は 3 つのリクエストを処理し、サーバー B は 2 つのリクエストを処理します。
擬似コードの単純な実装:
// 定义一个类 WeightedRoundRobinLoadBalancer
public class WeightedRoundRobinLoadBalancer {
// 定义一个服务器列表 servers,每个服务器有一个权重
private Map<String, Integer> servers;
// 定义一个当前索引 currentIndex 和当前权重 currentWeight
private int currentIndex;
private int currentWeight;
// 定义一个构造函数,接收一个服务器列表和对应的权重作为参数
public WeightedRoundRobinLoadBalancer(Map<String, Integer> servers) {
this.servers = servers;
this.currentIndex = -1;
this.currentWeight = 0;
}
// 定义一个方法 getNextServer,返回下一个服务器
public synchronized String getNextServer() {
// 获取服务器列表的大小
int size = servers.size();
// 循环直到找到一个合适的服务器
while (true) {
// 如果 currentIndex 为 size - 1,将 currentIndex 设置为 0,currentWeight 减 1
if (currentIndex == size - 1) {
currentIndex = 0;
currentWeight--;
// 如果 currentWeight 为 0,找出服务器列表中的最大权重,设置为 currentWeight
if (currentWeight == 0) {
currentWeight = getMaxWeight();
// 如果 currentWeight 仍为 0,表示没有可用的服务器,返回 null
if (currentWeight == 0) {
return null;
}
}
} else {
currentIndex++;
}
// 如果当前服务器的权重大于等于 currentWeight,返回当前服务器
if (servers.get(currentIndex) >= currentWeight) {
return servers.get(currentIndex);
}
}
}
// 定义一个方法 getMaxWeight,返回服务器列表中的最大权重
private int getMaxWeight() {
int max = 0;
for (int weight : servers.values()) {
max = Math.max(max, weight);
}
return max;
}
}
この疑似コードでは、
getNextServer
メソッドが呼び出されるたびに、サーバーの重みに基づいて次のサーバーに戻り、現在のインデックスと現在の重みを更新します。すべてのサーバーの重みが使い果たされると、最大重みが再計算され、重み付きポーリングが実装されます。スレッドの安全性を確保するために、ここでキーワードを使用していることに注意してくださいsynchronized
。
加重ポーリング アルゴリズムの利点は、不均一なサーバー パフォーマンスを適切に処理できることです。サーバーの重みを調整することで、負荷のバランスをより高めることができます。ただし、これにはサーバーのパフォーマンスを正確に理解する必要があり、サーバーのパフォーマンスが変化した場合には重みを手動で調整する必要がある場合があります。
3.3. 最小接続アルゴリズム
最小接続数は、一般的に使用される負荷分散アルゴリズムです。このアルゴリズムでは、新しいリクエストはアクティブな接続が最も少ないサーバーに割り当てられます。
具体的には、ロード バランサーはサーバーのリストを維持し、各サーバーのアクティブな接続の数をリアルタイムで監視します。新しいリクエストを受信すると、ロード バランサーはアクティブな接続が最も少ないサーバーにリクエストを割り当てます。
最小接続アルゴリズムの利点は、サーバーの実際の負荷に基づいて負荷分散を動的に実行できることです。これは、処理に時間がかかるリクエストに適しています。処理に時間がかかるリクエストほど多くの接続が必要となり、サーバーに新しいリクエストが割り当てられる可能性が減るためです。
最小接続アルゴリズムの欠点は、サーバーごとのアクティブな接続数をリアルタイムで監視する必要があるため、ロード バランサーの複雑さとオーバーヘッドが増加する可能性があることです。さらに、サーバーのパフォーマンスが不均一な場合、最小接続アルゴリズムでは良好な負荷分散効果が得られない可能性があります。
3.4. 重み付き最小結合アルゴリズム
加重最小接続 (加重最小接続) は、バックエンド サーバーの処理能力が異なる可能性があることを考慮した、最小接続アルゴリズムの変形です。
重み付き最小結合アルゴリズムでは、各サーバーにはサーバーの処理能力を反映する重みが割り当てられます。重みが大きいサーバーには、より多くのリクエストが割り当てられます。
具体的には、ロード バランサは、それぞれに重みとアクティブな接続の数を含むサーバーのリストを維持します。新しいリクエストが到着すると、ロード バランサーは、現在のアクティブな接続数と重みの比率が最も小さいサーバーにリクエストを割り当てます。
たとえば、サーバー A の重みが 3 でアクティブな接続の数が 6、サーバー B の重みが 2 でアクティブな接続の数が 3 の場合、新しいリクエストはサーバー B に割り当てられます。サーバー B の重みに対するアクティブな接続数の比率 (3/2=1.5) は、サーバー A の重みに対するアクティブな接続数の比率 (6/3=2) よりも小さくなります。
擬似コードの単純な実装:
// 定义一个类 WeightedLeastConnectionsLoadBalancer
public class WeightedLeastConnectionsLoadBalancer {
// 定义一个服务器列表 servers,每个服务器有一个权重和当前连接数
private Map<String, Server> servers;
// 定义一个构造函数,接收一个服务器列表和对应的权重作为参数
public WeightedLeastConnectionsLoadBalancer(Map<String, Server> servers) {
this.servers = servers;
}
// 定义一个方法 getNextServer,返回下一个服务器
public synchronized String getNextServer() {
// 初始化最小权重比率为正无穷大,最小服务器为 null
double minRatio = Double.POSITIVE_INFINITY;
String minServer = null;
// 遍历服务器列表
for (Map.Entry<String, Server> entry : servers.entrySet()) {
// 计算当前服务器的权重比率(当前连接数 / 权重)
double ratio = (double) entry.getValue().getConnections() / entry.getValue().getWeight();
// 如果当前服务器的权重比率小于最小权重比率,更新最小权重比率和最小服务器
if (ratio < minRatio) {
minRatio = ratio;
minServer = entry.getKey();
}
}
// 返回最小服务器
return minServer;
}
}
// 定义一个类 Server,表示一个服务器
public class Server {
private int weight;
private int connections;
// 定义一个方法 getWeight,返回服务器的权重
public int getWeight() {
return weight;
}
// 定义一个方法 getConnections,返回服务器的当前连接数
public int getConnections() {
return connections;
}
}
この疑似コードでは、
getNextServer
メソッドが呼び出されるたびに、サーバー リストを走査し、現在の接続数と重みの比率が最小のサーバーを見つけて、それを返します。スレッドの安全性を確保するために、ここでキーワードを使用していることに注意してくださいsynchronized
。
加重最小接続アルゴリズムの利点は、不均一なサーバー パフォーマンスを適切に処理できることです。サーバーの重みを調整することで、負荷のバランスをより高めることができます。ただし、これにはサーバーのパフォーマンスを正確に理解する必要があり、サーバーのパフォーマンスが変化した場合には重みを手動で調整する必要がある場合があります。
3.5. 送信元アドレスハッシュアルゴリズム
ソース IP ハッシュは、一般的に使用される負荷分散アルゴリズムです。このアルゴリズムでは、ロード バランサーがリクエストの送信元 IP アドレスに基づいてハッシュ計算を実行し、ハッシュ値に基づいてリクエストをバックエンド サーバーに分散します。
具体的には、ロード バランサーはサーバーのリストを維持します。新しいリクエストが受信されると、ロード バランサーはリクエストの送信元 IP アドレスを取得し、送信元 IP アドレスに対してハッシュ計算を実行します。計算されたハッシュ値はサーバーの選択に使用されます。たとえば、ハッシュ値はサーバーの数を法として取得され、その結果がリクエストを処理するサーバーのインデックスとなります。
送信元アドレス ハッシュ アルゴリズムの利点は、同じ送信元 IP アドレスからのリクエストが常に同じサーバーに割り当てられることです。これは、同じユーザーからの連続したリクエストを同じサーバーに割り当ててセッション状態を共有できるため、セッション状態を維持する必要があるアプリケーションに役立ちます。
送信元アドレス ハッシュ アルゴリズムの欠点は、特定の送信元 IP アドレスのリクエスト量が特に多い場合、特定のサーバーの負荷が高くなりすぎる可能性があることです。さらに、サーバーの追加や削除など、サーバーの数が変更されると、すべてのハッシュ値が変更され、多数のリクエストが他のサーバーに再割り当てされ、元のセッション状態が中断される可能性があります。
3.6. URL ハッシュアルゴリズム
URL ハッシュは、一般的に使用される負荷分散アルゴリズムです。このアルゴリズムでは、ロード バランサーがリクエストされた URL に基づいてハッシュ計算を実行し、そのハッシュ値に基づいてリクエストをバックエンド サーバーに分散します。
具体的には、ロード バランサーはサーバーのリストを維持します。新しいリクエストが受信されると、ロード バランサーはリクエストされた URL をフェッチし、その URL をハッシュします。計算されたハッシュ値はサーバーの選択に使用されます。たとえば、ハッシュ値はサーバーの数を法として取得され、その結果がリクエストを処理するサーバーのインデックスとなります。
擬似コードの単純な実装:
// 定义一个类 URLHashLoadBalancer
public class URLHashLoadBalancer {
// 定义一个服务器列表 servers
private List<String> servers;
// 定义一个构造函数,接收一个服务器列表作为参数
public URLHashLoadBalancer(List<String> servers) {
this.servers = servers;
}
// 定义一个方法 getServer,接收一个 URL 作为参数,返回对应的服务器
public String getServer(String url) {
// 使用 Java 的 hashCode 方法获取 URL 的哈希值
int hashcode = url.hashCode();
// 使用哈希值对服务器列表的长度取模,得到服务器的索引
int index = hashcode % servers.size();
// 返回对应的服务器
return servers.get(index);
}
}
この疑似コードでは、
getServer
メソッドは入力 URL に基づいてハッシュ値を計算し、ハッシュ値に基づいてサーバーを選択します。これにより、同じ URL が常に同じサーバーにルーティングされるようになり、セッションの永続性が実現されます。ここではハッシュ値の計算に Java メソッドが使用されていることに注意してくださいhashCode
。実際のアプリケーションでは、ハッシュ値を均等に分散させるために、より複雑なハッシュ関数を使用する必要がある場合があります。
URL ハッシュ アルゴリズムの利点は、同じ URL に対するリクエストが常に同じサーバーに割り当てられることを保証できることです。これは、同じ URL に対する連続したリクエストを同じサーバーに割り当ててキャッシュを共有できるため、キャッシュが必要なアプリケーションに役立ちます。
URL ハッシュ アルゴリズムの欠点は、特定の URL のリクエスト量が特に多い場合、特定のサーバーの負荷が高くなりすぎる可能性があることです。さらに、サーバーの追加や削除など、サーバーの数が変更されると、すべてのハッシュ値が変更され、多数のリクエストが他のサーバーに再割り当てされ、元のキャッシュが中断される可能性があります。
3.7. 最短応答時間アルゴリズム
最短応答時間 (Shortest Response Time) は、一般的に使用される負荷分散アルゴリズムです。このアルゴリズムでは、新しいリクエストは現在の応答時間が最も短いサーバーに割り当てられます。
具体的には、ロード バランサーはサーバーのリストを維持し、各サーバーの応答時間をリアルタイムで監視します。新しいリクエストが届くと、ロード バランサーは現在の応答時間が最も短いサーバーにリクエストを割り当てます。
擬似コードの単純な実装:
// 定义一个类 ShortestResponseLoadBalancer
public class ShortestResponseLoadBalancer {
// 定义一个服务器列表 servers,每个服务器有一个响应时间
private Map<String, Integer> servers;
// 定义一个构造函数,接收一个服务器列表作为参数
public ShortestResponseLoadBalancer(Map<String, Integer> servers) {
this.servers = servers;
}
// 定义一个方法 getServer,返回响应时间最短的服务器
public synchronized String getServer() {
// 初始化最短响应时间为正无穷大,最短响应时间的服务器为 null
int minResponseTime = Integer.MAX_VALUE;
String minResponseServer = null;
// 遍历服务器列表
for (Map.Entry<String, Integer> entry : servers.entrySet()) {
// 如果当前服务器的响应时间小于最短响应时间,更新最短响应时间和最短响应时间的服务器
if (entry.getValue() < minResponseTime) {
minResponseTime = entry.getValue();
minResponseServer = entry.getKey();
}
}
// 返回最短响应时间的服务器
return minResponseServer;
}
}
この疑似コードでは、
getServer
メソッドが呼び出されるたびに、サーバー リストを走査し、応答時間が最も短いサーバーを見つけて、それを返します。スレッドの安全性を確保するために、ここでキーワードを使用していることに注意してくださいsynchronized
。実際のアプリケーションでは、サーバーの応答時間は通常動的に変化するため、定期的に更新したり、リアルタイムで計算したりする必要がある場合があります。
最小応答時間アルゴリズムの利点は、サーバーの実際のパフォーマンスに基づいて負荷分散を動的に実行できることです。これは、処理時間が異なるリクエストに対して非常に効果的です。リクエストが長くなるとサーバーの応答時間が長くなり、サーバーに新しいリクエストが割り当てられる可能性が減るためです。
最小応答時間アルゴリズムの欠点は、各サーバーの応答時間をリアルタイムで監視する必要があるため、ロード バランサの複雑さとオーバーヘッドが増大する可能性があることです。さらに、サーバーのパフォーマンスが不均一な場合、最小応答時間アルゴリズムでは良好な負荷分散効果が得られない可能性があります。
3.8. 負荷分散アルゴリズムの選択
負荷分散アルゴリズムの選択は、主に次の要因によって決まります。
- サーバーのパフォーマンスが均一かどうか: サーバーのパフォーマンスが大きく異なる場合は、加重ラウンドロビンまたは加重最小結合アルゴリズムの方が適している可能性があります。これらの 2 つのアルゴリズムは重みを調整することでサーバーのパフォーマンスの違いを考慮できるためです。 。
- リクエストの処理時間が同じかどうか: リクエストの処理時間が大幅に異なる場合は、最小接続数または最短応答時間のアルゴリズムの方が適している可能性があります。これら 2 つのアルゴリズムはサーバーの負荷に基づいて動的に負荷分散できるためです。
- セッション状態を維持する必要があるかどうか: セッション状態を維持する必要がある場合は、送信元アドレス ハッシュ アルゴリズムの方が適している可能性があります。このアルゴリズムを使用すると、同じ送信元 IP アドレスからのリクエストが常に同じサーバーに割り当てられるためです。
- キャッシュが必要かどうか: キャッシュが必要な場合は、URL ハッシュ アルゴリズムの方が適している可能性があります。このアルゴリズムを使用すると、同じ URL へのリクエストが常に同じサーバーに割り当てられるためです。
- サーバーの数が頻繁に変更されるかどうか: サーバーの数が頻繁に変更される場合は、ラウンド ロビンまたは最小接続アルゴリズムの方が適している可能性があります。これら 2 つのアルゴリズムはサーバーの数に依存しないためです。
実際のアプリケーションでは、特定のニーズや環境条件に基づいて適切な負荷分散アルゴリズムを選択するか、複数の負荷分散アルゴリズムを組み合わせて使用することが必要な場合があります。
4. 負荷分散の適用実践
4.1. 負荷分散ソフトウェア
それでは、今後の返信では漢字と英語または数字の間にスペースを 1 つ入れます。負荷分散ハードウェアの答えは次のとおりです。
-
F5 BIG-IP: F5 BIG-IP は、高い市場シェアを持つハードウェア ロード バランサーです。SSL アクセラレーション、TCP 最適化、HTTP 圧縮、ファイアウォールなどの豊富な機能を提供します。F5 BIG-IP の利点は、強力なパフォーマンス、包括的な機能、および複雑な負荷分散戦略のサポートです。ただし、F5 BIG-IP の価格は高くなります。
-
A10 Networks: A10 Networks は、さまざまなハードウェア ロード バランサーを提供します。さまざまな負荷分散アルゴリズムをサポートし、SSL アクセラレーション、TCP 最適化、HTTP 圧縮などの豊富な機能を提供します。A10 Networks の利点は、強力なパフォーマンスと比較的低価格であることです。ただし、A10 Networks は市場シェアが低く、そのサポートとサービスは F5 BIG-IP ほど良くない可能性があります。
-
Radware Alteon: Radware Alteon は、SSL アクセラレーション、TCP 最適化、HTTP 圧縮、ファイアウォールなどの豊富な機能を提供するハードウェア ロード バランサーです。Radware Alteon の利点は、強力なパフォーマンスと複雑な負荷分散戦略のサポートです。ただし、Radware Alteon の価格は高くなります。
上記はいくつかの一般的な負荷分散ハードウェアですが、それぞれに独自の長所と短所があり、特定のアプリケーション シナリオとニーズに応じて選択する必要があります。
4.2. 負荷分散ハードウェア
負荷分散ソフトウェアには主に次の種類があります。
- Nginx: Nginx は、ロード バランサーとしても使用できるオープン ソース Web サーバーおよびリバース プロキシ サーバーです。Nginx は、ラウンド ロビン、最小接続、IP ハッシュなど、さまざまな負荷分散アルゴリズムをサポートしています。Nginx の利点は、高性能、シンプルな構成、高い同時実行性のサポート、静的リソースと短い接続の処理に適していることです。ただし、Nginx の負荷分散機能は比較的基本的なものであり、セッション永続性やヘルスチェックなどの一部の高度な機能はサポートしていません。
- HAProxy: HAProxy はオープン ソースのロード バランサーであり、主に高可用性、ロード バランシング、およびプロキシ サービスを提供するために使用されます。HAProxy は、ポーリング、最小接続数、ソース アドレス ハッシュなど、さまざまな負荷分散アルゴリズムをサポートしています。HAProxy の利点は、強力であり、セッション永続化、ヘルスチェック、SSL 終了などの高度な機能をサポートしていることです。ただし、HAProxy の構成は比較的複雑であり、パフォーマンスは Nginx よりもわずかに低くなります。
- LVS: LVS (Linux Virtual Server) は、Linux カーネルに基づくロード バランサーであり、主に高可用性およびロード バランシング サービスを提供するために使用されます。LVS は、ポーリング、最小接続数、ソース アドレス ハッシュなど、さまざまな負荷分散アルゴリズムをサポートしています。LVS の利点は、非常に高いパフォーマンスを備え、多数の同時接続をサポートし、長時間の接続や大量のトラフィックの処理に適していることです。ただし、LVS の構成は比較的複雑であり、Linux カーネルについてのある程度の理解が必要です。
- Traefik: Traefik は、主にマイクロサービス アーキテクチャで使用される最新の HTTP リバース プロキシおよびロード バランサーです。Traefik は、ポーリング、最小接続、ソース アドレス ハッシュなど、さまざまな負荷分散アルゴリズムをサポートしています。Traefik の利点は、動的構成をサポートし、Docker や Kubernetes などのコンテナ プラットフォームと適切に統合されていることです。ただし、Traefik のパフォーマンスは Nginx や HAProxy よりもわずかに低くなります。
上記はいくつかの一般的な負荷分散ソフトウェアですが、それぞれに独自の長所と短所があり、特定のアプリケーション シナリオとニーズに応じて選択する必要があります。
特徴 | アドバンテージ | 欠点がある | |
---|---|---|---|
Nginx | オープンソースの Web サーバーやリバース プロキシ サーバーもロード バランサとして使用できます。ポーリング、最小接続数、IP ハッシュなど、複数の負荷分散アルゴリズムをサポートします。 | 高性能、シンプルな構成を備え、高い同時実行性をサポートし、静的リソースや短い接続の処理に適しています。 | 負荷分散機能は比較的基本的なものであり、セッション永続性やヘルスチェックなどの一部の高度な機能はサポートしていません。 |
HAプロキシ | オープン ソースのロード バランサー。主に高可用性、ロード バランシング、プロキシ サービスを提供するために使用されます。ポーリング、最小接続数、ソース アドレス ハッシュなど、複数の負荷分散アルゴリズムをサポートします。 | 強力で、セッション永続性、ヘルスチェック、SSL 終了などの高度な機能をサポートします。 | 構成は比較的複雑で、パフォーマンスは Nginx よりわずかに低くなります。 |
LVS | Linux カーネルに基づくロード バランサー。主に高可用性サービスとロード バランシング サービスを提供するために使用されます。ポーリング、最小接続数、ソース アドレス ハッシュなど、複数の負荷分散アルゴリズムをサポートします。 | 非常に高いパフォーマンスを備え、多数の同時接続をサポートし、長時間の接続や大量のトラフィックの処理に適しています。 | 構成は比較的複雑であり、Linux カーネルについてのある程度の理解が必要です。 |
渋滞 | 最新の HTTP リバース プロキシとロード バランサー。主にマイクロサービス アーキテクチャで使用されます。ポーリング、最小接続数、ソース アドレス ハッシュなど、複数の負荷分散アルゴリズムをサポートします。 | 動的構成をサポートし、Docker や Kubernetes などのコンテナ プラットフォームと適切に統合されています。 | パフォーマンスは Nginx や HAProxy よりわずかに低くなります。 |
4.3. 有名なインターネット企業による負荷分散の実装
多くの有名なインターネット企業は、初期のアーキテクチャで Nginx、HAProxy、LVS、Traefik などのオープンソースの負荷分散テクノロジを使用していました。これらのテクノロジーは成熟し、安定しており、活発なコミュニティがあり、ほとんどの負荷分散のニーズを満たすことができます。
しかし、ビジネス規模の拡大と技術アーキテクチャの進化に伴い、これらの企業は、非常に大規模なネットワーク トラフィックを処理する必要性や、複雑な負荷分散戦略をサポートする必要性など、特別なニーズに遭遇することがよくあります。負荷分散テクノロジを研究するか、既存のオープンソース テクノロジに基づいてカスタマイズおよび最適化します。
有名なインターネット企業ごとの負荷分散テクノロジの実装には、それぞれ独自の特徴があります。いくつかの例を次に示します。
- Google: Google は独自の Google Cloud Load Balancing を使用しています。これは、大量のトラフィックを処理し、Google Cloud 上のアプリケーションやサービスに分散できる自動分散負荷分散サービスです。さらに、Google はデータセンターのネットワーク トラフィックを処理するために、Maglev と呼ばれるソフトウェア ロード バランサを開発しました。
- Facebook: Facebook は、大規模なネットワーク サービスを処理するために設計された Linux ベースのロード バランサである独自の Katran を使用しています。Katran は、Linux の eBPF テクノロジーを利用して、サービスを中断することなく負荷分散戦略を動的に変更します。
- Alibaba: Alibaba は、自社開発の Server Load Balancer を使用しています。これは、複数のバックエンド サーバーにトラフィックを分散できる、分散型、高性能、高可用性の負荷分散サービスです。さらに、アリババは、マイクロサービス アーキテクチャにおける負荷分散の問題を処理するために、Seata と呼ばれる分散トランザクション ミドルウェアもオープンソース化しました。
- Tencent: Tencent は自社開発のロード バランサーを使用しており、Tencent クラウド上のアプリケーションとサービスにトラフィックを自動的に分散できます。さらに、Tencent は負荷分散機能を備えた Tars と呼ばれる高性能 RPC フレームワークもオープンソース化しています。
- Baidu: Baidu は自社開発のロード バランサーを使用しており、Baidu クラウド上のアプリケーションとサービスにトラフィックを自動的に分散できます。さらに、Baidu は負荷分散機能を備えた BRPC と呼ばれる高性能 RPC フレームワークもオープンソース化しました。
4.4. 負荷分散の開発動向
負荷分散の開発傾向には主に次の方向性が含まれます。
- クラウド ネイティブとマイクロサービス: クラウド コンピューティングとマイクロサービス アーキテクチャの人気に伴い、負荷分散テクノロジもクラウド ネイティブに変わりつつあります。たとえば、Kubernetes などのコンテナ オーケストレーション プラットフォームには、サービス検出機能と負荷分散機能が組み込まれています。さらに、Envoy、Linkerd、Istio などの新しいロード バランサーも、マイクロサービスやクラウド ネイティブ環境向けに設計されています。
- インテリジェンスと自動化: 人工知能と機械学習テクノロジーの発展により、負荷分散もよりスマートになってきています。たとえば、トラフィックとサーバーのパフォーマンス データをリアルタイムで分析することで、負荷分散戦略を動的に調整して、システム パフォーマンスとリソースの使用率を最適化できます。
- セキュリティ: ネットワーク攻撃がますます蔓延しているため、ロード バランサーには、DDoS 攻撃や SQL インジェクションなどの防止など、より強力なセキュリティ保護機能も必要です。一部のロード バランサーは、Web アプリケーション ファイアウォール (WAF) などのセキュリティ機能を統合し始めています。
- マルチクラウドおよびハイブリッド クラウド: マルチクラウドおよびハイブリッド クラウド環境の普及に伴い、ロード バランサーは、さまざまなクラウド プラットフォームおよびデータ センターにわたって統合された負荷分散サービスを提供できる必要があります。
- パフォーマンスとスケーラビリティ: インターネット トラフィックが増大し続ける中、ロード バランサーは大規模なネットワーク トラフィックを処理するために、より高いパフォーマンスとスケーラビリティを備えている必要があります。