Config 入门教程 - 基础篇

大纲

配置中心介绍

什么是配置中心

在集中式开发时代,配置文件已经基本足够了,因为那时配置的管理通常不会成为一个很大的问题。但是在互联网时代,应用都是分布式系统,部署在 N 台服务器上,想要去线上一台台地重启机器肯定不靠谱,并且维护成本也很高,所以配置中心应运而生。配置中心被用作集中管理不同环境(Dev、Test、Stage、Prod)和不同集群配置,以及在修改配置后将实时动态推送到应用上进行刷新。配置中心应具备的功能如下:

  • Open API
  • 业务无关性
  • 高可用集群
  • 配置生效监控
  • 配合灰度与更新
  • 一致性 K-V 存储
  • 统一配置实时推送
  • 配置全局恢复、备份与历史

主流配置中心对比

  • Spring Cloud Config、Apollo、Nacos 对比图
  • Spring Cloud Config、Netflix Archaius、Apollo、Disconf(已停止维护) 对比图

config-server-vs

Config 配置中心概述

Spring Cloud Config 是一个集中化外部配置的分布式系统,由服务端和客户端组成。它不依赖于注册中心,是一个独立的配置中心。Spring Cloud Config 支持多种存储配置信息的形式,目前主要有 JDBC、Vault、Native、SVN、Git,其中默认为 Git 存储形式,Git 版的工作原理如下图:

config-server-git

配置中心流转与整体支持图

config-server-process

Config 入门案例

1. 版本说明

在本文中,使用的 Spring Cloud 版本是 Finchley.RELEASE,对应的 Spring Boot 版本是 2.0.3,特别声明除外,点击下载完整的案例代码。

2. 准备工作

由于下面的 Spring Cloud Config 使用 Git 作为存储方式,因此需要提前在 Git 远程仓库(Github、Gitlab)中创建对应的仓库,然后往仓库里 Push 三个配置文件,分别是 config-client-dev.yml、config-client-prod.yml、config-client-test.yml,配置文件的内容如下:

1
2
3
4
5
6
server:
port: 9001

cn:
springcloud:
config: I am the git configuration file from dev environment
1
2
3
4
5
6
server:
port: 9002

cn:
springcloud:
config: I am the git configuration file from prod environment
1
2
3
4
5
6
server:
port: 9003

cn:
springcloud:
config: I am the git configuration file from test environment

3. 创建 Maven 父级 Pom 工程

在父工程里面配置好工程需要的父级依赖,目的是为了更方便管理与简化配置,具体 Maven 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>

<!-- 利用传递依赖,公共部分 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<!--注意:这里需要添加以下配置,否则可能会有各种依赖问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>

4. 创建 Config Server 工程

创建 Config Server 的 Maven 工程,配置工程里的 pom.xml 文件,需要引入 spring-cloud-config-server

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>

创建 Config Server 的主启动类,增加 @EnableConfigServer 注解:

1
2
3
4
5
6
7
8
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

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

添加 Config Server 需要的 application.yml 配置文件到工程中,其中 uri 指的是 Git 远程仓库的地址,private_key_file 是指 SSH 公钥文件;若 Git 仓库地址使用的是 HTTPS 协议,此时可以使用 usemamepassword 参数替代掉 private_key_file,两者分别代表 Git 访问的用户名和密码;search-paths 表示搜索特定目录下所有满足条件的配置文件,可以根据需求添加多个目录,目录之间用逗号隔开;label 指的是 Git 仓库的分支名称,如果不写,默认的分支为 master

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server:
port: 8001

spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: git@github.com:xxxxx/spring-cloud-config-study-repo.git
search-paths: spring-cloud-config-study-repo/
strictHostKeyChecking: false
private_key_file: /root/.ssh/id_rsa.pub
label: master

启动 Config Server 应用后,可以看到控制台会输出如下信息,这里只是截取关键信息,从控制台信息里的 Mapped 中可以看到配置信息和 URL 的映射关系;其中 name 是应用名称,也可以理解成 Git 仓库里配置文件的名称,profile 指的是对应激活的环境名,例如 dev、test、prod 等,label 指的是 Git 的分支

1
2
3
4
5
6
7
8
9
10
Mapped "{[/{name}-{profiles}.yml || /{name}-{profiles}.yaml],methods=[GET]}"
Mapped "{[/{name}/{profiles:.*[^-].*}],methods=[GET]}"
Mapped "{[/{name}/{profiles}/{label:.*}],methods=[GET]}"
Mapped "{[/{label}/{name}-{profiles}.properties],methods=[GET]}"
Mapped "{[/{name}-{profiles}.json],methods=[GET]}"
Mapped "{[/{label}/{name}-{profiles}.json],methods=[GET]}"
Mapped "{[/{label}/{name}-{profiles}.yml || /{label}/{name}-{profiles}.yaml],methods=[GET]}"
Mapped "{[/{name}/{profile}/**],methods=[GET],params=[useDefaultLabel]}"
Mapped "{[/{name}/{profile}/{label}/**],methods=[GET]}"
Mapped "{[/{name}/{profile}/{label}/**],methods=[GET],produces=[application/octet-stream]}"

通过 http://127.0.0.1:8001/config-client/dev/master 访问 Config Server,接口返回的结果如下

config-server-info

此时观察 Config Server 控制台打印的信息可知,Config Server 会在本地的临时目录下面克隆远程仓库中的配置文件,本地临时目录的路径如下:

1
o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/tmp/config-repo-3558022506897899775/application.yml (document #0)

5. 创建 Config Client 工程

创建 Config Client 的 Maven 工程,配置工程里的 pom.xml 文件,需要引入 spring-cloud-config-client

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>

创建 Config Client 的主启动类:

1
2
3
4
5
6
7
@SpringBootApplication
public class ConfigClientApplication {

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

为了更好地观察拉取到的 Git 上面的配置,这里需要创建一个 Controller 用于访问返回配置信息,同时还需要创建一个实体,用于注入远程配置上的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
@ConfigurationProperties(prefix = "cn.springcloud")
public class ConfigProperties {

private String config;

public String getConfig() {
return config;
}

public void setConfig(String config) {
this.config = config;
}
}
1
2
3
4
5
6
7
8
9
10
11
@RestController
public class ConfigController {

@Autowired
public ConfigProperties configProperties;

@GetMapping("/getConfigInfo")
public String getConfigInfo() {
return configProperties.getConfig();
}
}

添加 Config Client 需要的 application.yml 配置文件到工程中:

1
2
3
spring:
application:
name: config-client

添加 Config Client 需要的 bootstrap.yml 配置文件到工程中,这些配置为什么要放在 bootstrap.yml 里,而不放在 application.yml 中呢?这与 Spring Boot 的加载顺序有关,bootstrap.yml 文件会优先于 application.yml 加载,因此会去加载远程的配置文件信息

1
2
3
4
5
6
7
spring:
cloud:
config:
name: config-client #需要从远程Git仓库读取的配置文件的名称,注意没有"yml"文件后缀,可以写多个,通过逗号隔开
profile: dev #本次访问的配置项
label: master #Git分支的名称
uri: http://127.0.0.1:8001 #Config Server的地址

6. 测试结果

  1. 依次启动 config-server、config-client 应用
  2. 访问 http://127.0.0.1:9001/getConfigInfo,接口会返回 I am the git configuration file from dev environment
  3. 更改 Git 远程仓库中的 config-client-dev.yml 配置文件,将内容修改为 I am the git configuration file from dev environment updated
  4. 重启 config-client 应用,再次访问 http://127.0.0.1:9001/getConfigInfo,接口会返回 I am the git configuration file from dev environment updated,说明配置更新了

刷新配置中心信息

Config Client 手动刷新

为了不用重启 Congit Client 应用也可以获取到最新的配置信息,下面将讲解在 Congit Client 端如何手动刷新配置信息,点击下载完整的案例代码。

i. 准备工作

本示例用到上面入门案例中 Git 仓库里的配置文件,包括 config-client-dev.yml、config-client-prod.yml、config-client-test.yml。

ii. 创建 Config Server 工程

由于本示例是在上面的入门案例的基础上进行改造的,因此 Config Server 工程与上面入门案例中的 Config Server 工程完全一样,只需拷贝一份即可,由于篇幅有限,这里不再累述。

iii. 创建 Config Client 工程

创建 Config Client 的 Maven 工程,配置工程里的 pom.xml 文件,第二个依赖是端点的访问依赖,第三个依赖是安全的依赖:

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

添加 Config Client 需要的 application.yml 配置文件到工程中,management.endpoints.web.exposure.include=* 表示暴露所有端点,默认情况下只暴露 info、health 端点,management.endpoint.health.show-details=always 表示总是显示详细信息

1
2
3
4
5
6
7
8
9
10
11
spring:
application:
name: config-client

management:
endpoints:
web:
exposure:
include: "*"
health:
show-details: always

添加 Config Client 需要的 bootstrap.yml 配置文件到工程中:

1
2
3
4
5
6
7
spring:
cloud:
config:
name: config-client #需要从远程Git仓库读取的配置文件的名称,注意没有"yml"文件后缀,可以写多个,通过逗号隔开
profile: dev #本次访问的配置项
label: master #Git分支的名称
uri: http://127.0.0.1:8001 #Config Server的地址

往 Config Client 添加安全配置类,主要作用是关闭端点访问的安全校验:

1
2
3
4
5
6
7
8
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}

为了更好地观察拉取到的 Git 上面的配置,这里需要创建一个 Controller 用于访问返回配置信息,同时还需要创建一个实体,用于注入远程配置上的信息。注意,这里的 ConfigProperties 与 ConfigController 类都需要额外添加 @RefreshScope 注解,被 @RefreshScope 注解修饰的 Bean 都是延迟加载的,只有在第一次访问时才会被初始化;刷新 Bean 也是同理,刷新后下次访问会创建一个新的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component
@RefreshScope
public class ConfigProperties {

@Value("${cn.springcloud.config}")
private String config;

public String getConfig() {
return config;
}

public void setConfig(String config) {
this.config = config;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
@RefreshScope
@RestController
public class ConfigController {

@Autowired
public ConfigProperties configProperties;

@GetMapping("/getConfigInfo")
public String getConfigInfo() {
return configProperties.getConfig();
}
}

iiii. 测试结果

  1. 依次启动 config-server、config-client 应用
  2. 访问 http://127.0.0.1:9001/getConfigInfo,接口会返回 I am the git configuration file from dev environment
  3. 更改 Git 远程仓库中的 config-client-dev.yml 配置文件,将内容修改为 I am the git configuration file from dev environment updated
  4. 通过 Post 请求访问 http://127.0.0.1:9001/actuator/refresh,让 Config Client 刷新配置信息
  5. 再次访问 http://127.0.0.1:9001/getConfigInfo,接口会返回 I am the git configuration file from dev environment updated,说明配置更新了

结合 Spring Cloud Bus 热更新

Spring Cloud Config 结合 Spring Cloud Bus 进行刷新的整体流程图如下,当用户更新配置信息时,触发 Git Hook 配置地址的调用,Config Server 接收到 Refresh 请求后,通过 Bus 将消息发送到 Config Client,当 Config Client 接收到消息后会重新发送请求加载配置信息,大体流程就是这样。下面将使用 RabbitMQ 作为消息中间件,由于篇幅有限,这里不再讲解 RabbitMQ 的安装和使用方法,点击下载完整的案例代码。

config-spring-cloud-bus

1. 准备工作

本示例用到上面入门案例中 Git 仓库里的配置文件,包括 config-client-dev.yml、config-client-prod.yml、config-client-test.yml。

2. 创建 Config Server 工程

创建 Config Server 的 Maven 工程,配置工程里的 pom.xml 文件,第二个依赖是端点的访问依赖,第三个依赖是安全的依赖,第四个是消息中间件的依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

创建 Config Server 的主启动类,增加 @EnableConfigServer 注解:

1
2
3
4
5
6
7
8
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

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

创建 Config Server 的安全配置类,主要作用是关闭端点访问的安全校验:

1
2
3
4
5
6
7
8
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}

添加 Config Server 需要的 application.yml 配置文件到工程中,其中包括 RabbitMQ 的地址和账号信息,spring.cloud.bus.trace.enabled=true 表示开启消息跟踪:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server:
port: 8001

spring:
application:
name: config-server
rabbitmq:
port: 5672
host: localhost
username: admin
password: admin
cloud:
bus:
trace:
enabled: true
config:
server:
git:
uri: git@github.com:xxxxx/spring-cloud-config-study-repo.git
search-paths: spring-cloud-config-study-repo/
strictHostKeyChecking: false
private_key_file: /root/.ssh/id_rsa.pub
label: master

management:
endpoints:
web:
exposure:
include: "*"
health:
show-details: always

3. 创建 Config Client 工程

创建 Config Client 的 Maven 工程,配置工程里的 pom.xml 文件,第二个依赖是端点的访问依赖,第三个依赖是安全的依赖,第四个是消息中间件的依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

往 Config Client 添加安全配置类,主要作用是关闭端点访问的安全校验:

1
2
3
4
5
6
7
8
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}

为了更好地观察拉取到的 Git 上面的配置,这里需要创建一个 Controller 用于访问返回配置信息,同时还需要创建一个实体,用于注入远程配置上的信息;注意,这里的 ConfigProperties 与 ConfigController 类都需要额外添加 @RefreshScope 注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component
@RefreshScope
public class ConfigProperties {

@Value("${cn.springcloud.config}")
private String config;

public String getConfig() {
return config;
}

public void setConfig(String config) {
this.config = config;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
@RefreshScope
@RestController
public class ConfigController {

@Autowired
public ConfigProperties configProperties;

@GetMapping("/getConfigInfo")
public String getConfigInfo() {
return configProperties.getConfig();
}
}

添加 Config Client 需要的 application.yml 配置文件到工程中,其中包括 RabbitMQ 的地址和账号信息,spring.cloud.bus.trace.enabled=true 表示开启消息跟踪:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
spring:
application:
name: config-client
rabbitmq:
port: 5672
host: localhost
username: admin
password: admin
cloud:
bus:
trace:
enabled: true

management:
endpoints:
web:
exposure:
include: "*"
health:
show-details: always

添加 Config Client 需要的 bootstrap.yml 配置文件到工程中:

1
2
3
4
5
6
7
spring:
cloud:
config:
name: config-client #需要从远程Git仓库读取的配置文件的名称,注意没有"yml"文件后缀,可以写多个,通过逗号隔开
profile: dev #本次访问的配置项
label: master #Git分支的名称
uri: http://127.0.0.1:8001 #Config Server的地址

4. 测试结果

  1. 依次启动 config-server、config-client 应用
  2. 访问 http://127.0.0.1:9001/getConfigInfo,接口会返回 I am the git configuration file from dev environment
  3. 更改 Git 远程仓库中的 config-client-dev.yml 配置文件,将内容修改为 I am the git configuration file from dev environment updated
  4. 通过 Post 请求访问 http://127.0.0.1:8001/actuator/bus-refresh,让 Config Server 通过 Spring Cloud Bus 发送消息通知所有 Config Client 刷新配置信息
  5. 再次访问 http://127.0.0.1:9001/getConfigInfo,接口会返回 I am the git configuration file from dev environment updated,说明配置更新了
    提示:可以将 Spring Cloud Bus 的刷新地址配置在 WebHooks 上面,这样在 Git 仓库每次有新文件提交(Push)之后,所有 Config Client 都会自动执行刷新的动作

Config Client 自动刷新(任务调度)

在有些应用上面,不需要在服务端批量推送消息的时候,客户端本身需要获取参数变化的情况,此时可以使用客户端的自动刷新功能,其原理是使用任务调度执行刷新操作,点击下载完整的案例代码

1. 准备说明

本示例用到上面入门案例中 Git 仓库里的配置文件,包括 config-client-dev.yml、config-client-prod.yml、config-client-test.yml。

2. Config Refresh Autoconfig 工程

创建 Config Refresh Autoconfig 的 Maven 工程,配置工程里的 pom.xml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

创建 Config Refresh Autoconfig 工程里的自动配置类,添加相关注解,使其在 Spring Boot 启动的时候将其加载。在该类中,主要是注入了端点类,通过定时任务和刷新时间,进行配置请求刷新。由于在类中是直接调用了 RefreshEndpoint 的 refresh() 方法,所以对于 F 版的安全机制不需要对端点进行打开也可以,但需要依赖 spring-boot-starter-actuator,否则无法注入 RefreshEndpoint 的 Bean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@ConditionalOnClass(RefreshEndpoint.class)
@ConditionalOnProperty("spring.cloud.config.refreshInterval")
@AutoConfigureAfter(RefreshAutoConfiguration.class)
@Configuration
public class ConfigAutoRefreshConfiguration implements SchedulingConfigurer {

private static final Logger logger = LoggerFactory.getLogger(ConfigAutoRefreshConfiguration.class);

/**
* 间隔刷新时间
*/
@Value("${spring.cloud.config.refreshInterval}")
private long refreshInterval;

/**
* 刷新的端点
*/
@Autowired
private RefreshEndpoint refreshEndpoint;

@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
final long interval = getRefreshIntervalInMilliseconds();
logger.info(String.format("Scheduling config refresh task with %s second delay", refreshInterval));
scheduledTaskRegistrar.addFixedDelayTask(new IntervalTask(new Runnable() {
@Override
public void run() {
refreshEndpoint.refresh();
}
}, interval, interval));
}

/**
* 以毫秒为单位返回刷新间隔
*
* @return
*/
private long getRefreshIntervalInMilliseconds() {

return refreshInterval * 1000;
}

/**
* 如果没有在上下文中注册,则启用调度程序
*/
@ConditionalOnMissingBean(ScheduledAnnotationBeanPostProcessor.class)
@EnableScheduling
@Configuration
protected static class EnableSchedulingConfigProperties {

}
}

在 Config Refresh Autoconfig 工程里创建 /src/main/resources/META-INF/spring.factories 配置文件,添加上面的自动配置类:

1
2
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.springcloud.study.config.ConfigAutoRefreshConfiguration

3. Cofnig Client 工程

这里 Cofnig Client 工程的代码基本与上面的 “Config Client 手动刷新” 示例的代码一致,拷贝一份即可,这里不再累述。

Cofnig Client 工程的 pom.xml 文件,引入 config-refresh-autoconfig 依赖:

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>com.springcloud.study</groupId>
<artifactId>config-refresh-autoconfig</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

Cofnig Client 工程的 application.yml 文件,refreshInterval: 15 表示每 15 秒刷新一次配置信息:

1
2
3
4
5
6
spring:
application:
name: config-client
cloud:
config:
refreshInterval: 15

4. Cofnig Server 工程

这里 Cofnig Server 工程的代码基本与上面的 “Config Client 手动刷新” 示例的代码一致,拷贝一份即可,这里不再累述。

5. 测试结果

  1. 依次启动 config-server、config-client 应用
  2. 访问 http://127.0.0.1:9001/getConfigInfo,接口会返回 I am the git configuration file from dev environment
  3. 更改 Git 远程仓库中的 config-client-dev.yml 配置文件,将内容修改为 I am the git configuration file from dev environment updated
  4. 等待一段时间后(15 秒),再次访问 http://127.0.0.1:9001/getConfigInfo,接口会返回 I am the git configuration file from dev environment updated,说明配置更新了