Spring Cloud Config 实现分布式配置中心及动态刷新机制配置

    科技2022-07-11  90

    目录

    前言1. 微服务面临的问题2. 了解 Spring Cloud Config2.1 Config 何方神圣 (Config 是什么?) 3.Git 远程服务器配置3.1 创建存储 Config 的新 Repository 4. 服务端配置4.1 创建ConfigServer模块4.2 引入 pom.xml 依赖4.3 启动类加入@EnableConfigServer注解4.4 配置文件 application.yml4.5 访问测试 5. 客户端配置5.1 客户端模块5.2 引入 pom.xml 依赖5.3 配置文件Ⅰ. bootstarp.yml 是什么Ⅱ. bootstarp.yml 配置 5.4 controller 业务配置5.5 启动客户端模块、测试 6. 分布式配置 动态刷新 问题6.1 pom.xml 引入 actuator 监控依赖6.2 修改 yml 新增暴露监控端口配置6.3 Controller层添加 @RefreshScope 注解6.4 修改远程 GitHub 配置,手动刷新演示6.5 手动动态刷新,存在的问题 参考文献

    前言

    本文来介绍 Spring Cloud Config 分布式配置中心 相关内容。首先来谈谈为什么要引入 Spring Cloud Config 分布式配置中心这么个玩意。

    Spring Cloud Config 和 Spring Cloud Bus 这两哥们,倒是谈不上 停更进维,在开发中还在使用。但是在接下来将会慢慢的被 后起之秀 Alibaba Nacos 所替代。

    Nacos 可以替代 EurekaSpring Cloud ConfigSpring Cloud Bus 。一代三减少更多组件的使用,这样我们就可以在工作中将更多的经历放在业务逻辑上。Spring Cloud Cofig 和 Spring Cloud Bus 这两个组件还是比较重要,很多公司都有在使用。

    微服务在 服务配置 + 服务总线 这块进行选型,共有三套方案:1.Spring Cloud Config + Spring Cloud Bus2.Spring Cloud Alibaba Nacos (Nacos 官网)、3.携程 Apollo(Github 地址:Apollo)

    1. 微服务面临的问题

    到目前为止,我们对 Eureka、Robbin、Feign、Hystrix、Gateway 等有了相应的了解,每个微服务都是单独一个模块,微服务彼此还支持集群环境。

    但是在微服务项目的开发中,还面临着一个严重的配置问题。每一个微服务都需要一个配置文件,如果有几个微服务需要连接数据库,name就需要进行 4 次数据库的配置。当数据库发生改变,那么就需要同时修改 4 个微服务的配置文件才可以。那么如果有40台呢?如果是集群模式呢??

    如果能够做到:一处修改、处处生效,这样就可以减轻修改配置压力,从而增强配置管理方面的功能,此时就需要 Spring Cloud Config 和 Spring Cloud Bus 上场了。

    使用 Config + Bus,可以实现 1.一处修改、处处生效,同时也可以 2.灵活的对版本(dev/test/prod)进行切换,这样就足够方便了。本文先来介绍 Spring Cloud Config

    2. 了解 Spring Cloud Config

    Spring Cloud Config 为微服务架构中的微服务 提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境 提供了一个中心化的外部配置。(公共配置都去配置中心读取,私有配置,各个服务独自配置)

    附:Spring Cloud Config 官网

    2.1 Config 何方神圣 (Config 是什么?)

    Spring Cloud Config 分为 服务端 和 客户端。

    服务端:也称为 分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口。就是图中的 Config Server;客户端:通过指定的 配置中心(Config Server) 来管理应用资源,以及与业务相关的配置内容,并在启动的时候从 配置中心 获取和加载配置信息。

    Tips:服务器默认采用 Git 来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过 Git 客户端工具来方便的管理和访问配置内容。(服务器也支持其他方式:支持SVN 和 本地文件,最推荐 Git,而且使用的是 http/https 访问的形式)

    3.Git 远程服务器配置

    以下操作,需要在 Github 下进行操作。如果你需要了解 Git 相关内容:TODO

    3.1 创建存储 Config 的新 Repository

    登陆 Git 平台 (github,开源中国git,码云git,阿里云git,或者自己搭建的gitlab服务器等…),进行新 Repository 的创建。此处新创建的 Repository 名称为:cloud_config 。

    Repository 创建成功,即可获取自己的仓库地址。我创建的仓库地址为:https://gitee.com/it-lemon/config-repo.git

    创建服务配置文件, 命名规则为 {name}-{profiles}.yml 例如:pro-dev.yml 、pro-test.yml 、pro-pro.yml

    4. 服务端配置

    服务端:也称为 分布式配置中心,它是一个独立的微服务应用。我们现在就来对服务端 ConfigServer 进行配置。

    4.1 创建ConfigServer模块

    它是一个独立的微服务应用,此处模块名称命名为:config-server

    4.2 引入 pom.xml 依赖

    <!--引入spring-cloud-config-server依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <!--注册到eureka注册中心需要的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>

    4.3 启动类加入@EnableConfigServer注解

    @SpringBootApplication @EnableConfigServer public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }

    4.4 配置文件 application.yml

    server: port: 3344 spring: application: name: config-server cloud: config: server: git: uri: https://gitee.com/laomao1024/config-repo.git username: xxxxxxxxxxx password: xxxxxxxxxxx timeout: 5 default-label: master #指定注册中心地址 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/

    4.5 访问测试

    通过以上配置之后我们的 configServer 就配置完成了

    启动 Config 模块后,测试通过 Config 微服务是否可以从 Github上获取配置内容,我们可以通过 http://localhost:3344/product-dev.yml 进行访问对应配置文件,能成功访问到配置就说明 OK!

    5. 客户端配置

    客服端:在启动的时候从 配置中心(Config Server) 获取和加载配置信息。

    5.1 客户端模块

    创建客户端模块,用来读取ConfigServer配置。此处模块名称为:config-client

    5.2 引入 pom.xml 依赖

    <!--引入spring-cloud-starter-config依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>

    5.3 配置文件

    注意:此处需要增加的是一个 bootstap.yml 文件。

    Ⅰ. bootstarp.yml 是什么

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

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

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

    所以,将客户端模块下的 application.yml 文件改为 bootstrap.yml ,这是很关键的。 因为 bootstrap.yml 是比 application.yml 优先加载的。bootstrap.yml 优先级高于 applicaiton.yml。

    Ⅱ. bootstarp.yml 配置
    server: port: 8771 #指定注册中心地址 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ #服务的名称 spring: application: name: product-service cloud: config: discovery: service-id: CONFIG-SERVER enabled: true profile: dev

    5.4 controller 业务配置

    @RestController @RequestMapping("/api/v1/product") public class ProductController { @Value("${config.name}") private String name; @RequestMapping("/name") public Object getName(){ return name; } }

    5.5 启动客户端模块、测试

    Config 模块需要注册到 Eureka Server,先启动 Eureka 服务。然后启动 Config Server 3344 模块,最后启动 Client 8771 模块。我们通过地址:http://127.0.0.1:8771/api/v1/product/name 发现可以成功读取到 ConfigServer 中的 product-dev.yml 配置。

    需要获取 test、prod 等环境配置信息,只需要修改 bootstrap.yml 配置内容 中的相关属性,即可获取响应环境的配置信息。

    6. 分布式配置 动态刷新 问题

    当 GitHub 上的配置文件内容有调整,Github中配置变更后,ConfigServer 配置中心会立刻响应,然鹅客户端却没有任何响应,除非客户端重启或者重新加载,才能够获取最新的配置。 难道每次修改配置文件,客户端都需要重启吗??

    为了避免每次修改 GitHub 配置文件后,客户端都需要重启的问题,此处就引出了客户端 动态刷新 的问题。

    接下来对客户端进行 动态刷新 配置

    6.1 pom.xml 引入 actuator 监控依赖

    <!--引入actuator监控--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>

    6.2 修改 yml 新增暴露监控端口配置

    #暴露监控端点 management: endpoints: web: exposure: include: "*" #此处有很多选项可以配置,为了省事 ,直接配置 *

    6.3 Controller层添加 @RefreshScope 注解

    @RestController @RefreshScope @RequestMapping("/api/v1/product") public class ProductController { @Value("${config.name}") private String name; @RequestMapping("/name") public Object getName(){ return name; } }

    6.4 修改远程 GitHub 配置,手动刷新演示

    发送命令http://微服务地址:端口/actuator/refresh,刷新客户端。该请求必须是 Post 方式。经过上述一番配置,便可避免服务的重启,成功实现客户端刷新到最新配置内容。

    发送请求可以使用PostMan也可以使用curl命令 curl -X POST "http://微服务地址:端口号/actuator/refresh"

    6.5 手动动态刷新,存在的问题

    实现了动态刷新,解决了 ConfigClient 重启才能获取最新配置信息问题。假如有 N 多个台,就需要 N 多次的 curl -X POST "http://微服务地址:端口号/actuator/refresh"。这仍然是一个噩梦,还是没有解决根本问题。

    大规模 微服务/集群模式,我们可以采用广播的方式,一次通知,处处生效。类似于 消息队列的 Topic ,微信公众号 的概念,一次订阅,所有订阅者都能接收到新消息。

    他来了,他来了,Spring Cloud Bus 总线 带着 消息队列/广播机制 向我们走来了。Spring Cloud Bus 总线 可以帮我们实现以下功能:

    真正实现:一处通知、处处生效实现精确通知,只通知集群中的某些服务 (精确通知,比如有100台机器,只通知前98台)

    参考文献

    https://blog.csdn.net/lzb348110175/article/details/107387510

    Processed: 0.010, SQL: 8