一、基础概述
1、为什么要有分布式配置中心Config?
微服务意味着要将单体应用中的业务拆分成一个个的子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务;
忧郁每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的!
SpringCloud提供了ConfigServer来解决这个问题,我们每个微服务都带着一个application.yml,上百个配置文件的管理,很恐怖o(╥﹏╥)o
SpringCloud Config为微服务架构汇中的微服务提供了集中化的外部配置支持,配置服务器Config Server为各个不同的微服务应用的所有环境提供了一个中心化的外部配置;
2、SpringCloud Config的组成?
SpringCloud Config分为服务端和客户端两部分;
服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息、加密/解密信息等访问接口;
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息,配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便地管理和访问配置内容;
3、SpringCloud Config能干嘛?
-
集中管理配置文件;
-
不同环境不同配置、动态化的配置更新,分环境部署比如dev/test/prod/beta/demo/release等;
-
运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务回想配置中心统一拉取自己的配置信息;
-
当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置信息;
-
将配置信息以Rest接口的形式暴露;
二、Config配置总控中心的搭建(Config Server)
1、首先,我们要创建一个新的git仓库,作为统一配置仓库:springcloud-config
https://github.com/jiguiquan/springcloud-config
新建三个配置文件,分别为:
-
config-dev.yml
-
config-prod.yml
-
config-test.yml
2、新建配置中心模块 cloud-config-center3344
pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud2020</artifactId> <groupId>com.jiguiquan.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-config-center3344</artifactId> <dependencies> <!--springcloud config server--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <!--eureka-client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--公共服务模块依赖--> <dependency> <groupId>com.jiguiquan.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!--springboot项目web和actuator最好一起走--> <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> <!--热部署devtools--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies> </project>
3、配置文件application.yml:
server: port: 3344 spring: application: name: cloud-config-center cloud: config: server: git: uri: git@github.com:jiguiquan/springcloud-config.git search-paths: - springcloud-config label: master eureka: client: service-url: defaultZone: http://localhost:7001/eureka
4、主启动类:ConfigCenterMain3344.java
@SpringBootApplication @EnableEurekaClient @EnableConfigServer public class ConfigCenterMain3344 { public static void main(String[] args) { SpringApplication.run(ConfigCenterMain3344.class, args); } }
5、修改windows下的host文件,增加映射:
127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com 127.0.0.1 config3344.com #增加此项
6、启动服务,测试是否可以从github上获取到配置信息:
启动后,访问一下路径: http://config3344.com:3344/master/config-dev.yml
成功读取到!
7、几种常用的读取配置文件规则:——官网5种
-
/{lable}/{application}-{profile}.yml: {lable}分支号——上文的配置方式;
-
/{application}-{profile}.yml:省略了{lable}号,默认为master分支;
-
/{application}/{profile}[/{lable}]:这种方式将配置数据读取到后,需要自己去解析读取到的信息;——还是上面的较好
三、Config客户端配置与测试
1、新建模块cloud-config-client3355
pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud2020</artifactId> <groupId>com.jiguiquan.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-config-client3355</artifactId> <dependencies> <!--springcloud config client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> </dependency> <!--eureka-client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--公共服务模块依赖--> <dependency> <groupId>com.jiguiquan.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!--springboot项目web和actuator最好一起走--> <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> <!--热部署devtools--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies> </project>
2、配置文件bootstrap.yml:
为什么是bootstrap.yml,而不再是application.yml,这两者的区别:
-
application.yml:用户级,资源配置项
-
bootstrap.yml:系统级,优先级更高
使用bootstrap.yml,SpringCloud会创建一个“Bootstrap Context”,它是“Application Context”的父级上下文,初始化的时候,“Bootstrap COntext”负责从外部源加载配置属性并解析配置。
这两个上下文共享一个从外部获取的“Environment”;
“Bootstrap”属于高优先级,默认情况下,它们不会被本地配置所覆盖。“Bootstrap Context”和“Application Context”有着不同的约定,所以增加了一个“bootstrap.yml”文件,保证“Bootstrap Context”和“Application Context”配置文件的分离;
要将Client模块下的application.yml文件改为bootstrap.yml,这是很关键的,因为“bootstrap.yml”的优先级更高!
bootstrap.yml:
server: port: 3355 spring: application: name: config-client cloud: config: lable: master name: config #配置文件名称 profile: dev #配置文件后缀 uri: http://localhost:3344 #配置中心地址 eureka: client: service-url: defaultZone: http://localhost:7001/eureka
3、主启动类 ConfigClientMain3355.java
@SpringBootApplication @EnableEurekaClient public class ConfigClientMain3355 { public static void main(String[] args) { SpringApplication.run(ConfigClientMain3355.class, args); } }
4、写一个简单的业务类ConfigClientController:
@RestController public class ConfigClientController { @Value("${config.info}") private String configInfo; @GetMapping("/configInfo") public String getConfigInfo(){ return configInfo; } }
5、启动服务进行测试:访问链接: http://localhost:3355/configInfo
显然config-client通过config-server成功地读取到了github上面的配置信息;
6、现在我们尝试将github上对应的文件文件进行修改,比如将version修改为2.0:
此时我们访问3344服务: http://localhost:3344/master/config-dev.yml
显然,配置服务器3344已经感知到了配置文件的变化;
但是当我们访问3355服务时,发现配置信息并没有变化: http://localhost:3355/configInfo
必须要重启3355服务后才可以生效!
那么问题来了:南岛我们每次修改配置信息后,都需要重启服务吗?显然不可以,所以我们要实现服务3355对配置文件的动态刷新!
四、Config客户端配置的动态刷新
1、动态刷新的目的?
避免每一次更新配置文件斗殴要重启客户端微服务!
2、确保服务添加了监控依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
3、在配置文件bootstrap.yml中,暴露监控端点:
#暴露监控端点 management: endpoints: web: exposure: include: "*"
4、在业务类ConfigClientController中增加注解 @RefreshScope
5、再次启动3355程序,并在github修改配置文件 version为3.0,观察3344/3355服务的读取结果:
3344服务肯定没有问题,但是3355服务还是没有自动刷新,我们还需要再做最后一件事情;
6、向服务3355发送一次POST请求,刷新一次服务: curl -X POST "http://localhost:3355/actuator/refresh"
刷新请求会返回这样的结果:
此时我们再次访问: http://localhost:3355/configInfo
这样我们就在没有重启3355微服务的情况下,自动刷新了它的配置文件;
最后,思考:
如果只有一两个服务还好,如果我们有成百个服务呢,南岛每次都要挨个发POST请求进行手动刷新操作吗?
可否通过广播,一次通知,处处生效!——以实现大范围的自动刷新!
这样就引入了我们的 消息总线——BUS!
个人此项目代码地址(持续更新):