Spring Cloud LoadBalancer

Spring Cloud は、独自のクライアント側ロードバランサーの抽象化と実装を提供します。負荷分散メカニズムについては、ReactiveLoadBalancer インターフェースが追加され、ラウンドロビンベースおよびランダム実装が提供されています。リアクティブから選択するインスタンスを取得するには、ServiceInstanceListSupplier が使用されます。現在、クラスパスで使用可能なディスカバリクライアントを使用してサービスディスカバリから利用可能なインスタンスを取得する、サービスディスカバリベースの ServiceInstanceListSupplier 実装をサポートしています。

spring.cloud.loadbalancer.enabled の値を false に設定することで、Spring Cloud LoadBalancer を無効にすることができます。

LoadBalancer コンテキストの積極的なロード

Spring Cloud LoadBalancer は、サービス ID ごとに個別の Spring 子コンテキストを作成します。デフォルトでは、サービス ID に対する最初のリクエストが負荷分散されるたびに、これらのコンテキストは遅延初期化されます。

これらのコンテキストを積極的にロードすることを選択できます。そのためには、spring.cloud.loadbalancer.eager-load.clients プロパティを使用して、積極的にロードするサービス ID を指定します。例:

spring.cloud-loadbalancer.eager-load.clients[0]=my-first-client
spring.cloud-loadbalancer.eager-load.clients[1]=my-second-client

負荷分散アルゴリズムの切り替え

デフォルトで使用される ReactiveLoadBalancer 実装は RoundRobinLoadBalancer です。選択したサービスまたはすべてのサービスを別の実装に切り替えるには、カスタム LoadBalancer 構成メカニズムを使用できます。

例: 次の設定を @LoadBalancerClient アノテーション経由で渡して、RandomLoadBalancer の使用に切り替えることができます。

public class CustomLoadBalancerConfiguration {

	@Bean
	ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
			LoadBalancerClientFactory loadBalancerClientFactory) {
		String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
		return new RandomLoadBalancer(loadBalancerClientFactory
				.getLazyProvider(name, ServiceInstanceListSupplier.class),
				name);
	}
}
@LoadBalancerClient または @LoadBalancerClients 構成引数として渡すクラスは、@Configuration のアノテーションが付けられていないか、コンポーネントのスキャン範囲外である必要があります。

Spring Cloud LoadBalancer の統合

Spring Cloud LoadBalancer を簡単に使用できるように、ReactorLoadBalancerExchangeFilterFunction ( WebClient で使用可能) および BlockingLoadBalancerClient (RestTemplate および RestClient で使用可能) を提供します。詳細と使用例については、次のセクションで説明します。

Spring Cloud LoadBalancer キャッシング

インスタンスを選択する必要があるたびに DiscoveryClient 経由でインスタンスを取得する基本的な ServiceInstanceListSupplier 実装とは別に、2 つのキャッシュ実装が提供されています。

Caffeine [GitHub] (英語) - バックアップされた LoadBalancer キャッシュ実装

クラスパスに com.github.ben-manes.caffeine:caffeine がある場合は、Caffeine ベースの実装が使用されます。設定方法については、"LoadBalancerCacheConfiguration" セクションを参照してください。

Caffeine を使用している場合は、spring.cloud.loadbalancer.cache.caffeine.spec プロパティに独自の Caffeine 仕様 (英語) を渡すことで、LoadBalancer のデフォルトの Caffeine キャッシュ設定をオーバーライドすることもできます。

WARN: 独自の Caffeine 仕様を渡すと、ttl や capacity などの一般的な LoadBalancer キャッシュ構成フィールドを含む他の LoadBalancerCache 設定がオーバーライドされます。

デフォルトの LoadBalancer キャッシュ実装

クラスパスに Caffeine がない場合は、spring-cloud-starter-loadbalancer に自動的に付属する DefaultLoadBalancerCache が使用されます。設定方法については、"LoadBalancerCacheConfiguration" セクションを参照してください。

デフォルトのキャッシュの代わりに Caffeine を使用するには、クラスパスに com.github.ben-manes.caffeine:caffeine 依存関係を追加します。

LoadBalancer キャッシュ構成

spring.cloud.loadbalancer.cache.ttl プロパティの値として Spring Boot String から Duration へのコンバーターの構文に準拠した String を渡すことで、Duration で表される独自の ttl 値(書き込み後、エントリの有効期限が切れるまでの時間)を設定できます。また、spring.cloud.loadbalancer.cache.capacity プロパティの値を設定することで、独自の LoadBalancer キャッシュ初期容量を設定することもできます。

デフォルトの設定には、35 秒に設定された ttl が含まれており、デフォルトの initialCapacity は 256 です。

spring.cloud.loadbalancer.cache.enabled の値を false に設定することで、loadBalancer キャッシュを完全に無効にすることもできます。

基本的なキャッシュされていない実装はプロトタイピングやテストには役立ちますが、キャッシュされたバージョンよりも効率がはるかに低いため、運用環境では常にキャッシュされたバージョンを使用することをお勧めします。DiscoveryClient 実装 ( EurekaDiscoveryClient など) によってキャッシュがすでに行われている場合は、二重キャッシュを防ぐためにロードバランサーのキャッシュを無効にする必要があります。
独自の構成を作成する場合、CachingServiceInstanceListSupplier を使用する場合は、ネットワーク経由でインスタンスを取得するサプライヤー ( DiscoveryClientServiceInstanceListSupplier など) の直後の階層内で、他のフィルタリングサプライヤーの前に必ず配置してください。

加重負荷分散

加重ロードバランシングを有効にするために、WeightedServiceInstanceListSupplier が提供されています。WeightFunction を使用して各インスタンスの重みを計算します。デフォルトでは、メタデータマップから重みを読み取って解析しようとします (キーは weight)。

メタデータマップで重みが指定されていない場合、このインスタンスの重みはデフォルトで 1 になります。

これを構成するには、spring.cloud.loadbalancer.configurations の値を weighted に設定するか、独自の ServiceInstanceListSupplier Bean を指定します。例:

public class CustomLoadBalancerConfiguration {

	@Bean
	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
			ConfigurableApplicationContext context) {
		return ServiceInstanceListSupplier.builder()
					.withDiscoveryClient()
					.withWeighted()
					.withCaching()
					.build(context);
	}
}
WeightFunction を提供することで、重み計算ロジックをカスタマイズすることもできます。

このサンプル構成を使用すると、すべてのインスタンスにランダムな重みを持たせることができます。

public class CustomLoadBalancerConfiguration {

	@Bean
	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
			ConfigurableApplicationContext context) {
		return ServiceInstanceListSupplier.builder()
					.withDiscoveryClient()
					.withWeighted(instance -> ThreadLocalRandom.current().nextInt(1, 101))
					.withCaching()
					.build(context);
	}
}

ゾーンベースの負荷分散

ゾーンベースの負荷分散を有効にするために、ZonePreferenceServiceInstanceListSupplier が提供されています。DiscoveryClient -specific zone 構成 (たとえば、eureka.instance.metadata-map.zone) を使用して、クライアントが利用可能なサービスインスタンスをフィルタリングしようとするゾーンを選択します。

spring.cloud.loadbalancer.zone プロパティの値を設定することで、DiscoveryClient -specific ゾーン設定をオーバーライドすることもできます。
当面は、LoadBalancer ゾーンを設定するために Eureka Discovery Client のみが装備されています。他の検出クライアントの場合は、spring.cloud.loadbalancer.zone プロパティを設定します。さらに多くの機器が間もなく登場します。
取得した ServiceInstance のゾーンを判断するには、そのメタデータマップ内の "zone" キーの値を確認します。

ZonePreferenceServiceInstanceListSupplier は、取得したインスタンスをフィルタリングし、同じゾーン内のインスタンスのみを返します。ゾーンが null である場合、または同じゾーン内にインスタンスがない場合は、取得されたすべてのインスタンスが返されます。

ゾーンベースの負荷分散アプローチを使用するには、カスタム構成で ZonePreferenceServiceInstanceListSupplier Bean をインスタンス化する必要があります。

ServiceInstanceListSupplier Bean を操作するためにデリゲートを使用します。DiscoveryClientServiceInstanceListSupplier デリゲートを使用し、それを CachingServiceInstanceListSupplier でラップして LoadBalancer キャッシュメカニズムを利用し、結果の Bean を ZonePreferenceServiceInstanceListSupplier のコンストラクターに渡すことをお勧めします。

このサンプル構成を使用してセットアップできます。

public class CustomLoadBalancerConfiguration {

	@Bean
	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
			ConfigurableApplicationContext context) {
		return ServiceInstanceListSupplier.builder()
					.withDiscoveryClient()
                    .withCaching()
					.withZonePreference()
					.build(context);
	}
}

LoadBalancer のインスタンスのヘルスチェック

LoadBalancer に対してスケジュールされた HealthCheck を有効にすることができます。HealthCheckServiceInstanceListSupplier はそのために提供されています。デリゲート ServiceInstanceListSupplier によって提供されたインスタンスがまだ生きているかどうかを定期的に確認し、正常なインスタンスのみを返します (存在しない場合は、取得したすべてのインスタンスを返します)。

このメカニズムは、SimpleDiscoveryClient を使用する場合に特に役立ちます。実際のサービスレジストリによってサポートされているクライアントの場合、外部 ServiceDiscovery にクエリを実行した後、正常なインスタンスがすでに取得されているため、サービスレジストリを使用する必要はありません。
このサプライヤーは、失敗したインスタンスでの呼び出しの再試行を避けるために、サービスあたりのインスタンス数が少ないセットアップにも推奨されます。
サービスディスカバリがサポートするサプライヤーを使用している場合は、インスタンスの健全性状態を Service Registry から直接取得するため、通常、この健全性チェックメカニズムを追加する必要はありません。
HealthCheckServiceInstanceListSupplier は、デリゲート flux によって提供されるリフレッシュされたインスタンスに依存しています。インスタンスのリストが変更される可能性があるにもかかわらず、インスタンスをリフレッシュしないデリゲート (当社が提供する DiscoveryClientServiceInstanceListSupplier など) を使用するまれなケースでは、spring.cloud.loadbalancer.health-check.refetch-instances を true に設定して、インスタンスリストを HealthCheckServiceInstanceListSupplier によってリフレッシュすることができます。その後、spring.cloud.loadbalancer.health-check.refetch-instances-interval の値を変更して再フェッチ間隔を調整し、spring.cloud.loadbalancer.health-check.repeat-health-check を false に設定して追加のヘルスチェックの繰り返しを無効にすることもできます。これは、インスタンスの再フェッチごとにヘルスチェックもトリガーされるためです。

HealthCheckServiceInstanceListSupplier は、spring.cloud.loadbalancer.health-check という接頭辞が付いているプロパティを使用します。スケジューラーには initialDelay と interval を設定できます。spring.cloud.loadbalancer.health-check.path.default プロパティの値を設定することで、ヘルスチェック URL のデフォルトのパスを設定できます。spring.cloud.loadbalancer.health-check.path.[SERVICE_ID] プロパティの値を設定し、[SERVICE_ID] をサービスの正しい ID に置き換えることにより、特定のサービスに特定の値を設定することもできます。[SERVICE_ID] が指定されていない場合は、デフォルトで /actuator/health が使用されます。[SERVICE_ID] が null に設定されている場合、または値が空の場合、ヘルスチェックは実行されません。spring.cloud.loadbalancer.health-check.port の値を設定することで、ヘルスチェックリクエスト用のカスタムポートを設定することもできます。何も設定されていない場合、リクエストされたサービスをサービスインスタンスで使用できるポート。

デフォルトのパス (/actuator/health) に依存する場合は、そのようなエンドポイントを独自に追加する予定がない限り、必ず spring-boot-starter-actuator をコラボレーターの依存関係に追加してください。
デフォルトでは、healthCheckFlux は取得された各生存 ServiceInstance に対して発行します。この動作は、spring.cloud.loadbalancer.health-check.update-results-list の値を false に設定することで変更できます。このプロパティが false に設定されている場合、生存インスタンスのシーケンス全体が最初にリストに収集され、その後発行されます。これにより、プロパティで設定されたヘルスチェック間隔の間に flux が値を発行しないことが保証されます。

ヘルスチェックスケジューラのアプローチを使用するには、カスタム構成で HealthCheckServiceInstanceListSupplier Bean をインスタンス化する必要があります。

ServiceInstanceListSupplier Bean を操作するためにデリゲートを使用します。HealthCheckServiceInstanceListSupplier のコンストラクターで DiscoveryClientServiceInstanceListSupplier デリゲートを渡すことをお勧めします。

このサンプル構成を使用してセットアップできます。

public class CustomLoadBalancerConfiguration {

	@Bean
	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
			ConfigurableApplicationContext context) {
		return ServiceInstanceListSupplier.builder()
					.withDiscoveryClient()
					.withHealthChecks()
					.build(context);
	    }
	}
非リアクティブスタックの場合は、withBlockingHealthChecks() を使用してこのサプライヤーを作成します。チェックに使用する独自の WebClientRestTemplate、または RestClient インスタンスを渡すこともできます。
HealthCheckServiceInstanceListSupplier には、Reactor Flux replay() に基づく独自のキャッシュメカニズムがあります。これが使用されている場合は、そのサプライヤーを CachingServiceInstanceListSupplier でラップするのをスキップすることをお勧めします。
独自の構成 HealthCheckServiceInstanceListSupplier を作成する場合は、ネットワーク経由でインスタンスを取得するサプライヤー ( DiscoveryClientServiceInstanceListSupplier など) の直後の階層内で、他のフィルタリングサプライヤーの前に必ず配置してください。

LoadBalancer の同じインスタンス設定

以前に選択されたインスタンスが使用可能な場合、そのインスタンスが優先されるように LoadBalancer をセットアップできます。

そのためには、SameInstancePreferenceServiceInstanceListSupplier を使用する必要があります。これを構成するには、spring.cloud.loadbalancer.configurations の値を same-instance-preference に設定するか、独自の ServiceInstanceListSupplier Bean を指定します。たとえば、次のようになります。

public class CustomLoadBalancerConfiguration {

	@Bean
	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
			ConfigurableApplicationContext context) {
		return ServiceInstanceListSupplier.builder()
					.withDiscoveryClient()
					.withSameInstancePreference()
					.build(context);
	    }
	}
これも Zookeeper StickyRule の代替です。

LoadBalancer のリクエストベースのスティッキーセッション

リクエスト Cookie で提供される instanceId を持つインスタンスが優先されるように LoadBalancer をセットアップできます。現在、リクエストが ClientRequestContext または ServerHttpRequestContext を介して LoadBalancer に渡される場合、これはサポートされています。これらは SC LoadBalancer 交換フィルター関数およびフィルターによって使用されます。

そのためには、RequestBasedStickySessionServiceInstanceListSupplier を使用する必要があります。これを構成するには、spring.cloud.loadbalancer.configurations の値を request-based-sticky-session に設定するか、独自の ServiceInstanceListSupplier Bean を指定します。たとえば、次のようになります。

public class CustomLoadBalancerConfiguration {

	@Bean
	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
			ConfigurableApplicationContext context) {
		return ServiceInstanceListSupplier.builder()
					.withDiscoveryClient()
					.withRequestBasedStickySession()
					.build(context);
	    }
	}

この機能では、リクエストを転送する前に、選択したサービスインスタンス (元のリクエスト Cookie が使用できない場合は、そのサービスインスタンスと異なる可能性があります) を更新できると便利です。これを行うには、spring.cloud.loadbalancer.sticky-session.add-service-instance-cookie の値を true に設定します。

デフォルトでは、Cookie の名前は sc-lb-instance-id です。spring.cloud.loadbalancer.instance-id-cookie-name プロパティの値を変更することで変更できます。

この機能は現在、WebClient ベースのロードバランシングでサポートされています。

Spring Cloud LoadBalancer ヒント

Spring Cloud LoadBalancer を使用すると、Request オブジェクト内の LoadBalancer に渡され、後で処理できる ReactiveLoadBalancer 実装で使用できる String ヒントを設定できます。

spring.cloud.loadbalancer.hint.default プロパティの値を設定することで、すべてのサービスのデフォルトのヒントを設定できます。spring.cloud.loadbalancer.hint.[SERVICE_ID] プロパティの値を設定し、[SERVICE_ID] をサービスの正しい ID に置き換えることにより、特定のサービスに特定の値を設定することもできます。ユーザーがヒントを設定しない場合は、default が使用されます。

ヒントベースの負荷分散

また、ヒントベースのインスタンス選択のための ServiceInstanceListSupplier 実装である HintBasedServiceInstanceListSupplier も提供します。

HintBasedServiceInstanceListSupplier は、ヒントリクエストヘッダー (デフォルトのヘッダー名は X-SC-LB-Hint ですが、spring.cloud.loadbalancer.hint-header-name プロパティの値を変更することで変更できます) をチェックし、ヒントリクエストヘッダーが見つかった場合は、ヘッダーに渡されたヒント値を使用してフィルターします。サービスインスタンス。

ヒントヘッダーが追加されていない場合、HintBasedServiceInstanceListSupplier はプロパティからのヒント値を使用してサービスインスタンスをフィルターします。

ヘッダーまたはプロパティによってヒントが設定されていない場合は、デリゲートによって提供されたすべてのサービスインスタンスが返されます。

フィルタリング中に、HintBasedServiceInstanceListSupplier は、metadataMap の hint キーに設定された一致する値を持つサービスインスタンスを検索します。一致するインスタンスが見つからない場合は、デリゲートによって提供されたすべてのインスタンスが返されます。

次のサンプル構成を使用してセットアップできます。

public class CustomLoadBalancerConfiguration {

	@Bean
	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
			ConfigurableApplicationContext context) {
		return ServiceInstanceListSupplier.builder()
					.withDiscoveryClient()
                    .withCaching()
					.withHints()
					.build(context);
	}
}

負荷分散された HTTP リクエストを変換する

選択した ServiceInstance を使用して、負荷分散された HTTP リクエストを変換できます。

RestTemplate および RestClient の場合、次のように LoadBalancerRequestTransformer を実装して定義する必要があります。

@Bean
public LoadBalancerRequestTransformer transformer() {
	return new LoadBalancerRequestTransformer() {
		@Override
		public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) {
			return new HttpRequestWrapper(request) {
				@Override
				public HttpHeaders getHeaders() {
					HttpHeaders headers = new HttpHeaders();
					headers.putAll(super.getHeaders());
					headers.add("X-InstanceId", instance.getInstanceId());
					return headers;
				}
			};
		}
	};
}

WebClient の場合、次のように LoadBalancerClientRequestTransformer を実装して定義する必要があります。

@Bean
public LoadBalancerClientRequestTransformer transformer() {
	return new LoadBalancerClientRequestTransformer() {
		@Override
		public ClientRequest transformRequest(ClientRequest request, ServiceInstance instance) {
			return ClientRequest.from(request)
					.header("X-InstanceId", instance.getInstanceId())
					.build();
		}
	};
}

複数のトランスフォーマが定義されている場合、Bean が定義されている順序で適用されます。または、LoadBalancerRequestTransformer.DEFAULT_ORDER または LoadBalancerClientRequestTransformer.DEFAULT_ORDER を使用して順序を指定することもできます。

Spring Cloud LoadBalancer サブセット

SubsetServiceInstanceListSupplier は、決定論的なサブセットアルゴリズム (英語) を実装して、ServiceInstanceListSupplier デリゲート階層内の限られた数のインスタンスを選択します。

これを構成するには、spring.cloud.loadbalancer.configurations の値を subset に設定するか、独自の ServiceInstanceListSupplier Bean を指定します。たとえば、次のようになります。

public class CustomLoadBalancerConfiguration {

	@Bean
	public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
			ConfigurableApplicationContext context) {
		return ServiceInstanceListSupplier.builder()
					.withDiscoveryClient()
					.withSubset()
					.withCaching()
					.build(context);
	    }
	}
デフォルトでは、各サービスインスタンスには一意の instanceId が割り当てられ、多くの場合、異なる instanceId 値により異なるサブセットが選択されます。通常は特に注意する必要はありません。ただし、複数のインスタンスに同じサブセットを選択させる必要がある場合は、spring.cloud.loadbalancer.subset.instance-id (プレースホルダーをサポートする) を使用して設定できます。
デフォルトでは、サブセットのサイズは 100 に設定されています。spring.cloud.loadbalancer.subset.size を使用して設定することもできます。

Spring Cloud LoadBalancer スターター

Spring Boot アプリに Spring Cloud LoadBalancer を簡単に追加できるスターターも提供しています。これを使用するには、ビルドファイルの Spring Cloud 依存関係に org.springframework.cloud:spring-cloud-starter-loadbalancer を追加するだけです。

Spring Cloud LoadBalancer スターターには、Spring Boot キャッシングおよびエヴィクター [GitHub] (英語) が含まれます。

独自の Spring Cloud LoadBalancer 構成を渡す

次のように、@LoadBalancerClient アノテーションを使用して、ロードバランサークライアントの名前と構成クラスを渡して、独自のロードバランサークライアント構成を渡すこともできます。

@Configuration
@LoadBalancerClient(value = "stores", configuration = CustomLoadBalancerConfiguration.class)
public class MyConfiguration {

	@Bean
	@LoadBalanced
	public WebClient.Builder loadBalancedWebClientBuilder() {
		return WebClient.builder();
	}
}
独自の LoadBalancer 構成での作業を容易にするために、ServiceInstanceListSupplier クラスに builder() メソッドを追加しました。
また、spring.cloud.loadbalancer.configurations プロパティの値を zone-preference に設定して ZonePreferenceServiceInstanceListSupplier をキャッシュとともに使用するか、health-check に設定して HealthCheckServiceInstanceListSupplier をキャッシュとともに使用することにより、デフォルトの構成の代わりに代替の事前定義された構成を使用することもできます。

この機能を使用すると、ユーザーが作成した、またはデフォルト設定をオーバーライドするための代替手段 (たとえば ZonePreferenceServiceInstanceListSupplier) として当社が提供した ServiceInstanceListSupplier または ReactorLoadBalancer のさまざまな実装をインスタンス化できます。

カスタム構成の例はここで見ることができます。

アノテーション value 引数 (上記の例では stores ) は、指定されたカスタム構成でリクエストを送信する必要があるサービスのサービス ID を指定します。

次の例に示すように、@LoadBalancerClients アノテーションを介して複数の構成 (複数のロードバランサークライアント用) を渡すこともできます。

@Configuration
@LoadBalancerClients({@LoadBalancerClient(value = "stores", configuration = StoresLoadBalancerClientConfiguration.class), @LoadBalancerClient(value = "customers", configuration = CustomersLoadBalancerClientConfiguration.class)})
public class MyConfiguration {

	@Bean
	@LoadBalanced
	public WebClient.Builder loadBalancedWebClientBuilder() {
		return WebClient.builder();
	}
}
@LoadBalancerClient または @LoadBalancerClients 構成引数として渡すクラスは、@Configuration のアノテーションが付けられていないか、コンポーネントのスキャン範囲外である必要があります。
独自の構成を作成する場合、CachingServiceInstanceListSupplier または HealthCheckServiceInstanceListSupplier を使用する場合は、両方ではなくどちらか一方を使用し、ネットワーク経由でインスタンスを取得するサプライヤーの直後の階層(たとえば DiscoveryClientServiceInstanceListSupplier など)に、他のフィルタリングサプライヤーよりも前に配置するようにしてください。

Spring Cloud LoadBalancer ライフサイクル

カスタム LoadBalancer 構成を使用して登録すると便利な Bean の型の 1 つは LoadBalancerLifecycle です。

LoadBalancerLifecycle Bean は、onStart(Request<RC> request)onStartRequest(Request<RC> request, Response<T> lbResponse)onComplete(CompletionContext<RES, T, RC> completionContext) という名前のコールバックメソッドを提供します。これを実装して、ロードバランシングの前後に実行するアクションを指定する必要があります。

onStart(Request<RC> request) は Request オブジェクトをパラメーターとして受け取ります。これには、ダウンストリームクライアントのリクエストやヒントなど、適切なインスタンスを選択するために使用されるデータが含まれています。onStartRequest は、Request オブジェクトに加えて、Response<T> オブジェクトもパラメーターとして受け取ります。一方、CompletionContext オブジェクトは onComplete(CompletionContext<RES, T, RC> completionContext) メソッドに提供されます。これには、選択したサービスインスタンス、そのサービスインスタンスに対して実行されたリクエストの Status、(利用可能な場合) ダウンストリームクライアントに返されたレスポンス、(例外が発生した場合) 対応する Throwable を含む LoadBalancer Response が含まれます。

supports(Class requestContextClass, Class responseClass, Class serverTypeClass) メソッドを使用すると、問題のプロセッサーが指定された型のオブジェクトを処理するかどうかを判断できます。ユーザーによってオーバーライドされていない場合は、true を返します。

前述のメソッド呼び出しでは、RC は RequestContext 型を意味し、RES はクライアントレスポンス型を意味し、T は返されたサーバー型を意味します。

Spring Cloud LoadBalancer 統計

MicrometerStatsLoadBalancerLifecycle と呼ばれる LoadBalancerLifecycle Bean が提供されており、これは Micrometer を使用して負荷分散された呼び出しの統計を提供します。

この Bean をアプリケーションコンテキストに追加するには、spring.cloud.loadbalancer.stats.micrometer.enabled の値を true に設定し、MeterRegistry を使用できるようにします (たとえば、プロジェクトに Spring Boot Actuator を追加します)。

MicrometerStatsLoadBalancerLifecycle は次のメーターを MeterRegistry に登録します。

  • loadbalancer.requests.active: 任意のサービスインスタンスの現在アクティブなリクエストの数を監視できるゲージ (サービスインスタンスデータはタグ経由で利用可能)。

  • loadbalancer.requests.success: 基礎となるクライアントにレスポンスを渡して終了した、負荷分散されたリクエストの実行時間を測定するタイマー。

  • loadbalancer.requests.failed: 例外で終了した負荷分散されたリクエストの実行時間を測定するタイマー。

  • loadbalancer.requests.discard: 破棄された負荷分散リクエスト、つまりリクエストを実行するサービスインスタンスが LoadBalancer によって取得されていないリクエストの数を測定するカウンター。

サービスインスタンス、リクエストデータ、レスポンスデータに関する追加情報は、利用可能な場合には常にタグを介してメトリクスに追加されます。

WebClient および RestClient -backed 負荷分散の場合、使用可能な場合は常に uri タグに uriTemplate を使用します。
spring.cloud.loadbalancer.stats.include-path を false に設定することで、path から uri タグの追加を無効にすることができます。
RestTemplate -backed ロードバランシングと同様に、uriTemplate にはアクセスできません。uri タグでは常にフルパスが使用されます。高カーディナリティの課題を回避するために、パスが高カーディナリティ値である場合 (たとえば、/orders/{id} で、id が多数の値を取る場合)、spring.cloud.loadbalancer.stats.include-path を false に設定して、uri タグへのパスの追加を無効にすることを強くお勧めします。
BlockingLoadBalancerClient などの一部の実装では、引数からジェネリクス型を確立し、型を判断してデータを読み取ることができない可能性があるため、リクエストデータとレスポンスデータが利用できない場合があります。
特定のメーターに少なくとも 1 つのレコードが追加されると、メーターはレジストリに登録されます。
MeterFilters を追加することで、これらのメトリクスの動作をさらに構成できます ( 公開パーセンタイルやヒストグラム (英語) の追加など)。

個別の LoadBalancerClients の構成

個々のロードバランサークライアントは、異なるプレフィックス spring.cloud.loadbalancer.clients.<clientId>. を使用して個別に構成できます。clientId はロードバランサーの名前です。デフォルトの構成値は spring.cloud.loadbalancer. 名前空間で設定でき、優先されるクライアント固有の値とマージされます。

application.yml
spring:
  cloud:
    loadbalancer:
      health-check:
        initial-delay: 1s
      clients:
        myclient:
          health-check:
            interval: 30s

上記の例では、initial-delay=1s および interval=30s とマージされたヘルスチェック @ConfigurationProperties オブジェクトが生成されます。

クライアントごとの構成プロパティは、次のグローバルなプロパティを除き、ほとんどのプロパティで機能します。

  • spring.cloud.loadbalancer.enabled - 負荷分散をグローバルに有効または無効にします

  • spring.cloud.loadbalancer.retry.enabled - 負荷分散された再試行をグローバルに有効または無効にします。グローバルに有効にしても、client -prefixed プロパティを使用して特定のクライアントの再試行を無効にすることはできますが、その逆はできません。

  • spring.cloud.loadbalancer.cache.enabled - LoadBalancer キャッシュをグローバルに有効または無効にします。グローバルに有効にした場合でも、ServiceInstanceListSupplier デリゲート階層に CachingServiceInstanceListSupplier を含まないカスタム構成を作成することで、特定のクライアントのキャッシュを無効にすることができますが、その逆はできません。

  • spring.cloud.loadbalancer.stats.micrometer.enabled - LoadBalancer Micrometer メトリクスをグローバルに有効または無効にします

すでに使用されている場所にマップされ、clients キーワードを使用せずにクライアントごとに異なる値を指定できるプロパティ ( hintshealth-check.path など) については、ライブラリの下位互換性を維持するためにその動作が維持されています。次のメジャーリリースで変更される予定です。
4.1.0 から、LoadBalancerProperties に callGetWithRequestOnDelegates フラグが導入されました。このフラグが true に設定されている場合、ServiceInstanceListSupplier#get(Request request) メソッドは、そのメソッドをまだ実装していない DelegatingServiceInstanceListSupplier から割り当て可能なクラスで delegate.get(request) を呼び出すように実装されます。ただし、CachingServiceInstanceListSupplier と HealthCheckServiceInstanceListSupplier は除外されます。CachingServiceInstanceListSupplier と HealthCheckServiceInstanceListSupplier は、インスタンスサプライヤー階層の直後に配置する必要があります。サプライヤーは、リクエストベースのフィルタリングが実行される前に、ネットワーク経由でインスタンスの取得を実行します。デフォルトでは true に設定されています。

[[-aot-and-native-image-support]] == AOT とネイティブイメージのサポート

4.0.0 以降、Spring Cloud LoadBalancer は Spring AOT 変換とネイティブイメージをサポートします。ただし、この機能を使用するには、LoadBalancerClient サービス ID を明示的に定義する必要があります。これを行うには、@LoadBalancerClient アノテーションの value または name 属性を使用するか、spring.cloud.loadbalancer.eager-load.clients プロパティの値として使用します。