欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringCloud(七)SpringCloudConfig 分布式配置中心

程序员文章站 2022-06-21 14:42:17
...


前言

微服务意味着将单体应用中的业务拆分成一个个的自服务,每个服务的粒度相对较小,因此系统中会出现大量的服务,由于每个服务都需要必须的配置中心才能运行,所以一套集中式的动态的配置管理设施是必不可少的。
SpringCloud 提供了ConfigServer来解决这个问题,我们每个微服务自己带着一个application.yml 上百个的配置文件。(╯‵□′)╯︵┻━┻字

一、Spring Cloud Config是什么?

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

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

客户端则是通过指定的配置中心来管理应用资源,以及业务相关的配置内容,并在启动的时候从配置中心加载配置获取配置信息,配置服务器默认采用git来存储配置信息。这样就有助于对环境配置进行版本管理,并且通过git客户端工具来方便的管理和访问配置内容。
SpringCloud(七)SpringCloudConfig 分布式配置中心

三、Config Server 特性

  • 集中管理配置文件
  • 不同环境不同配置,动态化的配置更新,分环境部署比如 dev/test/prod/beta/release
  • 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会像配置中心统一拉去自己的配置信息
  • 当配置发生变动时,服务不需要重启就可以感知到配置的变化并应用新的配置
  • 将配置信息以REST接口的形式暴露

四、使用步骤

1.1 先通过git创建配置中心的仓库

SpringCloud(七)SpringCloudConfig 分布式配置中心
三个配置文件内容

--- dev
server:
  port: 1997
--- prod
server:
  port: 2008
--- test
server:
  port: 2020

只是做简单测试使用的

1.2 创建module 并引入依赖 sgg-config-center3344

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

1.3 配置 yml 文件

server:
  port: 3344
spring:
  application:
    name: sgg-config-center-service
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/gssnb/springcloud-config.git
          username: username # git 的用户名
          password: xxx  # git 的密码
          search-paths: / # 读取文件的跟地址
          default-label: master # 默认使用的分支
eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka
  instance:
    instance-id: sgg-config-center-service-${server.port}

1.4 创建启动类

@SpringBootApplication
@EnableConfigServer
public class ConfigCenter3344App {

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

@EnableConfigServer 注解开启配置中心服务。
启动我们的 7001, 7002, 3344 服务

1.5 HTTP 接口

Config Server 的 EnvironmentController 类提供了读取配置的api接口 。

@RestController
@RequestMapping(
    method = {RequestMethod.GET},
    path = {"${spring.cloud.config.server.prefix:}"}  // 服务前缀  
)
public class EnvironmentController {
    @RequestMapping(
        path = {"/{name}/{profiles:.*[^-].*}"},
        produces = {"application/json"}
    )
  
    @RequestMapping(
        path = {"/{name}/{profiles:.*[^-].*}"},
        produces = {"application/vnd.spring-cloud.config-server.v2+json"}
    )
    
    @RequestMapping(
        path = {"/{name}/{profiles}/{label:.*}"},
        produces = {"application/json"}
    )
    
    @RequestMapping(
        path = {"/{name}/{profiles}/{label:.*}"},
        produces = {"application/vnd.spring-cloud.config-server.v2+json"}
    )
    
    @RequestMapping({"/{name}-{profiles}.properties"})

    @RequestMapping({"/{label}/{name}-{profiles}.properties"})

    @RequestMapping({"{name}-{profiles}.json"})

    @RequestMapping({"/{label}/{name}-{profiles}.json"})

    @RequestMapping({"/{name}-{profiles}.yml", "/{name}-{profiles}.yaml"})
    
    @RequestMapping({"/{label}/{name}-{profiles}.yml", "/{label}/{name}-{profiles}.yaml"})
  

接口有点多。 常用的就那么几个。 其实也就是那么几个参数的排列顺序组合
name : 配置文件的名字。Spring Cloud Config Client 默认约定,使用应用名 spring.application.name 读取对应的配置文件。注意: 这里是客户端, 比如说 spring.application.name=payment-service, 就会去读取 payment-service.yml

profiles: 配置文件的Profile, 一般用于解决环境不同的配置文件, spring.profiles.active 读取对应的 Profile 配置文件
比如说 在spring.profile.active 为 dev 的时候,会从配置中心读取 payment-service-dev.yml, 不带有 -dev的配置文件也会被读取

label 标签, 在使用 Git 作为存储器时候, label 代表的是分支。

1.6 简单测试一下。

SpringCloud(七)SpringCloudConfig 分布式配置中心
通过参数排序组合访问试试
SpringCloud(七)SpringCloudConfig 分布式配置中心
SpringCloud(七)SpringCloudConfig 分布式配置中心
当没有分支的时候
SpringCloud(七)SpringCloudConfig 分布式配置中心
更多的还是自己测试吧。

1.7 创建客户端module sgg-config-client3355

引入依赖

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

配置 yml 文件, 注意: 这边使用已经不是 application.yml 了 , 已经修改为 bootstrap.yml 文件了,原因如下;
application.yml 文件是用户级别的资源配置项
bootstrap.yml 文件是系统级别的。优先级更高

SpringCloud 会创建一个 "Bootstrap Context" 上下文, 作为Spring 应用的 Application Context 的父上下文。 初始化的时候, Bootstrap Context 负责从外部源加载配置属性并解析配置。 这两个上下文 共享一个从外部获取的 Environment

Bootstrap 属性具有更高的优先级, 默认情况下,它们不会被本地覆盖, Bootstrap contextApplication Context 有着不同的约定, 所以新增了一个 bootstrap.yml 文件,保证 Bootstrap ContextApplication Context 配置的分离

要将 Client 模块下的application.yml文件修改为 boostrap.yml 非常关键
因为 bootstrap.yml 是比 application.yml 先加载的。 boostrap.yml 优先级高于 application.yml

创建 bootstrap.yml 文件
SpringCloud(七)SpringCloudConfig 分布式配置中心

spring:
  application:
    name: payment-service  # 配置 {name} git 中的文件名
  cloud:
    config:
      uri: http://localhost:3344  # 配置config配置中心
      label: master	# 配置 master 分支下
      profile: dev	# 配置 **得 profiles

我们去我们的配置中心的远程仓库添加一个配置。 根据上面我们的规则, 也大概知道我们需要配置的配置的名字是在主分支下的 payment-service-dev.yml
SpringCloud(七)SpringCloudConfig 分布式配置中心
配置我们的 payment-service-dev.yml

server:
  port: 3355
eureka:
  instance:
    instance-id: payment-service-${server.port}
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka
payment:
  version: 1.0

配置好之后, 为了证明我们确实是 读取到了我们的文件 , 我们创建一个接口。 把读取到的配置通过 REST 接口暴露出来

创建ConfigController.java

@RestController
@Slf4j
@RequestMapping(value = "/config")
public class ConfigController {

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

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

    @Value("${eureka.instance.instance-id}")
    private String instanceId;

    @Value("${eureka.client.service-url.defaultZone}")
    private String defaultZone;
    
    @GetMapping(value = "/getConfigInfo")
    public String getConfigInfo(){
        JSONObject configInfo = new JSONObject();
        configInfo.put("port", port);
        configInfo.put("instanceId", instanceId);
        configInfo.put("defaultZone", defaultZone);
        return configInfo.toString();
    }
}

启动我们的 7001, 7002, 3344, 3355, 服务
3355 客户端控制
SpringCloud(七)SpringCloudConfig 分布式配置中心
也可以看到我们的启动时控制台打印出了去哪里读取 config 文件

尝试访问接口
http://localhost:3355/config/getConfigInfo

SpringCloud(七)SpringCloudConfig 分布式配置中心

虽然启动没有问题了,但是这样另一个问题出现了。 就是如果修改了配置文件,我们的 3344 服务虽然可以获取到最新的配置, 3355 客户端服务就无法获取到最新配置。 测试一下

修改 payment-service-dev.yml

payment:
  version: 2.0

我们修改 payment.version = 2.0 , 访问我们的 3344 服务 http://localhost:3344/master/payment-service-dev.yml
SpringCloud(七)SpringCloudConfig 分布式配置中心
可以看到我们的 3344 是可以获取到最新的配置文件的, 但是我们的 3355 就不行了。
依旧还是
SpringCloud(七)SpringCloudConfig 分布式配置中心

1.8 Config 动态刷新 <手动>

引入依赖

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

暴露配置监控端点

management:
  endpoints:
    web:
      exposure:
        include: '*'  # 配置暴露出所有的 

在我们的 Controller 上 配置 @RefreshScope

重启我们的 3355 服务 ,未修改前
SpringCloud(七)SpringCloudConfig 分布式配置中心
现在将我们的 version 修改为 3.0 ,查看 3344 配置中心
SpringCloud(七)SpringCloudConfig 分布式配置中心
更新到 3.0 。 我们的 3355 服务,获取到的 version 还是 2.0 , 这个时候, 就需要我们通过 post 请求去 刷新我们的配置。
打开 cmd 命令行, 通过curl 命令访问 refresh 接口
SpringCloud(七)SpringCloudConfig 分布式配置中心
可以看到请求成功之后,我们在去看我们的配置接口
SpringCloud(七)SpringCloudConfig 分布式配置中心

感谢B站尚硅谷 哈哈

参考 芋道源码
SpringCloud(七)SpringCloudConfig 分布式配置中心