SpringCloud学习——配置中心


在分布式微服务系统中,几乎所有服务的运行都离不开配置文件的支持,这些配置文件通常由各个服务自行管理,以 properties 或 yml 格式保存在各个微服务的类路径下,例如 application.properties 或 application.yml 等。

这种将配置文件散落在各个服务中的管理方式,存在以下问题:

  • 管理难度大:配置文件散落在各个微服务中,难以管理。
  • 安全性低:配置跟随源代码保存在代码库中,容易造成配置泄漏。
  • 时效性差:微服务中的配置修改后,必须重启服务,否则无法生效。
  • 局限性明显:无法支持动态调整,例如日志开关、功能开关。

Config

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

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

  • Config Server:也被称为分布式配置中心,它是一个独立运行的微服务应用,用来连接配置仓库并为客户端提供获取配置信息、加密信息和解密信息的访问接口。
  • Config Client:指的是微服务架构中的各个微服务,它们通过 Config Server 对配置进行管理,并从 Config Sever 中获取和加载配置信息。

Spring Cloud Config 默认使用 Git 存储配置信息,因此使用 Spirng Cloud Config 构建的配置服务器天然就支持对微服务配置的版本管理。我们可以使用 Git 客户端工具方便地对配置内容进行管理和访问。

Config 工作原理

Spring Cloud Config 工作流程如下:

  1. 开发或运维人员提交配置文件到远程的 Git 仓库。
  2. Config 服务端(分布式配置中心)负责连接配置仓库 Git,并对 Config 客户端暴露获取配置的接口。
  3. Config 客户端通过 Config 服务端暴露出来的接口,拉取配置仓库中的配置。
  4. Config 客户端获取到配置信息,以支持服务的运行。

在这里插入图片描述

Config 的特点与作用

Spring Cloud Config 具有以下特点与作用:

  • 集中管理配置文件。
  • 一个应用可能有多个环境,例如开发(dev)环境、测试(test)环境、生产(prod)环境等等,开发人员可以通过 Spring Cloud Config 对不同环境的各配置进行管理,且能够确保应用在环境迁移后仍然有完整的配置支持其正常运行。
  • 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务可以通过 Spring Cloud Config 向配置中心统一拉取属于它们自己的配置信息。
  • 当配置发生变化时,微服务不需要重启即可感知到配置的变化,并自动获取和应用最新配置。
  • Config 将所有微服务的配置文件集中存储在一个外部的存储仓库或系统(例如 Git)中,统一管理。
  • Spring Cloud Config 配置中心将配置以 REST 接口的形式暴露给各个微服务,以方便各个微服务获取。

Config 服务端搭建

创建 Github 仓库,并创建多个配置文件:config-dev.yml、config-prod.yml、config-test.yml。

config:
  info: "master branch,SpringCloud-ConfigCenter/config-dev.yml version=1" 

创建 Config 微服务

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>
server:
  port: 3344
spring:
  application:
    name:  config-center
  cloud:
    config:
      server:
        git:
          uri: git@github.com:KimTou/SpringCloud-ConfigCenter.git #GitHub上面的git仓库名字
          ##搜索目录
          search-paths:
            - SpringCloud-ConfigCenter
          # 如果Git仓库为公开仓库,可以不填写用户名和密码,如果是私有仓库需要填写
          # username: ********
          # password: ********
      ##分支名
      label: master
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
@SpringBootApplication
@EnableConfigServer
public class ConfigApplication {

windows下修改hosts文件,增加映射(可配可不配)

127.0.0.1 config-3344.com

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


Config 客户端搭建

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

applicaiton.yml 是用户级的资源配置项;bootstrap.yml 是系统级的,优先级高于 application.yml。要将 Client 模块下的 application.yml 文件改为 bootstrap.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的配置文件被读取
      #http://config-3344.com:3344/master/config-dev.yml
      uri: http://localhost:3344  #配置中心地址
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

配置中心将配置以 REST 接口的形式暴露给各个微服务。从 3344 端口获取 /master/config-dev.yml 信息。

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

存在的问题是:

  • 配置更新后,Spring Cloud Config 服务端(Server)可以直接从 Git 仓库中获取最新的配置。
  • 除非重启 Spring Cloud Config 客户端(Client),否则无法通过 Spring Cloud Config 服务端获取最新的配置信息。

手动刷新配置

POM 引入 actuator 监控:

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

修改 bootstrap.yml,添加暴露监控端口配置:

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

使用 @RefreshScope 注解开启配置刷新

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

当修改配置文件后,要想 Config Client 也拉去到最新的配置,需要打开命令行窗口,手动使用以下命令发送一个 POST 请求刷新 Config 3355 客户端,通知客户端配置文件已经修改,需要重新拉去配置。

curl -X POST "http://localhost:3355/actuator/refresh"
手动刷新配置的问题

在上面的实例中,我们通过在 Config 客户端(端口号:3355)中引入 Spring Boot actuator 监控组件来监控配置的变化,使我们可以在不重启 Config 客户端的情况下获取到了最新配置。

这种方式虽然解决了重启 Config 客户端才能获取最新配置的问题,但另一个问题却也接踵而至,那就是只要配置仓库中的配置发生改变,就需要我们挨个向 Config 客户端手动发送 POST 请求,通知它们重新拉取配置。

那么有没有“一次通知,处处生效”的方式呢?答案是肯定的。Spring Cloud Config 配合 Bus 就可以实现配置的动态刷新。


Config+Bus 实现配置的动态刷新

Spring Cloud Bus 又被称为消息总线,它能够通过轻量级的消息代理(例如 RabbitMQ、Kafka 等)将微服务架构中的各个服务连接起来,实现广播状态更改、事件推送等功能,还可以实现微服务之间的通信功能。

目前 Spring Cloud Bus 支持两种消息代理:RabbitMQ 和 Kafka。

Spring Cloud Bus 的基本原理

Spring Cloud Bus 会使用一个轻量级的消息代理来构建一个公共的消息主题 Topic(默认为 springCloudBus),这个 Topic 中的消息会被所有服务实例监听和消费。当其中的一个服务刷新数据时,Spring Cloud Bus 会把信息保存到 Topic 中,这样监听这个 Topic 的服务就收到消息并自动消费。

Spring Cloud Bus 动态刷新配置的原理

利用 Spring Cloud Bus 的特殊机制可以实现很多功能,其中配合 Spring Cloud Config 实现配置的动态刷新就是最典型的应用场景之一。

当 Git 仓库中的配置发生了改变,我们只需要向某一个服务(既可以是 Config 服务端,也可以是 Config 客户端)发送一个 POST 请求,Spring Cloud Bus 就可以通过消息代理通知其他服务重新拉取最新配置,以实现配置的动态刷新。

利用 Spring Cloud Bus 实现配置的动态刷新需要以下步骤:

  1. 当 Git 仓库中的配置发生改变后,运维人员向 Config 服务端发送一个 POST 请求,请求路径为“/actuator/refresh”。
  2. Config 服务端接收到请求后,会将该请求转发给服务总线 Spring Cloud Bus。
  3. Spring Cloud Bus 接到消息后,会通知给所有 Config 客户端。
  4. Config 客户端接收到通知,请求 Config 服务端拉取最新配置。
  5. 所有 Config 客户端都获取到最新的配置。

Nacos

Nacos Server 还可以作为配置中心,对 Spring Cloud 应用的外部配置进行统一地集中化管理。而我们只需要在应用的 POM 文件中引入 spring-cloud-starter-alibaba-nacos-config 即可实现配置的获取与动态刷新。

服务搭建

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

Nacos 同 SpringCloud Config 一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。SpringBoot 中配置文件的加载是存在优先级顺序的,bootstrap 优先级高于 application。

bootstrap.yml

server:
  port: 3377
spring:
  application:
    name: config-nacos-client
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  #注册进Nacos
      config:
        server-addr: 127.0.0.1:8848  #Nacos作为配置中心
        file-extension: yaml  #指定yaml格式的配置

application.yml

spring:
  profiles:
    active: dev  #指定环境

controller

@RestController
@RequestMapping("/config")
@RefreshScope //支持Nacos动态刷新
public class ConfigNacosController {

    @Value("${config.info}")
    private String configInfo;

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

在 Nacos Spring Cloud 中,dataId 的完整格式如下:

${prefix}-${spring.profiles.active}.${file-extension}
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
  • spring.profiles.active 即为当前环境对应的 profile。 注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 propertiesyaml 类型。

最后公式

${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
config-nacos-client-dev.yaml

在这里插入图片描述


在 Nacos 配置列表新建配置文件:

在这里插入图片描述


命名空间分组和 DataID 三者关系

Namespace+Group+Data lD三者关系?为什么这么设计?

类似 Java 里面的 package 名和类名,最外层的 namespace 是可以用于区分部署环境的,Group 和 DatalD 逻辑上区分两个目标对象。

在这里插入图片描述

默认情况:Namespace=public,Group=DEFAULT_GROUP,默认Cluster是DEFAULT

  • Nacos默认的Namespace是public,Namespace主要用来实现隔离。
    • 比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。
  • Group默认是DEFAULT_GROUP,Group可以把不同的微服务划分到同一个分组里面去
  • Service就是微服务:一个Service可以包含多个Cluster (集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。
  • 最后是Instance,就是微服务的实例。
spring:
  application:
    name: config-nacos-client
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  #注册进Nacos
      config:
        server-addr: 127.0.0.1:8848  #Nacos作为配置中心
        file-extension: yaml  #指定yaml格式的配置
        group: DEV_GROUP	#配置分组
        namespace: dc21f277-6490-4bbd-b627-ade2e2f9e837	#配置命名空间
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值