1. 简介
Spring Cloud Config是用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持的。
它由服务端和客户端构成:
其中,服务端也称为分布式配置中心,是一个独立的微服务应用,用来连接配置仓库、为客户端提供支持;
客户端则一般是各个微服务应用本身,它们通过指定服务端来管理自身的配置。
Spring Cloud Config默认支持Git作为配置仓库,存储各个微服务的配置信息,同时也能支持其他的存储方式,如:码云、SVN、本地化文件系统。
2. 服务端配置
使用码云仓库作为“配置文件管理中心”,对配置文件进行统一管理。
-
创建码云账号,并新建仓库springcloud-config,可以设置为私密库
-
安装git,并配置码云账户信息
-
使用git,拉取仓库,在仓库中创建配置文件后,提交新建的配置文件信息到码云仓库
config-dev.yml
config:
info: "master branch,springcloud-config/config-dev.yml version=1"
config-prod.yml
config:
info: "master branch,springcloud-config/config-prod.yml version=1"
config-test.yml
config:
info: "master branch,springcloud-config/config-test.yml version=1"
-
idea集成git
-
创建module,添加配置中心的核心pom引用
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- 主启动类使用注解@EnableConfigServer开启配置中心
@SpringBootApplication
@EnableConfigServer
public class MainAppConfigCenter3344 {
public static void main(String[] args) {
SpringApplication.run(MainAppConfigCenter3344.class,args);
}
}
- 在application.yaml中配置相关信息,并将配置中心微服务注册到注册中心
server:
port: 3344
spring:
application:
name: cloud-config-center #注册进Eureka服务器的微服务名
cloud:
config:
server:
git:
uri: https://gitee.com/qianghao/springcloud-config.git #GitHub上面的git仓库名字
####搜索目录
search-paths:
- springcloud-config
username: 你的码云账号
password: 你的码云密码
label: master
#服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://eureka-server-7001:7001/eureka/
- 修改本机Windows下的hosts文件,添加域名映射,启动注册中心和配置中心,使用http://config-3344.com:3344/master/config-dev.yml访问配置文件
127.0.0.1 config-3344.com
测试:
- 配置读取规则:
/{label}/{application}-{profile}.yml(推荐),例如:
master分支
- http://config-3344.com:3344/master/config-dev.yml
- http://config-3344.com:3344/master/config-test.yml
- http://config-3344.com:3344/master/config-prod.yml
dev分支 - http://config-3344.com:3344/dev/config-dev.yml
- http://config-3344.com:3344/dev/config-test.yml
- http://config-3344.com:3344/dev/config-prod.yml
3. 客户端配置
1. 新建客户端功能测试module:cloud-config-client-3355
2. 引入配置中心客户端的核心依赖:spring-cloud-starter-config
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3. 创建系统级配置文件bootstrap.yaml
这里需要引入一个新的概念:系统级的资源配置项 - bootstrap.yaml
3.1. 加载顺序
若application.yml 和bootstrap.yml 在同一目录下:bootstrap.yml 先加载 application.yml后加载
bootstrap.yml 用于应用程序上下文的引导阶段。bootstrap.yml 由父Spring ApplicationContext加载。
3.2. 配置区别
bootstrap是spring cloud的配置上下文加载。由spring-cloud-content包加载。
bootstrap.yml 和 application.yml 都可以用来配置参数。
bootstrap.yml 用来程序引导时执行,应用于更加早期配置信息读取。可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。一旦bootStrap.yml 被加载,则内容不会被覆盖。
application.yml 可以用来定义应用级别的, 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
3.3. 属性覆盖问题
启动上下文时,Spring Cloud 会创建一个 Bootstrap Context,作为 Spring 应用的 Application Context 的父上下文。
初始化的时候,Bootstrap Context 负责从 外部源 加载 配置属性 并 解析配置。这两个上下文共享一个从外部获取的 Environment。Bootstrap 属性有高优先级,默认情况下,它们不会被本地配置覆盖。
也就是说如果加载的 application.yml 的内容标签与 bootstrap 的标签一致,application 也不会覆盖 bootstrap,而 application.yml 里面的内容可以动态替换。
4. 因此我们需要从外部文件获取配置信息时,使用bootstrap.yaml就非常必要了。
创建bootstrap.yaml并写入以下配置:
server:
port: 3355
spring:
application:
name: config-client
cloud:
#Config客户端配置
config:
label: master #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
uri: http://config-3344.com:3344 #配置中心地址k
#服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://eureka-server-7001:7001/eureka/
5. 配置主启动类
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3355.class,args);
}
}
6. 编写业务类,获取配置信息
@RestController
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
private String getConfigInfo(){
return configInfo;
}
}
7. 测试获取配置信息:http://localhost:3355/configInfo
4. 动态刷新配置信息
从上面bootstrap.yaml的介绍可以知道,它的优先级比较高,配置信息加载后一般是不会被覆盖,比如:
- 我们现在对码云上的的配置文件内容做调整
- 刷新3344,发现ConfigServer配置中心立刻响应
- 刷新3355,发现ConfigClient客户端没有任何响应
- 3355没有变化除非自己重启或者重新加载
如果需要重新加载配置信息就需要重新启动服务,这是非常不友好的。这时我们就需要一种可以动态刷新配置的方法 - actuator监控服务。
- 引入actuator监控服务的pom依赖:spring-boot-starter-actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 在yaml中配置 actuator,添加暴露监控端口配置:
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
- 修改业务类
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
private String getConfigInfo(){
return configInfo;
}
}
- 发送刷新请求,Post方式请求刷新3355
curl -X POST "http://localhost:3355/actuator/refresh
-
测试:修改码云上的配置文件内容,并提交修改。然后发送post请求进行刷新,之后就可以获取最新的配置文件信息
-
现在产生了新的问题:
假如有多个微服务客户端3355/3366/3377怎么办?难道每个微服务都要进行请求刷新一次?
可否广播,一次通知,处处生效? Bus消息总线就可以实现