Spring Cloud之-Spring Cloud Config分布式配置中心- 13(个人笔记)

1、概述

微服务架构意味着将会产生越来越多的单体服务,每个业务模块都被拆成了一个微服务模块,每个微服务模块中,都有各自的配置文件,随着模块的增多,配置文件越来越多,因此,需要有一个集中式的、动态配置的管理来解决这个问题。于是Spring Cloud提供了Config类解决这个问题,它为微服务中的模块提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供一个中心化的外部配置

Spring Cloud Config分为服务端客户端两部分。

服务端称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口。

客户端通过指定配置中心来管理应用资源以及与业务相关的配置内容,在启动的时候,从配置中心读取加载配置信息,配置服务器默认采用git来存储配置信息,有助于对环境配置进行版本管理,可以通过git客户端工具方便管理和访问配置内容。

Spring Cloud Confi官方文档

Config的功能:

  • 集中管理配置文件
  • 不同环境可以使用不同的配置,动态配置更新
  • 运行期间,动态调整配置,不再需要在每个服务部署的机器上修改配置文件,服务回向配置中心统一拉取配置信息
  • 当配置发生变化,服务不需要重启即可感知到配置的变化,并应用新的配置
  • 将配置信息以REST接口形式暴露

Spring Cloud之-Spring Cloud Config分布式配置中心- 13(个人笔记)

2、Config服务端配置与测试

在自己账号GitHub或者Gitee上新建一个springcloudconfig2020的仓库,把自己本地的代码push上去,此时本地仓库和远程仓库就建立联系了。
Spring Cloud之-Spring Cloud Config分布式配置中心- 13(个人笔记)
Spring Cloud之-Spring Cloud Config分布式配置中心- 13(个人笔记)

添加cloud-config-center-3344模块,修改pom.xml,添加spring-cloud-config-server服务端依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- 引入父级模块名称 -->
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.king.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <!-- 子模块名称 -->
    <artifactId>cloud-config-center-3344</artifactId>

    <dependencies>
        <!-- 引入spring cloud config服务端依赖 -->
        <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>
        <!-- 引用cloud-api-common公共模块 -->
        <dependency>
            <groupId>com.king.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- 引用父级spring boot的依赖 -->
        <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>
        <!-- 引用父级的lombok依赖 -->
        <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>

</project>

cloud-config-center-3344模块添加application.yml配置文件。

# 配置服务端口号
server:
  port: 3344

# 配置应用信息
spring:
  application:
    name: cloud-config-client # 配置应用名称
  cloud:
    # Config客户端配置
    config:
      server:
        git:
#          uri: https://gitee.com/xxx/springcloudconfig2020.git # Github上的仓库地址
          uri: git@gitee.com:xxx/springcloudconfig2020.git #设置git仓库地址 # Github上的仓库地址
          search-paths: # 搜索目录,即配置文件的目录
            - springcloudconfig2020
      label: master # 分支名称

# 配置eureka
eureka:
  client:
    service-url:
      # 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7001.com:7001/eureka/

cloud-config-center-3344模块添加主启动类,使用注解@EnableConfigServer激活配置中心。

package com.king.springcloud.com.king.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

/**
 * @EnableConfigServer:开启SpringCloudConfig配置
 */
@EnableConfigServer
@SpringBootApplication
public class ConfigCenterMain3344 {
    public static void main(String[] args) {
        SpringApplication.run(ConfigCenterMain3344.class, args);
    }
}

先说一下url地址构造规则,通过官方文档的Quick Start可知,访问路径有如下5种形式:

label:分支(branch)
application:文件名前缀
profile:文件名后缀,环境(dev/test/prod)


/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

启动cloud-eureka-server7001注册中心模块,启动配置中心模块,在控制台可以看到如下内容,来到这个文件夹,可以看到和GitHub/Gitee地址相同的内容,表明配置中心在启动的时候,会把GitHub/Gitee地址的内容拉下来一份,作为缓存,防止每次都从GitHub/Gitee*问速度慢的问题。

2021-10-09 14:13:43.281  INFO 39724 --- [nio-3344-exec-1] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/var/folders/m9/syz58y4n54bbtc03jbdx8qth0000gp/T/config-repo-6117864259229222371/config-dev.yml
2021-10-09 14:22:13.021  INFO 39724 --- [nio-3344-exec-4] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/var/folders/m9/syz58y4n54bbtc03jbdx8qth0000gp/T/config-repo-6117864259229222371/config-test.yml
2021-10-09 14:22:33.164  INFO 39724 --- [nio-3344-exec-5] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/var/folders/m9/syz58y4n54bbtc03jbdx8qth0000gp/T/config-repo-6117864259229222371/config-prod.yml

这时候,我们通过浏览器访问http://localhost:3344/master/config-prod.yml,发现页面上显示出了config-dev.yml的内容。在GitHub/Gitee上,将config-dev.yml的内容做一下简单的改动并提交,无需重启配置中心模块,再次通过浏览器访问http://localhost:3344/master/config-dev.yml,浏览器上展示的内容是我们修改后的,在控制台可以看到类似的info输出,回到本地缓存文件夹,对比config-dev.yml的修改日期和其他配置文件的修改日期,只有config-dev.yml的日期时间是最新的,其他的配置文件还是配置中心启动时候的日期时间。
Spring Cloud之-Spring Cloud Config分布式配置中心- 13(个人笔记)

所以,当我们给配置中心发送一个获取配置文件请求的时候时,配置中心先去看下GitHub/Gitee地址有没有最新的提交记录,如果有,先pull下来,覆盖本地缓存,再响应请求,如果没有,直接把本地缓存的内容作为响应。

3、Config客户端配置与测试

新建cloud-config-client-3355模块,修改pom.xml,添加spring-cloud-starter-config客户端依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- 引入父级模块名称 -->
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.king.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <!-- 子模块名称 -->
    <artifactId>cloud-config-client-3355</artifactId>

    <dependencies>
        <!-- 引入spring cloud config客户端依赖 -->
        <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>
        <!-- 引用cloud-api-common公共模块 -->
        <dependency>
            <groupId>com.king.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- 引用父级spring boot的依赖 -->
        <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>
        <!-- 引用父级的lombok依赖 -->
        <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>

</project>

在创建cloud-config-client-3355模块application.yml配置文件之前,先说一个知识点。

Spring Boot默认是支持*.properties*.yml配置文件的,使用Spring Boot构建Spring Cloud应用的时候,Spring Boot两种上下文环境一个是Bootstrap一个是Application,当application.ymlbootstrap.yml在同一目录下的时候,bootstrap.yml先加载application.yml后加载Bootstrap ContextApplication Context父级上下文。初始化的时候,Bootstrap Context负责从外部配置文件中加载配置文件bootstrap.yml是系统级别的,Application Context负责应用内部加载配置文件application.yml是用户级别的。因为bootstrap.yml的级别高于application.yml,所以,bootstrap.yml的配置不会被application.yml所覆盖。对于一个Spring Boot模块,此时,它的配置文件来源可能有两个,一个是bootstrap.yml,一个是application.yml(当然,也可以没有application.yml,只走bootstrap.yml如果能满足需求也行)。

因为要读取配置中心的配置信息,所以这里使用bootstrap.ymlcloud-config-client-3355模块添加bootstrap.yml

# 配置服务端口号
server:
  port: 3355

# 配置应用信息
spring:
  application:
    name: cloud-config-client # 配置应用名称
  cloud:
    # Config客户端配置
    config:
      label: master # 分支名称
      name: config # 配置文件前缀名称
      profile: dev # 读取后缀名称
      uri: http://localhost:3344 # 上诉3个综合就是master分支上config-dev.yml,读取目标资源路径,这里读取cloud-config-center-3344模块


# 配置eureka
eureka:
  client:
    service-url:
      # 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7001.com:7001/eureka/

cloud-config-client-3355模块添加主启动类。

package com.king.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

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

cloud-config-client-3355模块添加业务类,用于验证客户端是否真的从配置中心拿到配置信息了。

package com.king.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConfigClientController {

    // 因为config仓库以rest形式暴露,所以客户端可以通过config服务端访问到GitHub上对应的文件信息
    @Value("${config.info}")
    private String configInfo;

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

启动cloud-eureka-server7001模块、cloud-config-client-3344模块、cloud-config-client-3355模块,浏览器访问http://localhost:3355/configInfo,可以拿到cloud-config-center-3344模块下config-dev.yml的配置,这里我们读取config.info属性的值。
Spring Cloud之-Spring Cloud Config分布式配置中心- 13(个人笔记)

GitHub/Gitee上直接修改config-dev.yml的内容,直接访问配置中心http://localhost:3344/master/config-dev.yml改动立刻生效,访问http://localhost:3355/configInfo改动并没有更新,重启cloud-config-client-3355模块后,再次访问生效了,可是这并不是最好的方式,因为重启服务代价太大了
Spring Cloud之-Spring Cloud Config分布式配置中心- 13(个人笔记)
Spring Cloud之-Spring Cloud Config分布式配置中心- 13(个人笔记)
重启cloud-config-client-3355模块后:
Spring Cloud之-Spring Cloud Config分布式配置中心- 13(个人笔记)

4、Config客户端之动态刷新

为了避免每次都重启cloud-config-client-3355服务,现在要实现cloud-config-client-3355的动态刷新。修改cloud-config-client-3355pom.xml,添加spring-boot-starter-actuator健康监控依赖。修改 bootstrap.yml,暴露所有监控端点,默认情况下,访问http://localhost:3355/actuator只会暴露部分端点,使用"*"actuator把所有端点都暴露出来。

修改cloud-config-client-3355模块bootstrap.yml文件:

# 配置服务端口号
server:
  port: 3355

# 配置应用信息
spring:
  application:
    name: cloud-config-client # 配置应用名称
  cloud:
    # Config客户端配置
    config:
      label: master # 分支名称
      name: config # 配置文件前缀名称
      profile: dev # 读取后缀名称
      uri: http://localhost:3344 # 上诉3个综合就是master分支上config-dev.yml,读取目标资源路径,这里读取cloud-config-center-3344模块


# 配置eureka
eureka:
  client:
    service-url:
      # 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7001.com:7001/eureka/


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

cloud-config-client-3355模块的业务类( ConfigClientController)上添加@RefreshScope注解(用来实现动态配置、实例热加载)。

package com.king.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 用来实现动态配置、实例热加载
 */
@RefreshScope
@RestController
public class ConfigClientController {

    // 因为config仓库以rest形式暴露,所以客户端可以通过config服务端访问到GitHub上对应的文件信息
    @Value("${config.info}")
    private String configInfo;

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

重启cloud-config-client-3355模块,在GitHub/Gitee上修改config-dev.yml的内容。访问http://localhost:3344/master/config-dev.yml可以看到配置信息随之修改,访问http://localhost:3355/configInfo发现配置信息并没有改变,此时我们还需要一步操作cmd中通过curl发送一个post形式的refresh请求给3355,再次访问http://localhost:3355/configInfo,即可拿到最新的配置信息了,避免了3355服务的重启。

test-MBP:~ test$ curl -X POST "http://localhost:3355/actuator/refresh"


[“config.client.version”,“config.info”]test-MBP:~ test$

其实这种方式还是有缺陷的,如果有非常多的微服务客户端,每一个都去发送请求执行刷新,也是很麻烦的,下面我们引入Spring Cloud Bus消息总线,采用广播的形式,一旦配置中心的配置发生变更,监听配置中心的各个微服务客户端就能收到消息,于是,refresh操作就可以自动完成了。

上一篇:GitLab服务器IP地址修改


下一篇:(十四)、SpringCloud Config分布式配置中心