• SpringCloud Config-分布式配置中心


    1. 介绍

    分布式微服务系统面临的问题

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

    例如:

    1. 不同环境,不同配置。例如,数据源配置在不同的环境(开发、测试、预发布、生产等)中是不同的
    2. 运行期间可动态调整。例如,我们可根据各个微服务的负载情况,动态调整数据源连接池大小或熔断阈值,并且在调整配置时不停止微服务
    3. 配置修改后可自动更新。如配置内容发生变化,微服务能够自动更新配置。

    而Spring Cloud 就可以顺利解决这个问题,

    官方文档: https://docs.spring.io/spring-cloud-config/docs/2.2.5.RELEASE/reference/html/

    SpringConfig 简介

    Spring Cloud Config为分布式系统外部化配置提供了服务器端和客户端的支持,它包括Config Server和Config Client两部分。

    Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环 境下的配置,默认使用Git存储配置内容(也可使用Subversion、本地文件系统或Vault存储 配置),因此可以方便的实现对配置的版本控制与内容审计。 Config Client 是Config Server的客户端,在启动或刷新时读取存储在Config Server中的配置属性,

    2. 基本使用

    2.1 SpringConfig Server 搭建

    Server端也是作为Eureka的Clinet注册进注册中心,

    同时他也需要依赖一个配置文件的管理地址,这里我使用gitee,
    首先我们需要创建一个仓库,并将本地创建好的不同环境的配置文件写好(必须是UTF-8),并上传到仓库中,入图所示

    内容分别是:

    • config-dev.yml

      config:
        info: "master branch,springcloud-config/config-dev.yml version=121" 
      
    • config-prod.yml

      config:
        info: "master branch,springcloud-config/config-prod.yml version=8" 
      
    • config-test.yml

      config:
        info: "master branch,springcloud-config/config-test.yml version=8" 
      

    下面开始搭建服务端

    pom文件依赖:

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        
        <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.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    

    Yaml配置文件

    server:
      port: 3344
    spring:
      application:
        name: cloud-config-center
      cloud:
        config:
          server:
            git:
              uri: https://gitee.com/xxxx/springcloud-config.git # 你的git项目地址
              username: username #如果仓库为私有的则需要配置账号密码
              password: password
          label: master #默认master分支
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
    

    主启动类:

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

    启动成功后,测试是否可以访问git, 访问地址:http://127.0.0.1:3344/master/config-dev.yml,成功访问git中对应配置文件信息

    访问规则

    在上面的测试中,我们使用一个链接,访问到了 配置文件信息, SpringConfig 中提供了多种方式,下面列举常用的几种

    1. 通过{application}-{profiles}.yml来访问
      • http://127.0.0.1:3344/config-dev.yml
      • http://127.0.0.1:3344/config-test.yml
      • http://127.0.0.1:3344/config-prod.yml
    2. 通过/{application}-{profiles}/{lable}
      • http://127.0.0.1:3344/config-test/marter
      • http://127.0.0.1:3344/config-dev/marter
      • http://127.0.0.1:3344/config-prod/marter
    3. 通过/lable/application-{profiles}.yml (推荐)
      • http://127.0.0.1:3344/master/config-dev.yml
      • http://127.0.0.1:3344/master/config-test.yml
      • http://127.0.0.1:3344/master/config-prod.yml

    2.2 SpringConfig Clinet 搭建

    client 端用于读取 Server中的配置信息,一般为普通的业务微服务

    Pom依赖: 和Server端没有区别

    bootstrap.yml

    因为项目中的配置信息,需要从Config Server 中读取,用来初始化项目中的各个模块,那么Config Server 地址等信息应该在bootstrap.yml

    中配置,

    • 此配置文件为引导类配置文件, 优先级最高,并且是在项目启动初始化前就已经被加载,,Spring Cloud 会创建一个 "Bootstrap Context",作为Spring应用的 "Application Context" 的父上下文, 初始化的时候, "Bootstrap Context" 负责从外部源加载配置属性并解析配置, 这两个上下文共享一个外部获取的"Environment"

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

    所以将Config Server的配置信息 配置在这里才可以被读取

    bootstrap.yml信息(放在resources根目录下即可)

    server:
      port: 3355
    
    spring:
      application:
        name: config-client
      cloud:
        config:
          label: master # 分支名
          name: config # 配置文件名称
          profile: dev # 环境后缀名称
          uri: http://localhost:3344  # 综上所述, 最终读取的文件为 http://localhost:3344/master/config-dev.yml
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
    

    测试controller,获取从Server端读取的配置信息

    @RestController
    @RefreshScope //手动刷新
    public class ConfigClientController {
    
        @Value("${config.info}")
        private String configInfo;
    
        @GetMapping("/configInfo")
        public String getConfigInfo(){
            return configInfo;
        }
    
    }
    

    启动类

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

    测试:

    浏览器访问接口: http://127.0.0.1:3355/configInfo,返回读取的信息master branch,springcloud-config/config-dev.yml version=121

    3. Config客户端动态刷新

    此时,当我们模拟运维人员,对git中的配置文件进行修改,并提交

    • 刷新3344,Server端, 发现 Config Server 配置中心立刻响应

    • 刷新3355,Clinet端, 发现 Config Server 配置中心没有刷新

    那么,如果修改了配置文件,我们就需要将所有的客户端都进行重启加载,这在实际生产环境中,几乎是不可能的事情,所以我们需要使客户端自动刷新

    修改Pom文件,添加额外的依赖(actuator包的功能可以自行百度学习,这里使用了它动态加载配置文件的功能)

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

    开启refresh的监控端口

    management:
      endpoints:
        web:
          exposure:
            include: "*"   #开启所有的端点
    

    在读取配置文件的类上加上@RefreshScope注解

    @RefreshScope
    @RestController
    public class ConfigClientController {
    
        @Value("${config.info}")
        private String configInfo;
    
        @GetMapping("/configInfo")
        public String getConfigInfo(){
            return configInfo;
        }
    }
    

    测试:

    修改dev文件 version改为 130

    config:
      info: "master branch,springcloud-config/config-dev.yml version=130" 
    

    再调用client端 接口http://127.0.0.1:3355/actuator/refresh(使用post请求)刷新配置信息, (调用此接口,使用actuator的功能,会清除注解@RefreshScope的缓存以及@ConfigurationProperties 重新加载,也就是将用户自定义使用到的配置文件和Spring Boot项目中各种自动配置的信息都刷新一遍)

    再读取client端的信息: http://127.0.0.1:3355/configInfo, 发现已经更新master branch,springcloud-config/config-dev.yml version=130

    4. config bus 消息总线支持

    在上一节中,我们解决了 修改配置文件,需要重启项目的问题,但是如果微服务过多,那么每次修改配置文件,大量的微服务都需要手动调用请求进行刷新,也是一个比较烦人的工作, 也可以对此进行优化

    方式一:

    可以利用消息队列的通知方式, 设定一个消息总线方,一般就为 Config Server 端, 设定一个Http 接口, 接口中向指定的队列中发送广播信号, 那么所有Config Server 端只需监听这个队列, 当接受到更新信息后,只需再代码中调用本服务的 Post 刷新接口即可,就可刷新本微服务的配置信息,

    如此,当我们修改完配置后,只需调用总线的Http接口,就可自动更新所有Clinet端配置信息

    方法二:

    使用 消息总线 bus来实现

    官方文档:https://spring.io/projects/spring-cloud-bus

    原理和上述方案一大致相同, 所以需要依赖 MQ 中间件, 目前仅仅支持 RabbitMq 和 Kafka,下面使用 Rabbitmq演示, 为了演示复杂性,再复制一份客户端, 端口为 3366

    Config Server端 和所有需要 Config Clinet 端 添加 相关依赖

        <!--    添加消息总线RabbitMQ支持    -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
    

    同时也都需要配置 RabbitMq的账号地址等信息

    server:
      port: 3344
    spring:
      application:
        name: cloud-config-center
      cloud:
        config:
          server:
            git:
              uri: https://gitee.com/xxxxx/springcloud-config.git
              username: username
              password: password
          label: master #默认master分支
      rabbitmq:
        virtual-host: /test
        host: dev.rabbitmq.md.com
        port: 5672
        username: username
        password: password
    

    但是此时,我们刷新的端点将不是Clinet本身,而是通过 Server端 刷新,并通知给所有客户端,所以Server也要依赖 actuator ,并开放端点

    修改Server端配置yml

    # 消息总线的支持 这个就是总线 只刷新这个
    management:
      endpoints:
        web:
          exposure:
            include: "*" # 开放所有,也可以仅仅开放消息总线的支持 bus-refresh
    

    测试:

    修改git中的文件, 并调用 Server 端刷新消息总线接口:http://127.0.0.1:3344/actuator/bus-refresh (Post方式),

    这时候我们发现, Clinet端 无须任何操作,配置文件就已经刷新 可以调用接口查询:http://127.0.0.1:3355/configInfo,说明消息总线配置成功,

    通过查看RabbitMq的 后台管理页面,可以看见, 在Rabbitmq中自动创建了一个交换机 springCloudBus ,用于通知

    单独通知某一个微服务

    在上面的案例中,我们刷新后,所有监听mq的客户端都会刷新配置文件,但是当我们想要单独刷新某一个客户端微服务时,也可以使用如下的方式

    调用Server端总线接口刷新: http://127.0.0.1:3344/actuator/bus-refresh/{destination},并指定某一个微服务,

    例如: http://127.0.0.1:3344/actuator/bus-refresh/config-client:3355, (微服务名:端口的方式), 可以单独刷新某一个微服务

  • 相关阅读:
    String对象的属性和方法
    Math对象的属性和方法
    对象Date的方法
    HTML5和CSS3阶段,我是如何学习的?
    移动端项目开发心得
    关于元素隐藏/显示的各种方法
    啊哈算法(一)
    项目心得。
    CSS篇之DIV+CSS布局
    CSS篇之动画(2)
  • 原文地址:https://www.cnblogs.com/xjwhaha/p/14215359.html
Copyright © 2020-2023  润新知