集中式配置

本指南將引導您完成從 Spring Cloud Config Server 搭建和消費配置的過程。

您將構建什麼

您將搭建一個 Config Server,並構建一個客戶端,該客戶端在啟動時消費配置,然後在不重啟客戶端的情況下重新整理配置。

您需要準備什麼

如何完成本指南

與大多數 Spring 入門指南一樣,您可以從頭開始並完成每個步驟,或者跳過您已熟悉的基本設定步驟。無論哪種方式,您最終都會得到可工作的程式碼。

從頭開始,請繼續閱讀 從 Spring Initializr 開始

跳過基礎步驟,請執行以下操作

完成時,您可以對照 gs-centralized-configuration/complete 中的程式碼檢查您的結果。

從 Spring Initializr 開始

您可以使用這個預初始化專案(用於服務應用)或這個預初始化專案(用於客戶端應用),然後點選 Generate 下載 ZIP 檔案。這個專案已配置好,適合本教程中的示例。

手動初始化專案

  1. 導航至 https://start.spring.io。該服務會引入應用程式所需的所有依賴項,併為您完成大部分設定。

  2. 選擇 Gradle 或 Maven,以及您想要使用的語言。本指南假設您選擇 Java。

  3. 點選 Dependencies 並選擇 Config Server(用於服務應用)或 Config ClientSpring Boot ActuatorSpring Web(用於客戶端應用)。

  4. 點選 Generate

  5. 下載生成的 ZIP 檔案,這是一個根據您的選擇配置的 Web 應用程式存檔。

如果您的 IDE 集成了 Spring Initializr,您可以在 IDE 中完成此過程。
您也可以從 Github 分叉專案並在 IDE 或其他編輯器中開啟。

搭建 Config Server

首先,您需要一個 Config Service 作為 Spring 應用程式和配置檔案的(通常是)版本控制倉庫之間的中間層。您可以使用 Spring Cloud 的 @EnableConfigServer 搭建一個可以與其他應用程式通訊的 Config Server。這是一個普通的 Spring Boot 應用程式,添加了一個註解來啟用 Config Server。以下清單(來自 configuration-service/src/main/java/com/example/configurationservice/ConfigurationServiceApplication.java)展示了這樣的應用程式

/*
 * Copyright 2012-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.configurationservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@EnableConfigServer
@SpringBootApplication
public class ConfigurationServiceApplication {

  public static void main(String[] args) {
    SpringApplication.run(ConfigurationServiceApplication.class, args);
  }
}

Config Server 需要知道管理哪個倉庫。這裡有幾種選擇,但我們從基於 Git 的檔案系統倉庫開始。您可以同樣輕鬆地將 Config Server 指向 Github 或 GitLab 倉庫。在檔案系統上,建立一個新目錄並在其中執行 git init。然後向 Git 倉庫新增一個名為 a-bootiful-client.properties 的檔案。接著在其中執行 git commit。稍後,您將使用一個 Spring Boot 應用程式連線到 Config Server,該應用程式的 spring.application.name 屬性將其標識為 a-bootiful-client 以便 Config Server 識別。Config Server 就是透過這種方式知道要向特定客戶端傳送哪組配置。它還會傳送 Git 倉庫中名為 application.propertiesapplication.yml 的任何檔案中的所有值。特定名稱檔案(如 a-bootiful-client.properties)中的屬性鍵會覆蓋 application.propertiesapplication.yml 中的屬性鍵。

向新建立的 a-bootiful-client.properties 檔案新增一個簡單的屬性和值 (message = Hello world),然後 git commit 提交更改。

透過在 configuration-service/src/main/resources/application.properties 中指定 spring.cloud.config.server.git.uri 屬性來指定 Git 倉庫的路徑。您還必須指定一個不同的 server.port 值,以避免在同一臺機器上執行此伺服器和另一個 Spring Boot 應用程式時出現埠衝突。以下清單(來自 configuration-service/src/main/resources/application.properties)展示了這樣的 application.properties 檔案

server.port=8888

spring.cloud.config.server.git.uri=${HOME}/Desktop/config

此示例使用位於 ${HOME}/Desktop/config 的基於檔案的 Git 倉庫。您只需建立一個新目錄並在其中對屬性和 YAML 檔案執行 git commit 即可輕鬆建立一個。以下命令集完成了這項工作

$ cd ~/Desktop/config
$ find .
./.git
...
./application.yml

或者,如果您更改應用程式中的配置檔案以指向遠端 Git 倉庫(例如 Github),您也可以使用遠端 Git 倉庫。

使用 Config Client 從 Config Server 讀取配置

現在您已經搭建了一個 Config Server,接下來需要搭建一個新的 Spring Boot 應用程式,該程式使用 Config Server 載入自己的配置,並在需要時重新整理其配置以反映 Config Server 的更改,而無需重啟 JVM。為此,請新增 org.springframework.cloud:spring-cloud-starter-config 依賴項,以便連線到 Config Server。Spring 會像處理從 application.propertiesapplication.yml 或任何其他 PropertySource 載入的任何屬性檔案一樣看待這些配置屬性檔案。

配置 Config Client 的屬性可以按 Spring Boot 應用程式的常用方式設定。在 configuration-client/src/main/resources/application.properties 中將客戶端的 spring.application.name 指定為 a-bootiful-client,並指定 Config Server 的位置 (spring.config.import)。以下清單顯示了該檔案

configuration-client/src/main/resources/application.properties

spring.application.name=a-bootiful-client
spring.config.import=optional:configserver:https://:8888/
management.endpoints.web.exposure.include=*

您還需要啟用 /refresh 端點,以演示動態配置更改。上面的清單展示瞭如何透過 management.endpoints.web.exposure.include 屬性來實現。

客戶端可以使用傳統機制(例如 @ConfigurationProperties@Value("${…​}") 或透過 Environment 抽象)訪問 Config Server 中的任何值。現在您需要建立一個 Spring MVC REST 控制器,該控制器返回已解析的 message 屬性的值。請參閱構建 RESTful Web 服務指南,瞭解更多關於使用 Spring MVC 和 Spring Boot 構建 REST 服務的資訊。

預設情況下,配置值在客戶端啟動時讀取,之後不再讀取。您可以透過使用 Spring Cloud Config 的 @RefreshScope 註解 MessageRestController,然後觸發一個重新整理事件來強制 bean 重新整理其配置(即從 Config Server 拉取更新的值)。以下清單(來自 configuration-client/src/main/java/com/example/configurationclient/ConfigurationClientApplication.java)展示瞭如何實現

/*
 * Copyright 2012-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.configurationclient;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class ConfigurationClientApplication {

  public static void main(String[] args) {
    SpringApplication.run(ConfigurationClientApplication.class, args);
  }
}

@RefreshScope
@RestController
class MessageRestController {

  @Value("${message:Hello default}")
  private String message;

  @RequestMapping("/message")
  String getMessage() {
    return this.message;
  }
}

測試應用程式

您可以透過先啟動 Config Service,然後在它執行後啟動客戶端來測試端到端結果。在瀏覽器中訪問客戶端應用程式 https://:8080/message。在那裡,您應該在響應中看到 Hello world

將 Git 倉庫中 a-bootiful-client.properties 檔案中的 message 鍵更改為不同的值(也許是 Hello Spring!?)。您可以透過訪問 https://:8888/a-bootiful-client/default 來確認 Config Server 是否看到了更改。您需要呼叫 refresh Spring Boot Actuator 端點來強制客戶端重新整理自身並拉取新值。Spring Boot 的 Actuator 暴露了有關應用程式的操作端點(例如健康檢查和環境資訊)。要使用它,您必須將 org.springframework.boot:spring-boot-starter-actuator 新增到客戶端應用程式的 classpath 中。您可以透過向客戶端的 refresh 端點發送一個空的 HTTP POST 請求來呼叫 refresh Actuator 端點:https://:8080/actuator/refresh。然後透過訪問 https://:8080/message 端點來確認它是否工作。

以下命令呼叫 Actuator 的 refresh 命令

$ curl -X POST localhost:8080/actuator/refresh -d {} -H "Content-Type: application/json"
我們在客戶端應用程式中設定 management.endpoints.web.exposure.include=* 以使其易於測試(自 Spring Boot 2.0 起,Actuator 端點預設不暴露)。預設情況下,如果您不設定此標誌,仍然可以透過 JMX 訪問它們。

總結

恭喜!您剛剛使用 Spring 透過先搭建一個服務然後動態更新其配置的方式,為所有服務集中化了配置。

另請參閱

以下指南可能也有幫助

想撰寫新指南或為現有指南貢獻力量?請檢視我們的貢獻指南

所有指南的程式碼均採用 ASLv2 許可證釋出,文字內容採用署名-禁止演繹 (Attribution, NoDerivatives) 知識共享許可協議釋出。

獲取程式碼