Spring Cloud Config クライアント

Spring Boot アプリケーションは、Spring Config Server(またはアプリケーション開発者が提供するその他の外部プロパティソース)をすぐに利用できます。また、Environment 変更イベントに関連するいくつかの追加の便利な機能を取り上げます。

Spring Boot 構成データのインポート

Spring Boot 2.4 は、spring.config.import プロパティを介して構成データをインポートする新しい方法を導入しました。これが、ConfigServer にバインドするデフォルトの方法になりました。

オプションで構成サーバーに接続するには、application.properties で以下を設定します。

application.properties
spring.config.import=optional:configserver:

これにより、デフォルトの "http://localhost:8888" の場所にある構成サーバーに接続されます。optional: プレフィックスを削除すると、構成サーバーに接続できない場合、構成クライアントが失敗します。構成サーバーの場所を変更するには、spring.cloud.config.uri を設定するか、spring.config.import=optional:configserver:http://myhost:8888 などの spring.config.import ステートメントに URL を追加します。import プロパティの場所は、uri プロパティよりも優先されます。

Spring Boot 構成データは、2 段階のプロセスで構成を解決します。まず、default プロファイルを使用してすべての構成をロードします。これにより、Spring Boot は追加のプロファイルをアクティブ化する可能性のあるすべての構成を収集できます。すべてのアクティブ化されたプロファイルを収集した後、アクティブプロファイルの追加構成をロードします。このため、構成を取得するために Spring Cloud Config サーバーに複数のリクエストが行われることがあります。これは正常であり、spring.config.import を使用するときに Spring Boot が構成をロードする方法の副作用です。Spring Cloud Config の以前のバージョンでは、単一のリクエストのみが行われましたが、これは、構成サーバーからの構成からプロファイルをアクティブ化できなかったことを意味していました。default プロファイルのみを使用した追加のリクエストにより、これが可能になります。

spring.config.import を介してインポートする Spring Boot Config Data メソッドには、bootstrap ファイル(プロパティまたは yaml)は必要ありません。

最初のブートストラップを構成する

構成サーバーに接続する従来のブートストラップ方法を使用するには、プロパティまたは spring-cloud-starter-bootstrap スターターを介してブートストラップを有効にする必要があります。プロパティは spring.cloud.bootstrap.enabled=true です。システムプロパティまたは環境変数として設定する必要があります。ブートストラップが有効になると、クラスパスに Spring Cloud Config クライアントがあるアプリケーションは、次のように構成サーバーに接続します。構成クライアントが起動すると、構成サーバーにバインドし(spring.cloud.config.uri ブートストラップ構成プロパティを介して)、リモートプロパティソースを使用して Spring Environment を初期化します。

この動作の最終的な結果として、構成サーバーを使用するすべてのクライアントアプリケーションには、サーバーアドレスが spring.cloud.config.uri (デフォルトは "http://localhost:8888")に設定された bootstrap.yml (または環境変数)が必要です。

最初のルックアップ検出

config first bootstrap を使用している場合を除き、構成プロパティに optional: プレフィックスが付いた spring.config.import プロパティが必要です。例: spring.config.import=optional:configserver:

Spring Cloud Netflix および Eureka サービス検出または Spring Cloud Consul などの DiscoveryClient 実装を使用する場合、構成サーバーを検出サービスに登録できます。

DiscoveryClient を使用して構成サーバーを検索する場合は、spring.cloud.config.discovery.enabled=true を設定することで実行できます (デフォルトは false です)。例: Spring Cloud Netflix では、Eureka サーバーアドレスを定義する必要があります (たとえば、eureka.client.serviceUrl.defaultZone で)。このオプションを使用するための価格は、サービス登録を見つけるための、起動時の追加のネットワークラウンドトリップです。利点は、Discovery Service が固定ポイントである限り、構成サーバーがその座標を変更できることです。デフォルトのサービス ID は configserver ですが、クライアントでは spring.cloud.config.discovery.serviceId を設定することで (およびサーバーでは spring.application.name を設定するなどのサービスの通常の方法で) 変更できます。

検出クライアントの実装はすべて、ある種のメタデータマップをサポートしています(たとえば、Eureka 用の eureka.instance.metadataMap があります)。クライアントが正しく接続できるように、構成サーバーのいくつかの追加プロパティをサービス登録メタデータで構成する必要がある場合があります。構成サーバーが HTTPBasic で保護されている場合は、資格情報を user および password として構成できます。また、構成サーバーにコンテキストパスがある場合は、configPath を設定できます。例: 次の YAML ファイルは、Eureka クライアントである構成サーバー用です。

eureka:
  instance:
    ...
    metadataMap:
      user: osufhalskjrtl
      password: lviuhlszvaorhvlo5847
      configPath: /config

Eureka および WebClient を使用した最初のブートストラップの検出

Spring Cloud Netflix の Eureka DiscoveryClient を使用していて、Jersey または RestTemplate の代わりに WebClient も使用したい場合は、クラスパスに WebClient を組み込み、eureka.client.webclient.enabled=true を設定する必要があります。

クライアントのフェイルファスト設定

場合によっては、サービスが構成サーバーに接続できない場合、サービスの起動に失敗することがあります。これが望ましい動作である場合は、ブートストラップ構成プロパティ spring.cloud.config.fail-fast=true を設定して、クライアントを例外で停止させます。

spring.config.import を使用して同様の機能を取得するには、optional: プレフィックスを省略します。

クライアントの再試行設定

アプリケーションの起動時に構成サーバーが時々利用不能になることが予想される場合は、失敗後も構成サーバーを試行し続けるようにすることができます。まず、spring.cloud.config.fail-fast=true を設定する必要があります。次に、spring-retry と spring-boot-starter-aop をクラスパスに追加する必要があります。デフォルトの動作では、初期バックオフ間隔 1000 ミリ秒と後続のバックオフの指数乗数 1.1 で 6 回再試行します。spring.cloud.config.retry.* 構成プロパティを設定することで、これらのプロパティ (およびその他) を構成できます。ランダム指数バックオフポリシーを使用するには、spring.cloud.config.retry.useRandomPolicy を true に設定します。

spring.cloud.config.retry.useRandomPolicy が true の場合、ランダム指数バックオフポリシーを使用している場合でも、max-attemptsinitial-intervalmax-intervalmultiplier プロパティは引き続き影響します。これらの使用方法の詳細については、Spring Retry [GitHub] (英語) の ExponentialRandomBackOffPolicy および ExponentialBackOffPolicy を参照してください。
再試行動作を完全に制御し、レガシーブートストラップを使用するには、ID が configServerRetryInterceptor である型 RetryOperationsInterceptor の @Bean を追加します。Spring Retry には、作成をサポートする RetryInterceptorBuilder があります。

spring.config.import を使用したクライアントの再試行設定

再試行は Spring Boot spring.config.import ステートメントで機能し、通常のプロパティが機能します。ただし、import ステートメントが application-prod.properties などのプロファイルにある場合は、再試行を構成する別の方法が必要です。構成は、インポートステートメントの URL パラメーターとして配置する必要があります。

application-prod.properties
spring.config.import=configserver:http://configserver.example.com?fail-fast=true&max-attempts=10&max-interval=1500&multiplier=1.2&initial-interval=1100"

これにより、spring.cloud.config.fail-fast=true (上記のプレフィックスが欠落していることに注意してください) と、使用可能なすべての spring.cloud.config.retry.* 構成プロパティが設定されます。

リモート構成リソースの検索

Config Service は、/{application}/{profile}/{label} からのプロパティソースを提供します。クライアントアプリのデフォルトのバインディングは次のとおりです。

  • 「アプリ」= ${spring.application.name}

  • 「プロファイル」= ${spring.profiles.active} (実際に Environment.getActiveProfiles())

  • " ラベル "=" マスター "

プロパティ ${spring.application.name} を設定するときは、正しいプロパティソースを解決する際の課題を防ぐために、アプリ名の前に予約語 application- を付けないでください。

spring.cloud.config.* を設定することで、これらすべてを上書きできます (ここで、* は nameprofile、または label です)。label は、以前のバージョンの構成にロールバックする場合に便利です。デフォルトの 構成サーバー実装では、git ラベル、ブランチ名、またはコミット ID を指定できます。ラベルは、コンマ区切りのリストとして指定することもできます。この動作は、機能 ブランチで作業する場合に便利です。たとえば、構成ラベルを ブランチに揃えたいが、オプションにしたい場合があります (その場合は、spring.cloud.config.label=myfeature,develop を使用します)。

複数のラベルのリクエスト

Spring Cloud Config 4.2.0 より前では、spring.cloud.config.label をカンマ区切りのラベルリストに設定すると、構成クライアントは、機能するラベルが見つかるまで、構成サーバーにリクエストを送信して各ラベルを試行していました。つまり、最初のラベルが見つかった場合、後続のラベルは試行されませんでした。

Spring Cloud Config 4.2.0 の時点で、spring.cloud.config.label をラベルのコンマ区切りリストに設定し、AND を spring.cloud.config.send-all-labels に設定すると、Config クライアントはラベルのコンマ区切りリストを使用して Config サーバーに単一のリクエストを送信し、構成サーバーはバージョン 4.2.0 以降を使用していますの場合はすべてのラベルのプロパティソースを含む単一のレスポンスを返します。

spring.cloud-config.send-all-labels を true に設定し、spring.cloud.config.label をラベルのカンマ区切りリストに設定し、4.2.0 より前のバージョンの 構成サーバーを使用すると、構成サーバーはカンマ区切りリストの値に一致するラベルを見つけようとしますが、ラベルを分割しようとしないため、予期しない動作が発生します。

すべてのラベルを 1 回のリクエストで送信することで、構成サーバーへのリクエストの数を減らすことができます。

spring.cloud.config.send-all-labels はデフォルトで false に設定されているため、古い動作が引き続きデフォルトとなり、古いバージョンの 構成サーバーとの互換性も維持されます。

構成サーバーに複数の URL を指定する

構成サーバーの複数のインスタンスがデプロイされていて、1 つ以上のインスタンスが利用できないか、(Git サーバーがダウンしている場合などに) 時々リクエストを受け入れることができないと予想される場合に、高可用性を確保するには、複数の URL を指定することができます ( spring.cloud.config.uri プロパティのコンマ区切りのリスト) またはすべてのインスタンスを Eureka のようなサービスレジストリに登録します (Discovery-First Bootstrap モードを使用している場合)。

spring.cloud.config.uri にリストされている URL は、リストされている順序で試行されます。デフォルトでは、構成クライアントは、高可用性を確保する試みが成功するまで、各 URL からプロパティを取得しようとします。

ただし、構成サーバーが実行されていないとき (つまり、アプリケーションが終了したとき) または接続タイムアウトが発生したときにのみ高可用性を確保したい場合は、spring.cloud.config.multiple-uri-strategy を connection-timeout-only に設定します。( spring.cloud.config.multiple-uri-strategy のデフォルト値は always です) 例: 構成サーバーが 500 (内部的サーバーエラー) レスポンスを返した場合、または構成クライアントが構成サーバーから 401 を受信した場合 (不正な資格情報またはその他の原因による)、構成クライアントは他の URL からプロパティを取得しようとしないでください。400 エラー (場合によっては 404 を除く) は、可用性の課題ではなく、ユーザーの課題を示します。構成サーバーが Git サーバーを使用するように設定されていて、Git サーバーへの呼び出しが失敗した場合、404 エラーが発生する可能性があることに注意してください。

spring.cloud.config.uri ではなく、1 つの spring.config.import キーで複数の場所を指定できます。ロケーションは定義された順序で処理され、後のインポートが優先されます。ただし、spring.cloud.config.fail-fast が true の場合、最初の構成サーバー呼び出しが何らかの理由で失敗すると、構成クライアントは失敗します。fail-fast が false の場合、失敗の理由に関係なく、1 つの呼び出しが成功するまですべての URL を試行します。(spring.config.import で URL を指定する場合、spring.cloud.config.multiple-uri-strategy は適用されません。)

構成サーバーで HTTP 基本セキュリティを使用している場合、現在、spring.cloud.config.uri プロパティで指定した各 URL に資格情報を埋め込んだ場合にのみ、ConfigServer ごとの認証資格情報をサポートできます。他の種類のセキュリティメカニズムを使用している場合、(現在)ConfigServer ごとの認証と認可をサポートすることはできません。

タイムアウトの構成

タイムアウトしきい値を構成する場合:

  • 読み取りタイムアウトは、プロパティ spring.cloud.config.request-read-timeout を使用して構成できます。

  • 接続タイムアウトは、プロパティ spring.cloud.config.request-connect-timeout を使用して構成できます。

文字セットの設定

リソースがサーバーによって配信される特定の文字セットを構成する場合は、文字セットを介してそれを適用する必要があります。

spring:
  cloud:
    config:
      charset: UTF-8

文字セット設定プロパティは java.nio.charset.Charset として定義されています

セキュリティ

サーバーで HTTP 基本セキュリティを使用する場合、クライアントはパスワード(およびデフォルトでない場合はユーザー名)を知っている必要があります。次の例に示すように、ユーザー名とパスワードは、構成サーバーの URI を介して、または個別のユーザー名とパスワードのプロパティを介して指定できます。

spring:
  cloud:
    config:
     uri: https://user:[email protected] (英語)  

次の例は、同じ情報を渡す別の方法を示しています。

spring:
  cloud:
    config:
     uri: https://myconfig.mycompany.com
     username: user
     password: secret

spring.cloud.config.password および spring.cloud.config.username 値は、URI で提供されるすべてのものをオーバーライドします。

アプリを Cloud Foundry にデプロイする場合、パスワードを提供する最善の方法は、サービス資格情報を使用することです(URI など、構成ファイルに含める必要がないため)。次の例は、ローカルで、configserver という名前の Cloud Foundry 上のユーザー提供サービスに対して機能します。

spring:
  cloud:
    config:
     uri: ${vcap.services.configserver.credentials.uri:http://user:password@localhost:8888}

構成サーバーでクライアント側の TLS 証明書が必要な場合は、次の例に示すように、プロパティを介してクライアント側の TLS 証明書とトラストストアを構成できます。

spring:
  cloud:
    config:
      uri: https://myconfig.myconfig.com
      tls:
        enabled: true
        key-store: <path-of-key-store>
        key-store-type: PKCS12
        key-store-password: <key-store-password>
        key-password: <key-password>
        trust-store: <path-of-trust-store>
        trust-store-type: PKCS12
        trust-store-password: <trust-store-password>

構成クライアント側 TLS を有効にするには、spring.cloud.config.tls.enabled が true である必要があります。spring.cloud.config.tls.trust-store を省略すると、JVM のデフォルトのトラストストアが使用されます。spring.cloud.config.tls.key-store-type および spring.cloud.config.tls.trust-store-type のデフォルト値は PKCS12 です。パスワードのプロパティを省略すると、空のパスワードが想定されます。

別の形式のセキュリティを使用する場合は、RestTemplate を ConfigServicePropertySourceLocator に提供する必要がある場合があります(たとえば、ブートストラップコンテキストでそれを取得して挿入することによって)。

ヘルス指標

構成クライアントは、構成サーバーから構成をロードしようとする Spring Boot ヘルスインジケーターを提供します。ヘルスインジケータは、health.config.enabled=false を設定することで無効にできます。パフォーマンス上の理由から、レスポンスもキャッシュされます。デフォルトのキャッシュ存続時間は 5 分です。その値を変更するには、health.config.time-to-live プロパティ(ミリ秒単位)を設定します。

カスタム RestTemplate の提供

場合によっては、クライアントから構成サーバーに対して行われるリクエストをカスタマイズする必要がある場合があります。通常、これには、リクエストを認証するための特別な Authorization ヘッダーをサーバーに渡すことが含まれます。

構成データを使用したカスタム RestTemplate の提供

構成データの使用時にカスタム RestTemplate を提供するには:

  1. BootstrapRegistryInitializer を実装するクラスを作成する

    CustomBootstrapRegistryInitializer.java
    public class CustomBootstrapRegistryInitializer implements BootstrapRegistryInitializer {
    
    	@Override
    	public void initialize(BootstrapRegistry registry) {
    		registry.register(RestTemplate.class, context -> {
    			RestTemplate restTemplate = new RestTemplate();
    			// Customize RestTemplate here
    			return restTemplate;
    		});
    	}
    
    }
  2. 次の例に示すように、resources/META-INF で、spring.factories というファイルを作成し、カスタム構成を指定します。

    spring.factories
    org.springframework.boot.BootstrapRegistryInitializer=com.my.config.client.CustomBootstrapRegistryInitializer

ブートストラップを使用したカスタム RestTemplate の提供

ブートストラップの使用時にカスタム RestTemplate を提供するには:

  1. 次の例に示すように、PropertySourceLocator の実装を使用して新しい構成 Bean を作成します。

    CustomConfigServiceBootstrapConfiguration.java
    @Configuration
    public class CustomConfigServiceBootstrapConfiguration {
        @Bean
        public ConfigServicePropertySourceLocator configServicePropertySourceLocator() {
            ConfigClientProperties clientProperties = configClientProperties();
           ConfigServicePropertySourceLocator configServicePropertySourceLocator =  new ConfigServicePropertySourceLocator(clientProperties);
            configServicePropertySourceLocator.setRestTemplate(customRestTemplate(clientProperties));
            return configServicePropertySourceLocator;
        }
    }
    Authorization ヘッダーを追加するための単純化されたアプローチとして、代わりに spring.cloud.config.headers.* プロパティを使用できます。
  2. 次の例に示すように、resources/META-INF で、spring.factories というファイルを作成し、カスタム構成を指定します。

    spring.factories
    org.springframework.cloud.bootstrap.BootstrapConfiguration = com.my.config.client.CustomConfigServiceBootstrapConfiguration

Vault

構成サーバーへのバックエンドとして Vault を使用する場合、クライアントは、サーバーが Vault から値を取得するためのトークンを提供する必要があります。このトークンは、次の例に示すように、bootstrap.yml で spring.cloud.config.token を設定することにより、クライアント内で提供できます。

spring:
  cloud:
    config:
      token: YourVaultToken

Vault のネストされたキー

Vault は、次の例に示すように、Vault に格納されている値にキーをネストする機能をサポートしています。

echo -n '{"appA": {"secret": "appAsecret"}, "bar": "baz"}' | vault write secret/myapp -

このコマンドは、JSON オブジェクトを Vault に書き込みます。Spring でこれらの値にアクセスするには、次の例に示すように、従来の dot(.)アノテーションを使用します。

@Value("${appA.secret}")
String name = "World";

上記のコードは、name 変数の値を appAsecret に設定します。

AOT およびネイティブイメージのサポート

4.0.0 以降、Spring Cloud Config クライアントは Spring AOT 変換と GraalVM ネイティブイメージをサポートします。

AOT およびネイティブイメージのサポートは、config first ブートストラップ spring.config.use-legacy-processing=true を使用) では利用できません。
リフレッシュスコープは、ネイティブイメージではサポートされていません。構成クライアントアプリケーションをネイティブイメージとして実行する場合は、必ず spring.cloud.refresh.enabled プロパティを false に設定してください。
Spring Cloud Config クライアントを含むプロジェクトを構築する場合、接続先の構成データソース (Spring Cloud Config サーバー、Consul、Zookeeper、Vault など) が利用可能であることを確認する必要があります。例: Spring Cloud Config サーバーから構成データを取得する場合は、そのインスタンスが実行中であり、構成クライアントのセットアップで指定されたポートで使用できることを確認してください。これが必要なのは、アプリケーションコンテキストがビルド時に最適化され、ターゲット環境を解決する必要があるためです。
AOT およびネイティブモードでは、ビルド時にコンフィギュレーションが処理され、コンテキストが最適化されるため、予期せぬ動作を避けるために、Bean の生成に影響を与えるプロパティ(ブートストラップコンテキスト内で使用されるものなど)は、ビルド時と実行時に同じ値に設定する必要があります。
構成クライアントは、ネイティブイメージからの起動中に実行中のデータソース (構成サーバーなど) に接続するため、このネットワーク通信が行われるのに必要な時間だけ、高速起動時間が遅くなります。

付録

可観測性メタデータ

可観測性 - メトリクス

以下に、このプロジェクトで宣言されたすべての指標のリストを示します。

環境リポジトリ

EnvironmentRepository を中心に作成された観測。

指標名  spring.cloud.config.environment.find (規約クラス org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention で定義)。タイプ  timer.

指標名  spring.cloud.config.environment.find.active (規約クラス org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention で定義)。タイプ  long task timer.

観測の開始後に追加された KeyValues は、*.active メトリクスから欠落している可能性があります。
Micrometer は、ベースユニットに nanoseconds を内部的に使用します。ただし、各バックエンドが実際のベースユニットを決定します。(つまり、Prometheus は秒を使用します)

外側のクラス org.springframework.cloud.config.server.environment.DocumentedConfigObservation の完全修飾名。

すべてのタグには、spring.cloud.config.environment プレフィックスを付ける必要があります。
表 1: カーディナリティの低いキー

名前

説明

spring.cloud.config.environment.application (必須)

プロパティが照会されるアプリケーション名。

spring.cloud.config.environment.class (必須)

EnvironmentRepository の実装。

spring.cloud.config.environment.label (必須)

プロパティがクエリされるラベル。

spring.cloud.config.environment.profile (必須)

プロパティが照会されるアプリケーション名。

可観測性 - スパン

以下に、このプロジェクトで宣言されたすべてのスパンのリストを示します。

環境リポジトリのスパン

EnvironmentRepository を中心に作成された観測。

スパン名  spring.cloud.config.environment.find (規約クラス org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention で定義)。

外側のクラス org.springframework.cloud.config.server.environment.DocumentedConfigObservation の完全修飾名。

すべてのタグには、spring.cloud.config.environment プレフィックスを付ける必要があります。
表 2: タグキー

名前

説明

spring.cloud.config.environment.application (必須)

プロパティが照会されるアプリケーション名。

spring.cloud.config.environment.class (必須)

EnvironmentRepository の実装。

spring.cloud.config.environment.label (必須)

プロパティがクエリされるラベル。

spring.cloud.config.environment.profile (必須)

プロパティが照会されるアプリケーション名。