本指南将引导您完成从 Spring Cloud Config Server 启动和获取配置的过程。
你将构建什么
您将设置一个配置服务器,并构建一个客户端,该客户端在启动时加载配置,然后在不重启客户端的情况下刷新配置。
您需要什么
-
大约15分钟
-
偏好的文本编辑器或 IDE
-
Java 17 或更高版本
-
您也可以直接将代码导入到您的 IDE 中:
如何完成本指南
与大多数 Spring 入门指南一样,您可以从头开始并完成每个步骤,或者可以跳过您已经熟悉的基本设置步骤。无论哪种方式,您最终都会得到可运行的代码。
要从头开始,请继续阅读使用 Spring Initializr 开始。
要跳过基础知识,请执行以下操作:
-
下载并解压本指南的源码仓库,或使用 Git 克隆它:
git clone https://github.com/spring-guides/gs-centralized-configuration.git
-
进入
gs-centralized-configuration/initial
目录 -
直接跳到 搭建配置服务器。
完成后,您可以将您的结果与 gs-centralized-configuration/complete
中的代码进行对比。
从 Spring Initializr 开始
您可以使用这个预初始化项目(用于服务应用程序)或这个预初始化项目(用于客户端应用程序),然后点击“生成”以下载一个 ZIP 文件。该项目已配置为适合本教程中的示例。
要手动初始化项目:
-
访问 https://start.spring.io。这个服务会拉取应用程序所需的所有依赖项,并为您完成大部分设置工作。
-
选择 Gradle 或 Maven 以及您想要使用的语言。本指南假设您选择了 Java。
-
点击 Dependencies 并选择 Config Server(用于服务应用程序)或 Config Client、Spring Boot Actuator 和 Spring Web(用于客户端应用程序)。
-
点击 Generate。
-
下载生成的 ZIP 文件,这是一个根据您的选择配置好的 Web 应用程序归档文件。
如果您的 IDE 集成了 Spring Initializr,您可以直接在 IDE 中完成此过程。
您还可以从 Github 上 fork 该项目,并在您的 IDE 或其他编辑器中打开它。
启动配置服务器
首先,您需要一个配置服务,作为您的Spring应用程序与(通常是)版本控制的配置文件仓库之间的中介。您可以使用Spring Cloud的@EnableConfigServer
来启动一个能够与其他应用程序通信的配置服务器。这是一个常规的Spring Boot应用程序,只需添加一个注解即可启用配置服务器。以下代码清单(来自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);
}
}
配置服务器需要知道要管理哪个仓库。这里有几个选择,但首先从基于 Git 的文件系统仓库开始。您可以轻松地将配置服务器指向一个 Github 或 GitLab 仓库。在文件系统上,创建一个新目录并在其中运行 git init
。然后向 Git 仓库添加一个名为 a-bootiful-client.properties
的文件,并在其中运行 git commit
。稍后,您将使用一个 Spring Boot 应用程序连接到配置服务器,该应用程序的 spring.application.name
属性将其标识为 a-bootiful-client
。这就是配置服务器知道向特定客户端发送哪组配置的方式。它还会发送 Git 仓库中任何名为 application.properties
或 application.yml
的文件中的所有值。更具体命名的文件(例如 a-bootiful-client.properties
)中的属性键会覆盖 application.properties
或 application.yml
中的键。
在新创建的 a-bootiful-client.properties
文件中添加一个简单的属性和值(message = Hello world
),然后通过 git commit
提交更改。
通过 configuration-service/src/main/resources/application.properties
文件中的 spring.cloud.config.server.git.uri
属性指定 Git 仓库的路径。为了避免在同一台机器上运行此服务器和另一个 Spring Boot 应用程序时出现端口冲突,您还必须指定一个不同的 server.port
值。以下清单(来自 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),您也可以使用它。
使用配置客户端从配置服务器读取配置
现在您已经搭建了一个 Config Server,接下来需要启动一个新的 Spring Boot 应用程序,该应用程序使用 Config Server 来加载自身的配置,并且能够在不重启 JVM 的情况下刷新其配置以反映 Config Server 的更改。为此,添加 org.springframework.cloud:spring-cloud-starter-config
依赖项以连接到 Config Server。Spring 会像处理从 application.properties
或 application.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
属性的值。有关使用 Spring MVC 和 Spring Boot 构建 REST 服务的更多信息,请参阅构建 RESTful Web 服务指南。
默认情况下,配置值在客户端启动时读取一次,之后不再读取。您可以通过在 MessageRestController
上使用 Spring Cloud Config 的 @RefreshScope
注解,然后触发 refresh 事件,强制 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;
}
}
测试应用程序
您可以通过先启动配置服务,然后在它运行后再启动客户端来测试端到端的结果。在浏览器中访问客户端应用程序 http://localhost:8080/message
。在那里,您应该会在响应中看到 Hello world
。
将 Git 仓库中的 a-bootiful-client.properties
文件里的 message
键更改为其他值(例如 Hello Spring!
)。您可以通过访问 http://localhost:8888/a-bootiful-client/default
来确认配置服务器是否看到了更改。您需要调用 Spring Boot Actuator 的 refresh
端点,以强制客户端刷新并获取新值。Spring Boot 的 Actuator 暴露了应用程序的操作端点(如健康检查和环境信息)。要使用它,您必须将 org.springframework.boot:spring-boot-starter-actuator
添加到客户端应用程序的类路径中。您可以通过向客户端的 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 集中了所有服务的配置。
另请参阅
以下指南也可能有所帮助: