集中式配置

本指南将引导您完成从 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://apache.ac.cn/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:http://localhost: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://apache.ac.cn/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,然后在它运行后启动客户端来测试端到端结果。在浏览器中访问客户端应用程序 http://localhost:8080/message。在那里,您应该在响应中看到 Hello world

将 Git 仓库中 a-bootiful-client.properties 文件中的 message 键更改为不同的值(也许是 Hello Spring!?)。您可以通过访问 http://localhost: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 端点:http://localhost:8080/actuator/refresh。然后通过访问 http://localhost: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) 知识共享许可协议发布。

获取代码