概述

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

微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息财能运行,所以一集中式的、动态的配置管理设施是必不可少的。
SpringCloud提供了ConfigServer来解决这个问题,我们每一个微服务自 己带着一个application.yml,.
上百个配置文件的管理….

是什么

14 SpringCloud config分布式配置中心 - 图1
是什么
SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。

怎么玩
SpringCloud Config分为服务端和客户端两部分。
服务端也称为分布式配置中心,它是-个独立的微服务应用,睐连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口

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

能干嘛

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

代码实践

新建Module模块cloud-config-center-3344

POM

  1. <dependencies>
  2. <!--config server-->
  3. <dependency>
  4. <groupId>org.springframework.cloud</groupId>
  5. <artifactId>spring-cloud-config-server</artifactId>
  6. </dependency>
  7. <dependency><!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
  8. <groupId>com.carve.springcloud</groupId>
  9. <artifactId>cloud-api-common</artifactId>
  10. <version>1.0-SNAPSHOT</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-web</artifactId>
  15. </dependency>
  16. <!--监控-->
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-actuator</artifactId>
  20. </dependency>
  21. <!--eureka client-->
  22. <dependency>
  23. <groupId>org.springframework.cloud</groupId>
  24. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  25. </dependency>
  26. <!--热部署-->
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-devtools</artifactId>
  30. <scope>runtime</scope>
  31. <optional>true</optional>
  32. </dependency>
  33. <dependency>
  34. <groupId>org.projectlombok</groupId>
  35. <artifactId>lombok</artifactId>
  36. <optional>true</optional>
  37. </dependency>
  38. <dependency>
  39. <groupId>org.springframework.boot</groupId>
  40. <artifactId>spring-boot-starter-test</artifactId>
  41. <scope>test</scope>
  42. </dependency>
  43. </dependencies>

YML

  1. server:
  2. port: 3344
  3. spring:
  4. application:
  5. name: cloud-config-center
  6. cloud:
  7. config:
  8. server:
  9. git:
  10. uri: https://gitee.com/xilidexiao/springcloud-config.git #Github上的git仓库名字
  11. ##搜索目录.这个目录指的是github上的目录
  12. search-paths:
  13. - springcloud-config
  14. ##读取分支
  15. label: master
  16. eureka:
  17. client:
  18. service-url:
  19. defaultZone: http://eureka7001.com:7001/eureka/

主启动类

ConfigCenterMain3344
@EnableConfigServer

@SpringBootApplication
@EnableConfigServer
public class ConfigCenterMain3344 {

    public static void main(String[] args) {
        SpringApplication.run(ConfigCenterMain3344.class,args);
    }
}

windows下修改hosts文件,增加映射

127.0.0.1 config-3344.com

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

启动服务3344

http://config-3344.com:3344/master/config-dev.yml

读取配置规则

官网

image.png

/{label}/{application}-{profile}.yml

  • master分支
  • dev分支

/{application}-{profile}.yml

/{application}/{profile}/{/label}

重点配置细节总结

14 SpringCloud config分布式配置中心 - 图3

成功实现了SpringCloudConfig通过Github获取配置信息

Config客户端配置与测试

新建cloud-config-client-3355

POM

<dependencies>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
  </dependency>
  <dependency><!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
    <groupId>com.carve.springcloud</groupId>
    <artifactId>cloud-api-common</artifactId>
    <version>1.0-SNAPSHOT</version>
  </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>
  <!--eureka client-->
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</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>

bootstrap.yml

applicaiton. ym1是用户级的资源配置项
bootstrap . ym1是系统级的,优先级更加高
Spring Cloud会创建一个”Bootstrap Context” ,作为Spring应用的Application
Context的父上下文。初始化的时候,‘Bootstrap
Context’负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的’Environment’。

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

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

server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: master #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称 上诉3个综合就是 master分支上 config-dev.yml
      uri: http://localhost:3344
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

修改config-dev.yml配置并提交到GitHub中,比如加个变量age或者版本号version

主启动

@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3355 {

    public static void main(String[] args) {
        SpringApplication.run(ConfigClientMain3355.class,args);
    }
}

业务类

@RestController
public class ConfigClientController {

    // 因为config仓库以rest形式暴露,所以所有客户端都可以通过config服务端访问到github上对应的文件信息
    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String getConfigInfo() {
        return  configInfo;
    }
}

测试

启动Config配置中心3344和eureka7001:http://config-3344.com:3344/master/config-dev.yml
启动3355作为Client准备访问:

问题随之而来,分布式配置的动态刷新问题

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

Config客户端之动态刷新

修改3355模块

POM引入actuator监控

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

修改YML,暴露监控端口

#暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

@RefreshScope业务类Controller修改

@RestController
@RefreshScope
public class ConfigClientController {

    // 因为config仓库以rest形式暴露,所以所有客户端都可以通过config服务端访问到github上对应的文件信息
    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String getConfigInfo() {
        return  configInfo;
    }
}

发送刷新请求

测试

http://localhost:3355/configInfo
成功实现了客户端3355刷新到最新配置内容:避免了服务重启

想想还有什么问题

  • 假如有多个微服务客户端3355,3366,3377.。。。
  • 每个微服务都要执行一次post请求,手动刷新?
  • 可否广播,一次通知,处处生效
  • 我们想大范围的自动刷新求方法