一、分布式配置中心概述

1、分布式系统面临的—-配置问题

微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的
服务。由于每个服务都需要必要的配置信息才能够运行,所以一套集中式的,动态的配置管理设施是必不可少的。

SpringCloud提供了ConfigServer【配置中心】来解决这个问题,我们每一个微服务自己都带着一个application.yml,上百个配置文件的管理就要管理上百个application.yml

2、配置中心是什么

image.png
SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置

官网: https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.2.1.RELEASE/reference/html/
由于SpringCloud Config默认使用Git来存储配置文件,最推荐与github整合。

3、配置中心怎么用

SpringCloud Config 分为服务端和客户端两部分。

服务端也成为分布式配置中心,他是一个独立的微服务应用,用来连接配置服务器并未客户端提供获取配置信息,加密/解密等信息访问接口。

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息配置服务器默认采用git来存储配置信息,这样既有助于对环境配置进行版本管理,并且可以通过git客户端来方便的管理和访问配置内容。

4、配置中心能干什么

  • 集中管理配置文件
  • 不同环境不同配置,动态化的配置更新,分环境部署比如 dev/test/prod/beta/release
  • 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务回想配置中心统一拉去配置自己的信息。
  • 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置。
  • 将配置信息以Rest接口的形式暴露。

二、Config服务端配置与测试

1、搭建

1.1 在github上创建一个springcloud_config的新仓库

1.2 获得新仓库的地址:https://github.com/xu-hao-tian/springcloud-config.git

1.3 本地硬盘目录上新建git仓库并clone

image.png

1.4 此时在工作目录会创建名为springcloud-config的文件夹。

在springcloud-config的文件夹种创建三个配置文件(为本次教学使用的),随后git add .,git commit -m “sth”等一系列上传操作上传到springcloud-config的新Repository。
自己创建文件:
该文件可以从周阳老师的github仓库克隆一份,复制到自己的仓库 https://github.com/zzyybs/springcloud-config

  • config-dev.yml
  • config-prod.yml
  • config-test.yml

    表示多个环境的配置文件 保存格式必须是 utf-8

1.5 新建Module模块 cloud-config-center-3344,它就是Cloud的配置中心模块 cloudConfig Center

1.6 pom添加依赖

  1. <dependencies>
  2. <!-- 分布式配置中心 -->
  3. <dependency>
  4. <groupId>org.springframework.cloud</groupId>
  5. <artifactId>spring-cloud-config-server</artifactId>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.springcloud</groupId>
  13. <artifactId>cloud-api-commons</artifactId>
  14. <version>${project.version}</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework.boot</groupId>
  18. <artifactId>spring-boot-starter-web</artifactId>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-actuator</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-devtools</artifactId>
  27. <scope>runtime</scope>
  28. <optional>true</optional>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.projectlombok</groupId>
  32. <artifactId>lombok</artifactId>
  33. <optional>true</optional>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-test</artifactId>
  38. <scope>test</scope>
  39. </dependency>
  40. </dependencies>

1.7 yml 配置文件

  1. server:
  2. port: 3344
  3. spring:
  4. application:
  5. name: cloud-config-center
  6. cloud:
  7. config:
  8. server:
  9. git:
  10. # Github上面git仓库的地址
  11. uri: https://github.com/zzyybs/springcloud-config
  12. # 搜索的目录
  13. search-paths:
  14. - springcloud-config
  15. # 分支
  16. label: master
  17. eureka:
  18. client:
  19. service-url:
  20. defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

1.8 主启动类@EnableConfigServer

@EnableConfigServer激活配置中心

  1. @EnableConfigServer
  2. @EnableEurekaClient
  3. @SpringBootApplication
  4. public class ConfigServerMain3344 {
  5. public static void main(String[] args) {
  6. SpringApplication.run(ConfigServerMain3344.class,args);
  7. }
  8. }

1.9 修改hosts文件,增加映射

127.0.0.1 config-3344.com

2.0 测试通过config微服务是否可以从GitHub上获取配置内容

成功实现了通过SpringCloud Config 通过github中获取配置信息

访问:http://localhost:3344/master/config-dev.yml
image.png

2、读取配置规则

2.1 /{label}/{application}-{profile}.yml(最推荐使用这种方式)

① 读取master分支

② 读取dev分支

2.2 /{application}-{profile}.yml

没有了分支那一项,是因为在application.yml中配置了 label: master
所以会先去读取master的 (就算不配label 也会先去master寻找)

2.3 /{application}-{profile}[/{label}]

这样读取的是 JSON串

三、客户端配置和测试

1、搭建

1.1 新建cloud-config-client-3355模块

1.2 pom

  1. <dependencies>
  2. <!-- 客户端的config 依赖 -->
  3. <dependency>
  4. <groupId>org.springframework.cloud</groupId>
  5. <artifactId>spring-cloud-starter-config</artifactId>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.springcloud</groupId>
  13. <artifactId>cloud-api-commons</artifactId>
  14. <version>${project.version}</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework.boot</groupId>
  18. <artifactId>spring-boot-starter-web</artifactId>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-actuator</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-devtools</artifactId>
  27. <scope>runtime</scope>
  28. <optional>true</optional>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.projectlombok</groupId>
  32. <artifactId>lombok</artifactId>
  33. <optional>true</optional>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-test</artifactId>
  38. <scope>test</scope>
  39. </dependency>
  40. </dependencies>

1.3 bootstrap.yml

① bootstrap.yml是什么

简单理解:bootstrap.yml 是用来读取并使用github上公共的配置的,而application.yml是模块自用的

application.yml 是用户级的资源配置项
bootstrap.yml是系统级的,优先级更高。

SpringCloud会创建一个 “Bootstrap Context”,作为Spring应用的”Application Context”的父上下文,初始化的时候,“Bootstrap Context”负责从外部源加载配置属性并且解析属性,这两个上下文共享一个从外部获取的”Environment”[环境]

BootStrap 属性有高优先级,默认情况下,他们不会被本地配置覆盖,“Bootstrap Context” 和“Application Context” 有着不同的约定,所以新增一个“bootstrap.yml”文件保证“Bootstrap Context” 和“Application Context”配置的分离

要将Client模块下的 application.yml文件改为bootstrap.yml,这是很关键的。
因为bootstrap.yml是要比application.yml先加载的,bootstrap.yml优先级高于application.yml

  1. server:
  2. port: 3355
  3. spring:
  4. cloud:
  5. config:
  6. label: master # 哪个分支
  7. name: config # 什么名字
  8. profile: dev # 名字-xxx 什么环境
  9. uri: http://localhost:3344 # 配置中心地址
  10. # 上面的进行拼接后位: http://localhost:3344/master/config-dev.yaml
  11. eureka:
  12. client:
  13. service-url:
  14. defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

image.png

1.4 主启动类

  1. @EnableEurekaClient
  2. @SpringBootApplication
  3. public class ConfigConsumerMain3355 {
  4. public static void main(String[] args) {
  5. SpringApplication.run(ConfigConsumerMain3355.class,args);
  6. }
  7. }

1.5 业务类

这里的@Value(“${config.info}’)是从github上的配置文件中获取到的

  1. @RestController
  2. public class ConfigController {
  3. /**
  4. * 这里取的值是从github上取回来的
  5. */
  6. @Value("${config.info}")
  7. private String configInfo;
  8. @RequestMapping("/config/info")
  9. public String test(){
  10. return configInfo;
  11. }
  12. }

1.6 测试

image.png

成功实现了客户端3355访问SpringCloud Config3344通过GitHub获取配置信息

四、客户端的动态刷新

1、问题:分布式的动态刷新问题

Linux运维修改了GitHub上的配置文件内容做调整。
刷新3344,发现ConfigServer配置中心立刻响应。
刷新3355,发现ConfigClient客户端没有任何响应。
3355没有变化除非自己重新启动或者重新加载。
难道每次运维修改配置文件,客户端都要重新启动?噩梦?

2、步骤

2.1 修改3355客户端模块

2.1 添加依赖 图形化监控

  1. <!--图形化监控依赖-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-actuator</artifactId>
  5. </dependency>

2.2 修改yml,暴露监控端口

  1. # 暴漏监控端点
  2. management:
  3. endpoints:
  4. web:
  5. exposure:
  6. include: "*"

2.3 controller层添加@RefreshScope注解

  1. @RefreshScope
  2. @RestController
  3. public class ConfigController {
  4. /**
  5. * 这里取的值是从github上取回来的
  6. */
  7. @Value("${config.info}")
  8. private String configInfo;
  9. @RequestMapping("/test/config/info")
  10. public String test(){
  11. return configInfo;
  12. }
  13. }

2.4 运维修改github之后 给3355发一个post请求

目的是告诉3355 github上的配置文件已经修改了,请重新加载

发送的地址为 :http://localhost:3355/actuator/refresh 【注意是post请求】

2.5 测试

3、存留问题

虽然这种方式解决了不重启3355客户端的问题,但是如果有100个机器需要重新加载配置文件呢
所以这就需要使用 消息总线来进行广播。