分布式微服务系统中,几乎所有服务的运行都离不开配置文件的支持,这些配置文件通常由各个服务自行管理,以 properties 或 yml 格式保存在各个微服务的类路径下。这种将配置文件散落在各个服务中的管理方式,存在以下问题:
  • 管理难度大:配置文件散落在各个微服务中,难以管理。
  • 安全性低:配置跟随源代码保存在代码库中,容易造成配置泄漏。
  • 时效性差:微服务中的配置修改后,必须重启服务,否则无法生效。
  • 局限性明显:无法支持动态调整,例如日志开关、功能开关。
这时候配置中心的概念就应运而生。我们可以通过配置中心对配置进行统一管理。也就是我们本章学习的 Spring Cloud Config 简单来说就是,Spring Cloud Config 可以将各个微服务的配置文件集中存储在一个外部的存储仓库或系统(例如 Git 、SVN 等)中,对配置的统一管理,以支持各个微服务的运行。 Spring Cloud Config 包含以下两个部分:
  • Config Server:也被称为分布式配置中心,它是一个独立运行的微服务应用,用来连接配置仓库并为客户端提供获取配置信息、加密信息和解密信息的访问接口。
  • Config Client:指的是微服务架构中的各个微服务,它们通过 Config Server 对配置进行管理,并从 Config Sever 中获取和加载配置信息。
Spring Cloud Config 默认使用 Git 存储配置信息,因此使用 Spirng Cloud Config 构建的配置服务器天然就支持对微服务配置的版本管理。我们可以使用 Git 客户端工具方便地对配置内容进行管理和访问。除了 Git 外,Spring Cloud Config 还提供了对其他存储方式的支持,例如 SVN、本地化文件系统等。 Spring Cloud Config 工作流程如下:
  1. 提交配置文件到远程的 Git 仓库。
  2. Config 服务端(分布式配置中心)负责连接配置仓库 Git,并对 Config 客户端暴露获取配置的接口。
  3. Config 客户端通过 Config 服务端暴露出来的接口,拉取配置仓库中的配置。
  4. Config 客户端获取到配置信息,以支持服务的运行。

画板

搭建Config服务端

  1. 在 Github 上创建一个名为spring-cloud-config的仓库(Repository)并获取该仓库的地址。Github 站点对于国内用户来说不够稳定,很可能存在加载缓慢等问题,因此我们可以在码云上执行该操作

Spring Cloud Config - 图2

  1. 创建config模块 spring-cloud-config-center-8006,添加config所需核心依赖如下
  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  4. </dependency>
  5. <!--配置中心服务器依赖-->
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-config-server</artifactId>
  9. </dependency>
  1. 在类路径(<font style="color:rgb(68, 68, 68);">/resources </font>目录)下,创建一个名为 <font style="color:rgb(68, 68, 68);">application.yml</font> 的配置文件
  1. server:
  2. port: 8006 #端口号
  3. spring:
  4. application:
  5. name: spring-cloud-config-center-8006 #服务名
  6. cloud:
  7. config:
  8. server:
  9. git:
  10. # 可以使用git也可使用码云,github 站点访问较慢,因此这里我们使用gitee,实现道理思路都一样
  11. uri: https://gitee.com/chenhaijia/spring-cloud-config.git
  12. #仓库名
  13. search-paths:
  14. - spring-cloud-config
  15. force-pull: true
  16. # 如果Git仓库为公开仓库,可以不填写用户名和密码,如果是私有仓库需要填写
  17. # username: ******
  18. # password: ******
  19. #分支名
  20. label: master
  21. eureka:
  22. client: #将客户端注册到 eureka 服务列表内
  23. service-url:
  24. defaultZone: http://127.0.0.1:9001/eureka
  1. 主启动类上使用 @EnableConfigServer 注解开启 Spring Cloud Config 配置中心功能
@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class SpringCloudConfigCenter8006Application {

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

}

获取到刚才所创建 Git 仓库的地址并且 Clone 。HTTPS 或者 SSH 的都可以。在本地找好目录(我放在未知和本模块同级,放哪里都OK根据自己喜好),就直接在这个目录下打开 git-bash ,然后进行克隆git@gitee.com:chenhaijia/spring-cloud-config.git

克隆后创建三个配置文件如下:

  • config-dev.yml
config:
  info: spring-cloud-config-center-8006-dev
  branch: master
  name: config-dev.yml
  version: 1.0
  • config-test.yml
config:
  info: spring-cloud-config-center-8006-test
  branch: master
  name: config-test.yml
  version: 2.0
  • config-prod.yml
config:
  info: spring-cloud-config-center-8006-prod
  branch: master
  name: config-prod.yml
  version: 2.0

分别创建三个配置文件(演示使用)创建完毕后,然后通过 git add .git commit -m 'first commit'git push -u origin "master"等命令上传到 Github&Gitee 上

  1. 依次启动Eureka,Config服务端,Config客户端。浏览器访问 http://127.0.0.1:8006/master/config-dev.yml

Spring Cloud Config - 图3

Spring Cloud Config 规定了一套配置文件访问规则,如下表。
访问规则 示例
/{application}/{profile}[/{label}] /config/dev/master
/{application}-{profile}.{suffix} /config-dev.yml
/{label}/{application}-{profile}.{suffix} /master/config-dev.yml
访问规则内各参数说明如下。
  • {application}:应用名称,即配置文件的名称,例如 config-dev。
  • {profile}:环境名,一个项目通常都有开发(dev)版本、测试(test)环境版本、生产(prod)环境版本,配置文件则以 application-{profile}.yml 的形式进行区分,例如 application-dev.yml、application-test.yml、application-prod.yml 等。
  • {label}:Git 分支名,默认是 master 分支,当访问默认分支下的配置文件时,该参数可以省略,即第二种访问方式。
  • {suffix}:配置文件的后缀,例如 config-dev.yml 的后缀为 yml。
通过这套规则,我们在浏览器上就直接对配置文件进行访问。http://127.0.0.1:8006/config-dev.yml Spring Cloud Config - 图4 # 搭建Config客户端 1. 搭建<font style="color:rgb(68, 68, 68);">config</font>客户端模块spring-cloud-config-client-8007,添加核心依赖如下 xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--SpringCloud2020及以后的版本默认不启用 bootstrap 配置,我们需要在pom里面显式地引入:--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> 2. 类路径<font style="color:rgb(68, 68, 68);">/resources</font> 目录下,创建一个名为 <font style="color:rgb(68, 68, 68);">bootstrap.yml</font> 的配置文件
#bootstrap.yml 是系统级别的,加载优先级高于 application.yml ,负责从外部加载配置并解析
server:
  port: 8007

spring:
  application:
    name: spring-cloud-config-client-8007 #服务名
  cloud:
    config:
      label: master #分支名称
      name: config  #配置文件名称,config-dev.yml 中的 config
      profile: dev  #环境名  config-dev.yml 中的 dev
      #这里不要忘记添加 http:// 否则无法读取
      uri: http://127.0.0.1:8006/ #Spring Cloud Config 服务端(配置中心)地址

eureka:
  client: #将客户端注册到 eureka 服务列表内
    service-url:
      defaultZone: http://127.0.0.1:9001/eureka
  1. 创建ConfigClientController通过改类查看配置文件中的内容
//读取配置中心指定配置文件的内容,并展示到页面
@RestController
public class ConfigClientController {

    @Value("${server.port}")
    private String serverPort;

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

    @Value("${config.branch}")
    private String configBranch;

    @Value("${config.name}")
    private String configName;

    @Value("${config.version}")
    private String configVersion;

    @GetMapping(value = "/getConfig")
    public String getConfig() {
        return "port【"+serverPort+"】info【"+ configInfo +"】branch【"+configBranch+"】name【"+configName+"】configVersion【"+configVersion+"】";
    }
}
  1. 修改主启动类,添加@EnableEurekaClient启动Eureka
@SpringBootApplication
@EnableEurekaClient
public class SpringCloudConfigClient8007Application {

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

}
  1. 启动spring-cloud-config-client-8007模块的服务,浏览器访问 http://localhost:8007/getConfig

Spring Cloud Config - 图5

  1. 将配置文件 config-dev.yml 中 version 的值修改为 2.0,配置如下
config:
  info: spring-cloud-config-center-8006-dev
  branch: master
  name: config-dev.yml
  version: 2.0
  1. 重新启动spring-cloud-config-client-8007模块的服务,浏览器访问 http://localhost:8007/getConfig

Spring Cloud Config - 图6

通过该实例,我们可以得到以下 2 点结论,
  • 配置更新后,Spring Cloud Config 服务端(Server)可以直接从 Git 仓库中获取最新的配置。
  • 除非重启 Spring Cloud Config 客户端(Client),否则无法通过 Spring Cloud Config 服务端获取最新的配置信息。

收到刷新配置

为了解决不重启 Config 客户端无法获取最新配置的问题,接下来,我们就对spring-cloud-config-client-8007进行改造,步骤如下
  1. spring-cloud-config-client-8007模块添加以下依赖,引入 Spring Boot actuator 监控模块
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. 配置文件 <font style="color:rgb(68, 68, 68);">bootstrap.yml</font> 中添加以下配置,对外暴露 <font style="color:rgb(68, 68, 68);">Spring Boot actuator</font> 的监控节点
management:
  endpoints:
    web:
      exposure:
        include: "*"   # * 在yaml 文件属于关键字,所以需要加引号
  1. 使用@RefreshScope注解开启配置刷新
@RestController
@RefreshScope //为了让动态(手动)的获取最新的git 配置,在添加 actuator 监控加载 RefreshScope,
//读取配置中心指定配置文件的内容,并展示到页面
public class ConfigClientController {

    @Value("${server.port}")
    private String serverPort;

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

    @Value("${config.branch}")
    private String configBranch;

    @Value("${config.name}")
    private String configName;

    @Value("${config.version}")
    private String configVersion;

    @GetMapping(value = "/getConfig")
    public String getConfig() {
        return "port【"+serverPort+"】info【"+ configInfo +"】branch【"+configBranch+"】name【"+configName+"】configVersion【"+configVersion+"】";
    }
}
  1. 将配置文件 config-dev.yml 中 version 的值修改为 3.0,配置如下
config:
  info: spring-cloud-config-center-8006-dev
  branch: master
  name: config-dev.yml
  version: 3.0

不重启客户端,直接去访问我们会发现,配置好动态刷新后配置依然没有实时刷新。那是应为我们还少一步,往下看。

  1. 开命令行窗口,使用以下命令发送一个 POST 请求刷新spring-cloud-config-client-8007客户端,通知客户端配置文件已经修改,需要重新拉去配置
curl -X POST "http://localhost:8007/actuator/refresh"
  1. 浏览器再次访问如下已经刷新 http://localhost:8007/getConfig

Spring Cloud Config - 图7