Spring Cloud Config 客戶端

Spring Boot 應用程式可以立即利用 Spring Config Server(或應用程式開發人員提供的其他外部屬性源)。它還具有一些與 Environment 更改事件相關的額外有用功能。

Spring Boot配置資料匯入

Spring Boot 2.4 引入了一種新的透過 spring.config.import 屬性匯入配置資料的方式。這現在是繫結到 Config Server 的預設方式。

要可選地連線到配置伺服器,請在 application.properties 中進行如下設定

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

這將連線到預設位置為“https://:8888”的 Config Server。如果無法連線到 Config Server,刪除 optional: 字首將導致 Config 客戶端失敗。要更改 Config Server 的位置,請設定 spring.cloud.config.uri 或將 URL 新增到 spring.config.import 語句中,例如 spring.config.import=optional:configserver:http://myhost:8888。匯入屬性中的位置優先於 uri 屬性。

Spring Boot 配置資料透過兩步過程解析配置。首先,它使用 default 配置檔案載入所有配置。這允許 Spring Boot 收集所有可能啟用任何其他配置檔案的配置。在收集了所有已啟用的配置檔案後,它將為活動配置檔案載入任何額外的配置。因此,您可能會看到多次向 Spring Cloud Config Server 發出請求以獲取配置。這是正常的,是 Spring Boot 在使用 spring.config.import 時載入配置的方式的副作用。在 Spring Cloud Config 的先前版本中,只發出一個請求,但這表示您無法從 Config Server 啟用配置檔案。現在,額外使用 default 配置檔案的請求使得這成為可能。

透過spring.config.import的Spring Boot配置資料匯入方法不需要bootstrap檔案(properties或yaml)。

配置優先啟動

要使用傳統的啟動方式連線到 Config Server,必須透過屬性或 spring-cloud-starter-bootstrap 啟動器啟用啟動。該屬性是 spring.cloud.bootstrap.enabled=true。它必須設定為系統屬性或環境變數。一旦啟用了啟動,任何類路徑上帶有 Spring Cloud Config Client 的應用程式都將按以下方式連線到 Config Server:當配置客戶端啟動時,它會繫結到 Config Server(透過 spring.cloud.config.uri 啟動配置屬性)並使用遠端屬性源初始化 Spring Environment

此行為的最終結果是,所有希望使用 Config Server 的客戶端應用程式都需要一個 bootstrap.yml(或一個環境變數),其中設定了伺服器地址 spring.cloud.config.uri(預設為“https://:8888”)。

服務發現優先查詢

除非您正在使用配置優先啟動,否則您的配置屬性中需要有一個帶有 optional: 字首的 spring.config.import 屬性。例如,spring.config.import=optional:configserver:

如果您使用 DiscoveryClient 實現,例如 Spring Cloud Netflix 和 Eureka 服務發現或 Spring Cloud Consul,您可以讓 Config Server 向發現服務註冊。

如果您希望使用 DiscoveryClient 來定位 Config Server,您可以透過設定 spring.cloud.config.discovery.enabled=true(預設為 false)來實現。例如,使用 Spring Cloud Netflix,您需要定義 Eureka 伺服器地址(例如,在 eureka.client.serviceUrl.defaultZone 中)。使用此選項的代價是在啟動時額外進行一次網路往返以定位服務註冊。好處是,只要發現服務是固定點,Config Server 就可以更改其座標。預設服務 ID 為 configserver,但您可以透過設定 spring.cloud.config.discovery.serviceId 在客戶端上更改它(並在伺服器上,以服務通常的方式,例如透過設定 spring.application.name)。

所有的發現客戶端實現都支援某種元資料對映(例如,Eureka 有 eureka.instance.metadataMap)。Config Server 的一些額外屬性可能需要在其服務註冊元資料中進行配置,以便客戶端能夠正確連線。如果 Config Server 使用 HTTP Basic 進行安全保護,您可以將憑據配置為 userpassword。此外,如果 Config Server 有上下文路徑,您可以設定 configPath。例如,以下 YAML 檔案適用於作為 Eureka 客戶端的 Config Server

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

使用 Eureka 和 WebClient 進行服務發現優先啟動

如果您使用 Spring Cloud Netflix 的 Eureka DiscoveryClient,並且還想使用 WebClient 而不是 Jersey 或 RestTemplate,您需要在類路徑中包含 WebClient,並設定 eureka.client.webclient.enabled=true

配置客戶端快速失敗

在某些情況下,如果服務無法連線到 Config Server,您可能希望啟動失敗。如果這是期望的行為,請將啟動配置屬性 spring.cloud.config.fail-fast=true 設定為使客戶端因異常而停止。

要使用 spring.config.import 實現類似功能,只需省略 optional: 字首即可。

配置客戶端重試

如果您預期在應用程式啟動時配置伺服器可能偶爾不可用,您可以在失敗後使其繼續嘗試。首先,您需要設定 spring.cloud.config.fail-fast=true。然後您需要將 spring-retryspring-boot-starter-aop 新增到您的類路徑中。預設行為是重試六次,初始退避間隔為 1000ms,後續退避的指數乘數為 1.1。您可以透過設定 spring.cloud.config.retry.* 配置屬性來配置這些屬性(和其他屬性)。要使用隨機指數退避策略,請將 spring.cloud.config.retry.useRandomPolicy 設定為 true

spring.cloud.config.retry.useRandomPolicytrue 時,max-attemptsinitial-intervalmax-intervalmultiplier 屬性即使在使用隨機指數退避策略時仍然有效。有關它們如何使用的詳細資訊可以在 Spring Retry 中的 ExponentialRandomBackOffPolicyExponentialBackOffPolicy 中找到。
要完全控制重試行為並使用舊版啟動,請新增一個 ID 為 configServerRetryInterceptorRetryOperationsInterceptor 型別的 @Bean。Spring Retry 有一個 RetryInterceptorBuilder 支援建立此類。

使用 spring.config.import 的配置客戶端重試

重試功能適用於 Spring Boot 的 spring.config.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.* 配置屬性。

定位遠端配置資源

配置服務從 /{application}/{profile}/{label} 提供屬性源,其中客戶端應用程式中的預設繫結如下

  • "application" = ${spring.application.name}

  • "profile" = ${spring.profiles.active}(實際上是 Environment.getActiveProfiles()

  • "label" = "master"

設定屬性 ${spring.application.name} 時,請勿使用保留字 application- 作為應用名字首,以防止解析正確屬性源時出現問題。

您可以透過設定 spring.cloud.config.*(其中 *nameprofilelabel)來覆蓋所有這些屬性。label 對於回滾到以前的配置版本非常有用。對於預設的 Config Server 實現,它可以是 git 標籤、分支名稱或提交 ID。Label 也可以以逗號分隔列表的形式提供。當在功能分支上工作時,此行為可能很有用。例如,您可能希望將配置標籤與您的分支對齊,但使其可選(在這種情況下,使用 spring.cloud.config.label=myfeature,develop)。

請求多個標籤

在 Spring Cloud Config 4.2.0 之前,如果您將 spring.cloud.config.label 設定為逗號分隔的標籤列表,Config Client 將透過向 Config Server 發出請求來嘗試每個標籤,直到找到一個可用的標籤。這意味著如果找到了第一個標籤,則不會嘗試後續標籤。

從 Spring Cloud Config 4.2.0 開始,如果您將 spring.cloud.config.label 設定為逗號分隔的標籤列表 **並且** 設定 spring.cloud.config.send-all-labelstrue,則 Config Client 將向 Config Server 傳送一個包含逗號分隔標籤列表的單個請求,並且如果 **Config Server 使用 4.2.0 或更高版本**,它將返回一個包含所有標籤的屬性源的單個響應。

spring.cloud-config.send-all-labels 設定為 true,將 spring.cloud.config.label 設定為逗號分隔的標籤列表,並使用低於 4.2.0 版本的 Config Server 將導致意外行為,因為 Config Server 將嘗試查詢與逗號分隔列表值匹配的標籤,並且不會嘗試拆分標籤。

透過在單個請求中傳送所有標籤,您可以減少向 Config Server 發出的請求數量。

spring.cloud.config.send-all-labels 預設為 false,因此舊的行為仍然是預設行為,並且它還保持與舊版本 Config Server 的相容性。

為配置伺服器指定多個 URL

當您部署了多個 Config Server 例項,並且預計一個或多個例項會時不時地不可用或無法響應請求(例如,如果 Git 伺服器宕機),為了確保高可用性,您可以指定多個 URL(作為 spring.cloud.config.uri 屬性下的逗號分隔列表),或者讓所有例項在像 Eureka 這樣的服務註冊中心註冊(如果使用服務發現優先啟動模式)。

spring.cloud.config.uri 下列出的 URL 將按列出的順序嘗試。預設情況下,Config Client 將嘗試從每個 URL 獲取屬性,直到嘗試成功,以確保高可用性。

但是,如果您只想在 Config Server 未執行(即應用程式已退出)或發生連線超時時確保高可用性,請將 spring.cloud.config.multiple-uri-strategy 設定為 connection-timeout-only。(spring.cloud.config.multiple-uri-strategy 的預設值為 always。)例如,如果 Config Server 返回 500(Internal Server Error)響應或 Config Client 從 Config Server 收到 401(由於錯誤的憑據或其他原因),Config Client 不會嘗試從其他 URL 獲取屬性。400 錯誤(可能除了 404)表示使用者問題而不是可用性問題。請注意,如果 Config Server 設定為使用 Git 伺服器且呼叫 Git 伺服器失敗,則可能會發生 404 錯誤。

可以在單個 spring.config.import 鍵下指定多個位置,而不是 spring.cloud.config.uri。位置將按定義的順序處理,後面的匯入優先。但是,如果 spring.cloud.config.fail-fasttrue,則如果第一個 Config Server 呼叫因任何原因失敗,Config Client 將失敗。如果 fail-fastfalse,它將嘗試所有 URL,直到一個呼叫成功,無論失敗原因如何。(當在 spring.config.import 下指定 URL 時,spring.cloud.config.multiple-uri-strategy 不適用。)

如果您的配置伺服器使用 HTTP 基本安全,目前只有在您將憑據嵌入到 spring.cloud.config.uri 屬性下指定的每個 URL 中時,才能支援每個配置伺服器的身份驗證憑據。如果您使用任何其他型別的安全機制,您(目前)無法支援每個配置伺服器的身份驗證和授權。

配置超時

如果您想配置超時閾值

  • 可以透過使用屬性 spring.cloud.config.request-read-timeout 來配置讀取超時。

  • 可以透過使用屬性 spring.cloud.config.request-connect-timeout 來配置連線超時。

配置字元集

如果您希望配置伺服器提供特定字元集的資源,您需要透過 charset 應用它。

spring:
  cloud:
    config:
      charset: UTF-8

字元集配置屬性定義為 java.nio.charset.Charset

安全

如果伺服器使用 HTTP Basic 安全,客戶端需要知道密碼(如果不是預設值,還需要知道使用者名稱)。您可以透過配置伺服器 URI 或透過單獨的使用者名稱和密碼屬性指定使用者名稱和密碼,如以下示例所示

spring:
  cloud:
    config:
     uri: https://user:[email protected]

以下示例展示了傳遞相同資訊的另一種方式

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

spring.cloud.config.passwordspring.cloud.config.username 的值會覆蓋 URI 中提供的任何內容。

如果您將應用程式部署到 Cloud Foundry,提供密碼的最佳方式是透過服務憑據(例如在 URI 中,因為它不需要在配置檔案中)。以下示例適用於本地和 Cloud Foundry 上名為 configserver 的使用者提供服務

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>

spring.cloud.config.tls.enabled 必須為 true 才能啟用配置客戶端 TLS。當省略 spring.cloud.config.tls.trust-store 時,將使用 JVM 預設信任儲存。spring.cloud.config.tls.key-store-typespring.cloud.config.tls.trust-store-type 的預設值為 PKCS12。當省略密碼屬性時,假定為空密碼。

如果您使用其他形式的安全性,您可能需要 ConfigServicePropertySourceLocator 提供一個 RestTemplate(例如,透過在引導上下文中獲取並注入它)。

健康指標

Config Client 提供了一個 Spring Boot 健康指標,它會嘗試從 Config Server 載入配置。可以透過設定 management.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

使用 Bootstrap 提供自定義 RestTemplate

在使用 Bootstrap 時提供自定義 RestTemplate

  1. 建立一個新的配置 bean,其中包含 PropertySourceLocator 的實現,如以下示例所示

    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 中訪問這些值,您將使用傳統的點(.)表示法,如以下示例所示

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

上述程式碼將 name 變數的值設定為 appAsecret

AOT 和 Native Image 支援

4.0.0 版本開始,Spring Cloud Config Client 支援 Spring AOT 轉換和 GraalVM 本機映象。

對於配置優先啟動(使用 spring.config.use-legacy-processing=true)不支援 AOT 和本地映象。
原生映象不支援重新整理範圍。如果你將把你的配置客戶端應用程式作為原生映象執行,請確保將 spring.cloud.refresh.enabled 屬性設定為 false
在構建包含 Spring Cloud Config Client 的專案時,您必須確保它連線到的配置資料來源(例如,Spring Cloud Config Server、Consul、Zookeeper、Vault 等)可用。例如,如果您從 Spring Cloud Config Server 檢索配置資料,請確保其例項正在執行並可在 Config Client 設定中指示的埠上訪問。這是必要的,因為應用程式上下文在構建時進行了最佳化,並且需要解析目標環境。
由於在 AOT 和原生模式下,配置正在被處理並且上下文在構建時被最佳化,因此任何會影響 bean 建立的屬性(例如在引導上下文中使用的屬性)在構建時和執行時都應設定為相同的值,以避免意外行為。
由於 Config Client 在從本機映象啟動時會連線到正在執行的資料來源(例如 Config Server),因此快速啟動時間將因網路通訊所需的時間而減慢。

附錄

可觀測性元資料

可觀測性 - 指標

以下是本專案宣告的所有指標列表。

環境倉庫

圍繞 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

在啟動觀測後新增的鍵值可能會從 *.active 指標中缺失。
Micrometer 內部使用 納秒 作為基本單位。但是,每個後端確定實際的基本單位。(即 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 (必填)

正在查詢屬性的應用程式名稱。

可觀測性 - Span

以下是本專案宣告的所有 Span 列表。

環境倉庫範圍

圍繞 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 (必填)

正在查詢屬性的應用程式名稱。

© . This site is unofficial and not affiliated with VMware.