SpringCloud Config分布式配置中心

1、介绍

①what

微服务意味着需要将单体拆成很多子服务,每个服务都需要配置才能运行。所以需要一套集中式,动态的配置管理,来解决这个问题。

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

SpringCloud Config也分为服务端客户端还需要Git仓库管理配置文件夹,在③how中有介绍

服务端:也成为分布式配置中心,是一个独立的微服务应用

客户端:通过指定的配置中心管理应用资源,以及业务相关的配置内容,

②why

  • 不同的环境有不同的配置,动态化配置更新,比如dev /test/prod/beta/release
  • 不需要再每个服务器编写配置文件,服务会向配置中心统一拉取配置自己的信息
  • 当配置改变,服务不需要重启就能应用新的配置
  • 将配置信息以Rest接口暴露

③how

springcloud config是如何获取配置中心的文件,然后进行集中配置下方的呢?

如下图:

Config Server通过本地的Git仓库,和Remote的Git仓库,获取配置信息,然后再集中对各个微服务进行配置。

所以springcloud config需要三个部分:

  1. 本地/远程Git仓库:存储配置信息
  2. Config Server:分布式配置中心
  3. Client:从配置中心获取配置

image-20230117220343071

2、搭建

①Git仓库搭建

在github上创建springcloud-config项目

image-20230117224353980

初始化仓库

image-20230117224415560

如图,创建文件和文件夹:

image-20230117224652203

push到远程仓库

②Config Server搭建

原来的项目(不是上面Git搭建的项目)中新建子模块cloud-config-center-3344

image-20230118002732968

pom.xml:

<dependencies>
    <!--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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</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>

yml:

image-20230118003053384

server:
  port: 3344

spring:
  application:
    name: cloud-config-center #注册进Eureka服务器的微服务名
  cloud:
    config:
      server:
        git:
          uri: https://github.com/zko0/springcloud-config.git  #git的仓库地址
          search-paths:   #搜索目录
            - springcloud-config
          #如果仓库为私有,需要下面的认证信息
          #username: zko0 用户名
          #password: xxxxxxx token
      label: master   #读取的分支

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka   #服务注册到的eureka地址

启动类:

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

修改springcloud-config工程中的配置文件:

image-20230118003834522

Push到远端仓库

image-20230118003953850

启动Eureka注册中心7001,Config配置中心3344

image-20230118010325146

调用Config配置中心的接口,测试,成功:

image-20230118010349048

调用接口的三种URL方式:

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

    lable:分支,application:配置前缀名,profile:配置后缀名

    ip:port/master/config-dev.yml

    这种方式显示的是配置文件的内容

    image-20230118010349048

  2. /{application}-{profile}.yml (这种情况默认找master)

    application:配置前缀名,profile:配置后缀名

    ip:port/config-dev.yml

    同1

  3. /{application}-{profile}/

    lable:分支,application:配置前缀名,profile:配置后缀名

    ip:port/config-dev/master

    这种方式显示的json串,格式也有所区别

    image-20230118011241043

③Clinet搭建

新建模块cloud-config-client-3355

image-20230118012238950

pom.xml:

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

yml:

application.yml是用户级别的资源配置项

bootstrap.yml是系统级别的,优先级更高

需要将Client模块的application.yml文件改为bootstrap.yml,这很重要,因为bootstrap.yml比application.yml先加载,bootstrap.yml优先级更高

官方解释:

Spring Cloud 构建于 Spring Boot 之上,在 Spring Boot 中有两种上下文,一种是 bootstrap, 另外一种是 application, bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。bootstrap 主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。bootstrap 里面的属性会优先加载,它们默认也不能被本地相同配置覆盖。

image-20230118012657175

server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    config: #config客户端配置
      label: master   #分支名称
      name: config    #配置文件名称       这三个综合:master分支上的config-dev.yml的配置文件
      profile: dev    #读取后缀名称       被读取到http://config-3344.com:3344/master/config/dev
      uri: http://localhost:3344  #配置中心地址

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka   #服务注册到的eureka地址

启动类:

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

Controller:

通过@Value获取配置文件中的value,通过接口展现出来:

@RestController
public class ConfigClientController {

    @Value("${config.info}")   //spring的@Value注解
    private String configInfo;

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

}

启动Eureka注册中心7001,Config配置中心3344,Config Client3355:

image-20230118013549958

测试3344获取3355所需的配置文件:

image-20230118013609831

测试3355接口:

image-20230118013640553

3、动态刷新

①问题演示

在2的基础上,我们修改仓库中的配置文件:

image-20230118014001099

过了一段时间(可能需要1min以上),访问334获取dev配置,成功刷新了:

image-20230118014335914

但是此时访问3355,通过@Value注入的值,没有刷新:

image-20230118014440245

如果需要3355获取最新的值,重启3355即可。

PS:上面的配置动态更新,还需要重启服务才能生效,不是很傻逼的操作吗?

对,很傻逼,下面有更好的方式

②Client动态刷新(还是需要手动)

往config客户端3355添加健康监控依赖

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

然后在bootstrap.yml中添加配置:

关于这里的配置,需要学习Actuator的知识,本人也没有进行系统的学习,看到这篇博客写的不错,也涉及了该部分配置的含义讲解。

Actuator

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

在Controller上添加注解开启动态刷新:

image-20230118015049621

启动3355,测试:

首先3355与dev配置文件的value相同

image-20230118015521537

更新dev配置文件,将version修改为3:

image-20230118015604531

等待一段时间,3344的配置中心可以获取到version为3的配置:

image-20230118020552727

需要向3355发送post请求,手动刷新:

http://localhost:3355/actuator/refresh

image-20230118020406844

此时3355的version就变更为3了,成功:

image-20230118020637567

③问题

  • 需要手动发送Post(虽然可以写个脚本发送,但是还是不完美)

  • 不能广播,一次通知,全部生效,只能单个通知

  • 大范围自动刷新

posted @ 2023-01-18 02:13  yikolemon  阅读(64)  评论(0)    收藏  举报