分布式配置中心

摘要:是一种集中、统一管理各种应用配置的基础服务组件。


目录

[TOC]

分布式配置中心

配置中心:是一种集中、统一管理各种应用配置的基础服务组件,从而解决因为数量和环境导致的配置信息不一致问题。

  • 在分布式服务架构中,当系统从一个单体应用,被拆分成分布式系统上一个个服务节点后,配置文件也必须跟着迁移 (分割),这样配置就分散了,不仅如此,分散中还包含着冗余。

  • 而配置中心将配置从各应用中剥离出来,对配置进行统一管理,应用自身不需要自己去管理配置。

img

配置加载顺序

若 application.yml 和 bootStrap.yml 在同目录下,则bootStrap.yml 会优先被加载。

原理:bootstrap.yml 于应程序上下的引导阶段,由Spring ApplicationContext加载。

  • bootstrap.yml:可以理解成系统级别的参数配置,这些参数一般是不会变动的。在Spring ApplicationContext 应用上下文初始化之前加载,用于配置那些需要在这之前就被设置好的属性。
    • 如配置中心连接配置信息,如果搭配 spring-cloud-config 使用可以实现动态替换。
  • application.yml:用来定义 Spring Boot 应用级别的主要配置文件,包含了应用运行时大部分的配置信息,如数据库连接、服务端口等。

常见的实现工具

比较典型的配置中心实现工具有:

  • 推荐:Apollo(阿波罗)、Nacos、Spring Cloud Config
  • ETCD、Consul、ZooKeeper
  • 百度开源的 Disconf、阿里巴巴提供的 Diamond。

Spring Cloud Config 配置管理

Spring Cloud Config:用来为分布式系统中的(基础设施和微服务应用)提供集中化外部配置支持,可以集中存储所有应用的配置文件。分为服务端和客户端两部分:

  • 服务端(Config Server)也称为分布式配置中心,是一个独立的微服务应用,可以从配置仓库获取配置信息并提供给客户端使用,加密/解密信息等访问接口。对应的组件是:spring-cloud-config-server
  • 客户端则是微服务架构中的各个微服务应用或基础设施,通过指定的配置中心管理(应用资源与业务相关的)配置内容,并在启动时从配置中心获取和加载配置信息。对应的组件是:spring-cloud-starter-client
  • Spring Cloud Config 的配置中心默认采用Git来存储配置信息,所以天然就支持配置信息的版本管理,并且可以使用Git客户端来方便地管理和访问配置信息。通常使用不同格式来区分不同应用的不同配置文件。
  • 支持安全认证
  • 云计算环境下,习惯上使用YAML配置,而且一般配置文件的位置都放在类路径下的config目录下,配置文件规则:应用名+profile.yml。
1
2
3
4
5
/{application}/{profile}[/{label}]  
/{application}-{profile}.yml  
/{label}/{application}-{profile}.yml  
/{application}-{profile}.properties  
/{label}/{application}-{profile}.properties  

Spring Cloud提供了注解@EnableConfigServer来启动配置服务。

img

在Git仓库中准备配置信息

Spring Cloud Config 需要一个存储配置信息的Git仓库。

配置仓库的目录结构:

创建 config-server 模块

在pom.xml中添加相关依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
<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>
<-- 通过整合 Spring Security 来为配置中心添加安全认证 !-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
在application.yml中进行配置

config-server 自己本身作为一个应用的配置,因此不用 bootstrap.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server:
  port: 8901 #默认8888
spring:
  application:
    name: config-server
  cloud:
    config:
      server: #Config服务端配置
        git: #配置存储配置信息的Git仓库,集群?
          uri: https://gitee.com/macrozheng/springcloud-config.git
          username: macro
          password: 123456
          clone-on-start: true #开启启动时直接从git获取配置
   security: #配置中心添加安全认证,配置用户名和密码
    user:
      name: macro
      password: 123456
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8001/eureka/
在启动类上添加@EnableConfigServer注解

来启用 Config Server 功能作为配置中心

1
2
3
4
5
6
7
8
9
10
@EnableConfigServer
@EnableDiscoveryClient
@SpringBootApplication
public class ConfigServerApplication {

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

}
通过config-server获取配置信息

这里通过config-server来演示下如何获取配置信息。

获取配置文件信息的访问格式
1
2
3
4
# 获取配置信息
/{label}/{application}-{profile}
# 获取配置文件信息
/{label}/{application}-{profile}.yml
占位符相关解释
  • application:代表应用名称,默认为配置文件中的spring.application.name,如果配置了spring.cloud.config.name,则为该名称;
  • label:代表分支名称,对应配置文件中的spring.cloud.config.label;
  • profile:代表环境名称,对应配置文件中的spring.cloud.config.profile。
获取配置信息演示

config-sever集群搭建

在微服务架构中,所有服务都从配置中心获取配置,配置中心一旦宕机,会发生很严重的问题,下面我们搭建一个双节点的配置中心集群来解决该问题。

  • 首先启动两个config-server分别运行在8902和8903端口上;

创建 config-client 模块(微服务客户端)

创建一个config-client模块来从config-server获取配置。

在pom.xml中添加相关依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</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-starter-web</artifactId>
</dependency>
<-- Actuator依赖,用于刷新 !-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在bootstrap.yml中进行配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server:
  port: 9001
spring:
  application:
    name: config-client #mall-order
  cloud:
    config: #Config客户端配置
      profile: dev #启用配置后缀名称
      label: dev #分支名称
      #uri: http://localhost:8901 #配置中心地址
      name: config #配置文件名称
      username: macro #配置中心的用户名和密码
      password: 123456
      discovery: #添加了从注册中心的(配置中心集群)获取配置中心地址,
        enabled: true
        service-id: config-server
        
management:
  endpoints:
    web:
      exposure:
        include: 'refresh' #开启refresh端点,用于刷新
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8001/eureka/
添加 bootstrap-cluster.yml 配置文件

可集成在 bootstrap.yaml 中

  • 主要是添加了从注册中心获取配置中心地址的配置,并去除了配置中心uri的配置:

  • 以bootstrap-cluster.yml启动config-client服务,注册中心显示信息如下:

添加ConfigClientController类用于获取配置
1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RefreshScope //用于刷新配置
public class ConfigClientController {

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

    @GetMapping("/configInfo")
    public String getConfigInfo() {
        return configInfo;
    }
}
演示从配置中心获取配置
1
config info for dev(dev)
获取子目录下的配置

我们不仅可以把每个项目的配置放在不同的Git仓库存储,也可以在一个Git仓库中存储多个项目的配置,此时就会用到在子目录中搜索配置信息的配置。

  • 首先我们需要在config-server中添加相关配置,用于搜索子目录中的配置,这里我们用到了application占位符,表示对于不同的应用,我们从对应应用名称的子目录中搜索配置,比如config子目录中的配置对应config应用;
1
2
3
4
5
6
spring:
  cloud:
    config:
      server:
        git: 
          search-paths: '{application}'
1
config info for config dir dev(dev)
刷新配置

当Git仓库中的配置信息更改后,可以通过SpringBoot Actuator的refresh端点来刷新客户端配置信息。

  • 重新启动config-client后,调用refresh端点进行配置刷新:

Spring Cloud Bus:消息总线

Spring Cloud Bus 使用轻量级的消息代理来连接微服务架构中的各个服务,可以将其用于广播状态更改(例如配置中心配置更改)或其他管理指令,本文将对其用法进行详细介绍。

Spring Cloud Bus 简介

通常会使用消息代理来构建一个主题,然后把微服务架构中的所有服务都连接到这个主题上去,当向该主题发送消息时,所有订阅该主题的服务都会收到消息并进行消费。

  • 使用 Spring Cloud Bus 可以方便地构建起这套机制,所以 Spring Cloud Bus 又被称为消息总线。
  • Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。
  • 目前 Spring Cloud Bus 支持两种消息代理:RabbitMQ 和 Kafka,下面以 RabbitMQ 为例来演示下使用Spring Cloud Bus 动态刷新配置的功能。

RabbitMQ的安装

见安装

动态刷新配置

使用 Spring Cloud Bus 动态刷新配置需要配合 Spring Cloud Config 一起使用,使用上一节中的config-server、config-client模块来演示下该功能。

给config-server添加消息总线支持
  • 在pom.xml中添加相关依赖:
1
2
3
4
5
6
7
8
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • 添加配置文件application-amqp.yml,主要是添加了RabbitMQ的配置及暴露了刷新配置的Actuator端点;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
server:
  port: 8904
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/macrozheng/springcloud-config.git
          username: macro
          password: 123456
          clone-on-start: true # 开启启动时直接从git获取配置
  rabbitmq: #rabbitmq相关配置
    host: localhost
    port: 5672
    username: guest
    password: guest
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8001/eureka/
management:
  endpoints: #暴露bus刷新配置的端点
    web:
      exposure:
        include: 'bus-refresh'
给config-client添加消息总线支持
  • 在pom.xml中添加相关依赖:
1
2
3
4
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
  • 添加配置文件bootstrap-amqp1.yml及bootstrap-amqp2.yml用于启动两个不同的config-client,两个配置文件只有端口号不同;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
server:
  port: 9004
spring:
  application:
    name: config-client
  cloud:
    config:
      profile: dev #启用环境名称
      label: dev #分支名称
      name: config #配置文件名称
      discovery:
        enabled: true
        service-id: config-server
  rabbitmq: #rabbitmq相关配置
    host: localhost
    port: 5672
    username: guest
    password: guest
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8001/eureka/
management:
  endpoints:
    web:
      exposure:
        include: 'refresh'
动态刷新配置演示
  • 我们先启动相关服务,启动eureka-server,以application-amqp.yml为配置启动config-server,以bootstrap-amqp1.yml为配置启动config-client,以bootstrap-amqp2.yml为配置再启动一个config-client,启动后注册中心显示如下:

  • 启动所有服务后,我们登录RabbitMQ的控制台可以发现Spring Cloud Bus 创建了一个叫springCloudBus的交换机及三个以 springCloudBus.anonymous开头的队列:

  • 我们先修改Git仓库中dev分支下的config-dev.yml配置文件:
1
2
3
4
5
6
# 修改前信息
config:
  info: "config info for dev(dev)"
# 修改后信息
config:
  info: "update config info for dev(dev)"  

1
update config info for dev(dev)

配合WebHooks使用

WebHooks相当于是一个钩子函数,我们可以配置当向Git仓库push代码时触发这个钩子函数,这里以Gitee为例来介绍下其使用方式,这里当我们向配置仓库push代码时就会自动刷新服务配置了。

Nacos 作为配置中心

见 Nacos

Consul 作为配置中心

见 Consul

0%