LoadBalancerClientは、SpringCloudによって提供される負荷分散クライアントです。リボン負荷分散コンポーネントは、LoadBalancerClientも統合して、負荷分散を実現します。では、LoadBalancerClientはどのように内部的にそれを行うのでしょうか?まず、LoadBalancerClientの実装原理について説明し、次にソースコードで分析します。
初期化中に、LoadBalancerClientはEurekaサーバーからEurekaクライアントを介してすべてのサービスインスタンスの登録情報を取得し、ローカルにキャッシュし、サービスの可用性を判断するために10秒ごとにEurekaClientに「ping」を送信します。サービスの可用性が変更された場合、またはサービスの数が以前と一致しない場合は、更新または再プルします。最後に、サービス登録リスト情報を取得した後、ILoadBalancerはIRuleのポリシー(デフォルトのポリシーはラウンドロビン)に従って負荷分散を実行します。
LoadBalancerClientを使用してリモート呼び出しの負荷分散を実行する場合、LoadBalancerClientは最初に、ターゲットサービス名を介してローカルサービス登録リスト内のサービスプロバイダーのインスタンスを取得します。たとえば、注文サービスは商品サービスにアクセスする必要があります。コモディティサービス、およびLoadBalancerClientが渡されますchoose()メソッドは、3つのノード間でサービスを取得します。サービス情報を取得した後、サービスIP情報を取得すると、アクセスする完全なIPアドレスとインターフェイスを取得できます。最後に、RestTempateを介して商品サービスにアクセスします。
LoadBalancerClientインターフェイスのソースコードの詳細な分析:
1. LoadBalancerClientソースコード分析:
LoadBalancerClientは、Spring Cloudによって提供される非常に重要なインターフェイスであり、ServiceInstanceChooserインターフェイスを継承します。このインターフェイスの実装クラスはRibbonLoadBalanceClientです。これらの関係を次の図に示します。
(1)LoadBalancerClientインターフェイスのソースコード:
まず、LoadBalancerClientソースコードの追跡を開始します。
public interface LoadBalancerClient extends ServiceInstanceChooser
{
<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
URI reconstructURI(ServiceInstance instance, URI original);
}
LoadBalancerClientインターフェイスはServiceInstanceChooserインターフェイスを継承し、メインメソッドは2つのexecute()メソッドであり、どちらもリクエストの実行に使用されます。URLを再構築するために使用されるreconstructURI()もあります。
(2)ServiceInstanceChooserインターフェースのソースコード:
次のように、LoadBalancerClientによって継承されたServiceInstanceChooserインターフェイスのソースコードを引き続き表示します。
public interface ServiceInstanceChooser
{
ServiceInstance choose(String serviceId);
}
ServiceInstanceChooserインターフェイスのメインメソッドはchoose()です。これは、サービス名serviceIdに従ってサービスインスタンスの1つを選択するため、つまりserviceIdに従ってServiceInstanceを取得するために使用されます。
(3)RibbonLoadBalanceClient実装クラスのソースコード:
次に、LoadBalancerClientのRibbonLoadBalanceClient実装クラスを見てみましょう。これは、最終的な負荷分散要求を実行するために使用されます。その中で、RibbonLoadBalanceClientのchoose()メソッドは、getServer()メソッドを介してILoadBalancerによって内部的に完了する特定のサービスインスタンスを選択するために使用されます。まず、RibbonLoadBalanceClientのいくつかの重要な実装メソッドのソースコードを見てみましょう。
①最初のもの:特定のサービスインスタンスを選択するために使用されるchoose()。
@Override
public ServiceInstance choose(String serviceId) {
return choose(serviceId, null);
}
/**
* New: Select a server using a 'key'.
* @param serviceId of the service to choose an instance for
* @param hint to specify the service instance
* @return the selected {@link ServiceInstance}
*/
public ServiceInstance choose(String serviceId, Object hint) {
Server server = getServer(getLoadBalancer(serviceId), hint);
if (server == null) {
return null;
}
return new RibbonServer(serviceId, server, isSecure(server, serviceId),
serverIntrospector(serviceId).getMetadata(server));
}
②2番目:getServer()、インスタンスを取得します。
protected Server getServer(ILoadBalancer loadBalancer) {
return getServer(loadBalancer, null);
}
protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
if (loadBalancer == null) {
return null;
}
// 最终通过 loadBalancer 去做服务实例的选择。
// Use 'default' on a null hint, or just pass it on?
return loadBalancer.chooseServer(hint != null ? hint : "default");
}
サービスインスタンスの選択が最終的にloadBalancerを介して行われることがわかります。次に、loadBalancerがサービスインスタンスの選択をどのように実装するかを見てみましょう。
(4)BaseLoadBalancerソースコード:
上記から、ILoadBalancerのchooseServerメソッドのデフォルト値がデフォルトであることがわかります。ILoadBalancer実装クラスBaseLoadBalancerのchooseServer()を入力して、以下を参照してください。
キーの値は「デフォルト」ですが、このキーはどういう意味ですか?ルールオブジェクトに移動して、以下を参照してください。
このルールはIRuleインターフェースによって宣言されており、デフォルトで定義されている実装クラスは、ポーリング戦略であるRoundRobinRule()であることがわかります。次に、IRuleインターフェイスを見てみましょう。
(5)IRuleインターフェースのソースコード:
public interface IRule{
/*
* choose one alive server from lb.allServers or
* lb.upServers according to key
*
* @return choosen Server object. NULL is returned if none
* server is available
*/
public Server choose(Object key);
public void setLoadBalancer(ILoadBalancer lb);
public ILoadBalancer getLoadBalancer();
}
IRuleインターフェイスが3つのメソッドを定義していることがわかります。選択()はインスタンスの選択に使用され、setLoadBalancer()とgetLoadBalance()はILoadBalancerの設定と取得に使用されます。次に、IRuleインターフェイスにはいくつの実装クラスがありますか。
(1)ランダム戦略RandomRule:乱数は、サービスリストでサービスノードサーバーを選択します。現在のノードが利用できない場合は、利用可能なサービスノードが選択されるまで次のランダム戦略を入力します。
(2)Round RobinRule:受信したリクエストの順序に従って、異なるバックエンドサーバーに1つずつ割り当てられます
(3)再試行戦略RetryRule:選択した負荷分散戦略マシンで再試行メカニズム。構成期間内にサーバーの選択が失敗した場合、常にsubRuleメソッドを使用して使用可能なサーバーを選択しようとします。
(4)利用可能なフィルタリング戦略PredicateBaseRule:接続障害と同時接続数の多いサービスノードを除外し、線形ポーリング方式で正常なサービスノードからノードを選択して戻ります
(5)応答時間の重み戦略WeightedRespinseTimeRule:サーバーの応答時間に応じて重みを割り当てます。応答時間が長いほど、重みは小さくなり、選択される可能性は低くなります。主にバックグラウンドスレッドを介して、ステータスから平均応答時間を定期的に読み取り、各サーバーの重みを計算します
(6)BestAvailableRule:同時実行性が最小のサービスノードサーバーを選択します。ServerStatsのactiveRequestCountプロパティは、サーバーの同時実行性を記録し、すべてのサーバーをポーリングして、同時実行性が最小のサービスノードであるactiveRequestCountが最小のサーバーを選択します。この戦略の利点は、各サービスノードの負荷を十分に考慮することができ、要求が最小の負荷圧力でサービスノードに送信されることです。ただし、欠点は、すべてのサービスノードをポーリングする必要があることです。クラスターの数が多すぎると、時間がかかります。
(7)ゾーンウェイト戦略ZoneAvoidanceRule:サーバーが配置されているリージョンのパフォーマンスとサーバーの可用性を包括的に判断し、ZoneAvoidancePredicateとAvailabilityPredicateを使用してサーバーを選択するかどうかを判断します。前者は、ゾーンのパフォーマンスが利用可能かどうかを判断します。 、および使用できないゾーン(すべてのサーバー)を除外します。AvailabilityPredicateは、接続数が多すぎるサーバーを除外するために使用されます。
同様に、IRuleインターフェイスを実装することで負荷分散戦略をカスタマイズできる場合。
2. ILoadBalancerソースコード分析:
ILoadBalancerは、負荷分散を実装するための一連のメソッドを定義するインターフェイスです。LoadBalancerClientの実装クラスであるRibbonLoadBalanceClientも、負荷分散の特定の実装を処理のためにILoadBalancerに渡します。ILoadBalancerは、IRule、IPingなどを構成することによってEurekaClientから登録リスト情報を取得します。 。、デフォルトでは、10秒ごとにEurekaClientに「ping」を送信し、サービスの登録リスト情報を更新する必要があるかどうかを確認します。最後に、サービス登録リスト情報を取得した後、ILoadBalancerはIRuleのポリシーに従って負荷分散を実行します。ILoadBalancerインターフェイスの実装クラスの結果を次の図に示します。
BaseLoadBalancerとDynamicServerListLoadBalancerのソースコードを見ると、次の構成がデフォルトで実装されています。
(1)IClientConfig clientConfig:負荷分散クライアントを構成するために使用されます。デフォルトの実装クラスはDefaultClientConfigImplです。
(2)IRuleルール:負荷分散の構成に使用される戦略。デフォルトでは、RoundRobinRuleポーリング戦略が使用されます。
(3)IPing ping:現在のサービスが利用可能かどうかを判断するために、現在のサービスに応答があるかどうかを確認するために使用されます。デフォルトの実装クラスはDummyPingです。この実装クラスのisAlive()メソッドの戻り値trueであり、すべてのサービスインスタンスがデフォルトで使用可能です。
(4)ServerList serverList:すべてのサーバー登録リスト情報を取得するために使用されます。ソースコードをたどると、ServerListの実装クラスがDiscoveryEnabledNIWSServerListであることがわかります。このクラスで定義されているgettainServersViaDiscovery()メソッドは、eurekaClientProvider.get()メソッドに従ってEurekaClientを取得し、サービス登録リスト情報を取得します。 EurekaClientによると。EurekaClientの実装クラスはDiscoveryClientです。DiscoveryClientには、サービス登録やサービス登録リストの取得などの機能があります。
(5)ServerListFilterフィルター:構成に従ってフィルター処理されるか、動的に取得される適格なサービスのリストを定義します。デフォルトの実装クラスはZonePreferenceServerListFilterであり、要求元の呼び出し元と同じゾーン内のサービスインスタンスを優先的にフィルターで除外できます。