一、概述
1、分布式系统面临的问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。假设我们每一个微服务自己带着一个application.yml,那么上百个配置文件的管理所耗费的时间是非常庞大的,因此springcloud自己提供了一个config分布式配置中心来解决这个。
2、是什么
SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。
SpringCloud Config分为服务端和客户端两部分。 服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口,客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。
3、能干嘛
- 集中管理配置文件。
- 不同环境不同配置,动态化的配置更新,分环境部署比如dev/test/prod/beta/release。
- 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息。
- 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置。
- 将配置信息以REST接口的形式暴露,这样我们使用post、curl访问刷新均可。
4、与GitHub整合配置
由于SpringCloud Config默认使用Git来存储配置文件(也有其它方式,比如支持SVN和本地文件),但最推荐的还是Git,而且使用的是http/https访问的形式。
5、官网
二、快速入门SpringCloud Config
1、创建配置中心仓库
首先我们需要一个创建一个配置中心仓库。由于github的网速太慢,所以我使用码云创建配置中心仓库,当然你也可以使用github。
1、在码云创建springcloud-config仓库
2、在仓库中创建三个文件
文件命名规格:{项目名}-{配置环境版本}.yml。比如config-dev.yml,表示的是config项目的开发环境配置。
配置文件内容分别如下。
config-dev.yml
user:
name: "张三 dev"
config-prod.yml
user:
name: "张三 prod"
2、config服务端搭建
1、新建maven工程spring-cloud-config-server并引入依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- spring cloud config 服务端包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
2、配置config相关配置
bootstrap.yml 文件
spring:
application:
name: config-server # 应用名称
cloud:
config:
server:
git:
# 配置中心仓库地址
uri: https://gitee.com/F_promise/springcloud-config.git #配置文件所在仓库
username: 码云用户名
password: 码云密码
default-label: master #配置文件分支
# search-paths: config #配置文件所在根目录
3、启动类
增加相关注解 @EnableConfigServer
@SpringBootApplication
@EnableConfigServer
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
}
4、测试
Spring Cloud Config 有它的一套访问规则,我们通过这套规则在浏览器上直接访问就可以。
- /{application}/{profile}[/{label}]
- /{application}-{profile}.yml
- /{label}/{application}-{profile}.yml
- /{application}-{profile}.properties
- /{label}/{application}-{profile}.properties
- application:应用名,这里是config
- profile:配置文件版本,比如dev、prod
- label:git的分支,默认master
以第一条规则为例,访问config-dev.yml配置文件:
至此,配置中心服务端搭建完毕,接下来客户端(其他项目)需要从配置中心中获取配置信息。
3、config客户端搭建
1、新建maven工程spring-cloud-config-client,并引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring cloud config 客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
注意,客户端和服务端引入的config依赖是不一样的。
2、编写bootstrap.yml配置文件
--- bootstrap.yml ---
spring:
profiles:
active: dev #激活开发环境的配置文件
---
spring:
application:
name: config
cloud:
config:
uri: http://localhost:8080 #config服务端的地址
label: master
profile: dev #开发环境
---
spring:
application:
name: config
cloud:
config:
uri: http://localhost:8080 #config服务端的地址
label: master
profile: prod #生产环境
3、编写application.yml配置文件
server:
port: 8888
user:
name: 小王 #配置默认值。配置中心有用配置中心的
4、创建UserController测试使用
@RestController
public class UserController {
@Value("${user.name}")
private String name;
@GetMapping("info")
public String info(){
return name;
}
}
5、启动服务,访问测试
可以看到,成功读取到了配置中心中的config-dev.yml配置文件。将bootstrap.yml中的active改成prod在进行测试:
4、存在的问题
当我们在仓库中修改内容并保存后,服务端8080可以获取到最新的信息,但是客户端8888去调用服务端的接口来获取仓库的内容时,我们发现获取到的内容仍然是仓库修改之前的数据,并没有实现配置刷新。换句而言,当配置文件修改后,需要重启服务才能生效,这样很明显会给我们带来很多不便。
三、实现配置刷新(手动版)
1、在客户端spring-cloud-config-client加入actuator依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、在application.yml中添加如下actuator的配置
management:
endpoint:
shutdown:
enabled: false
endpoints:
web:
exposure:
include: "*"
3、在Controller上添加@RefreshScope注解
@RestController
@RefreshScope
public class UserController {
@Value("${user.name}")
private String name;
@GetMapping("info")
public String info(){
return name;
}
}
4、手动触发更新方法
在配置文件修改后,使用Postman发送一个post请求到http://localhost:8888/actuator/refresh 这个接口,触发主动更新。
5、测试
此时我们再次更改仓库的数据,然后执行第四步的手动刷新方法,我们可以看到不需要重启项目也可以获取到仓库的最新数据了。
四、是否还有其他问题?
如果每次配置文件修改后,都需要我们主动发送post请求触发更新,这明显有点不太方便。而且如何客户端比较多的话,一个一个的手动刷新也比较耗时。这个时候,我们可以借助Spring Cloud Bus的广播功能,让client端都订阅配置更新事件,当配置更新时,触发其中一个端的更新事件,Spring Cloud Bus就把此事件广播到其他订阅端,以此来达到批量更新。
关于Spring Cloud Bus请看我的另外一篇文章:SpringCloud之bus消息总线