分布式系统面临的配置问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。
Config是什么?
SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。 SpringCloud Config分为服务端和客户端两部分。
服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息,配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。
Config能干什么?
1. 集中管理配置文件
2. 不同环境不同配置,动态化的配置更新,分环境部署比如dev/test/prod
3. 运行期间动态调整配置,不再需要在每个服务器部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
4. 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置
5. 将配置信息以REST接口的形式暴露
Config原理图
一、Config配置总控中心搭建1. 新建一个工程,作为Config服务端工程名:cloud-config-center
2. pom文件添加config依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
3. 修改application.yml文件,重点!!!说明:一般来说,我们需要单独创建一个仓库用来存放这些配置文件,但是我这个工程就在github上放着,懒得再去创建了,就用这个仓库吧(^_^)v
server:
port: 3344
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
# 这个就是你平时clone项目的地址,https和ssh地址都可以
uri: https://github.com/Lmg12580/springcloud.git
# 这个地址是进入仓库后配置文件的目录地址
search-paths:
- config
label: master #git分支
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka8761.com:8761/eureka
4. 主启动类添加启用注解
public class ConfigCenterApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigCenterApplication.class, args);
}
}
5. 我把配置文件放到我仓库的config目录下了,具体的内容可以在github上查看,大概就是下面这样的内容格式
config:
info: "master branch,springcloud-config/config-dev.yml version=1"
6. 在浏览器输入地址查看配置文件内容,发现这时候就可以查看到github上的配置了。
http://ip:3344/master/config-dev.yml">http://ip:3344/master/config-dev.ymlhttp://ip:3344/master/config-test.yml
配置文件读取规则
1. /{application}/{profile}[/{label}]
对应: http://localhost:3344/config/dev/master
这个返回的结果是一个json串
2. /{application}-{profile}.yml
对应: http://localhost:3344/config-dev.yml
如果没有输入分支,默认取配置文件中的label配置
3. /{label}/{application}-{profile}.yml
对应: http://localhost:3344/master/config-dev.yml
这个就是上面我们使用的方式
二、Config客户端配置
1. 在学习阶段,为了让配置看上去更清晰,我们单独建一个新工程,用来做客户端
工程名:cloud-config-client
2. pom文件添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
3. 新建bootstrap.yml文件,知识点:
application.yml与bootstrap.yml
application.yml是用户级的资源配置项
bootstrap.yml是系统级的,优先级更高
因为bootstrap有高优先级,比application.yml先加载,且不会被本地配置覆盖,保证了配置的分离。springboot基础知识,不多聊了。
server:
port: 3355
spring:
application:
name: cloud-config-client
cloud:
config: # config客户端配置
label: master # 分支名称
name: config # 配置文件名称
profile: dev # 读取后缀名称 综合:master分支上的config-dev.yml配置文件
uri: http://localhost:3344 #配置中心地址 合起来就是http://localhost:3344/master/config-dev.yml
eureka:
client:
service-url:
defaultZone: http://eureka8761.com:8761/eureka
4. 新增业务类,用来获取服务端配置信息
public class ConfigClientController {
("${config.info}")
private String configInfo;
("/configInfo")
public String getConfigInfo(){
return configInfo;
}
}
5. 启动客户端3355,在地址栏请求访问配置文件,发现这时候我们可以读取到配置信息
6. 我们修改一下github的该配置文件,将版本号改为2,看3355返回的信息
config:
info: "master branch,springcloud-config/config-dev.yml version=2"
7. 在访问3355之前,先看一下服务端3344的返回信息,发现已经取到了最新的配置
8. 这时候再看一下3355的返回信息,刷新后仍然是原先的配置
问题:分布式配置的动态刷新问题
在远程仓库修改以后,配置中心ConfigServer立即响应,但是客户端ConfigClient没有任何响应,除非自己重启,那么每次修改配置,都需要重启的话,不太友好……(˶‾᷄ ⁻̫ ‾᷅˵)三、Config客户端动态刷新
1. 客户端3355添加actuator依赖作用:如果自身服务发生变化,能被别的服务监控到。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2. 修改3355yml文件,暴露监控端口
management:
endpoints:
web:
exposure:
include: "*"
3. ConfigClientController.java添加以下注解,重启3355客户端
@RefreshScope
4. 修改github配置文件,将版本号改为3
config:
info: "master branch,springcloud-config/config-dev.yml version=3"
5. 请求访问3355,发现修改还是没有生效
6. 没生效是因为这种配置方式需要手动向客户端3355发送一个post请求
Lmg12580:~ wangyg$ curl -X POST "http://localhost:3355/actuator/refresh"
7. 再去访问客户端3355,这时候就可以取到github上的最新配置了
上述方案已经能够满足大部分公司的需求了,但是还不够完美,因为需要手动向客户端做post请求。那么有没有更好的方式来处理这个问题呢?
接下来一起学习下个组件:消息总线Bus
本项目已上传到gitee和github,地址在公众号窗口 我的->git 查看相关内容