分布式配置中心Config

一、基础概述

1、为什么要有分布式配置中心Config?

微服务意味着要将单体应用中的业务拆分成一个个的子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务;

忧郁每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的!

SpringCloud提供了ConfigServer来解决这个问题,我们每个微服务都带着一个application.yml,上百个配置文件的管理,很恐怖o(╥﹏╥)o

20.jpg

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

2、SpringCloud Config的组成?

SpringCloud Config分为服务端和客户端两部分;

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

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

3、SpringCloud Config能干嘛?

  • 集中管理配置文件;

  • 不同环境不同配置、动态化的配置更新,分环境部署比如dev/test/prod/beta/demo/release等;

  • 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务回想配置中心统一拉取自己的配置信息;

  • 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置信息;

  • 将配置信息以Rest接口的形式暴露;


二、Config配置总控中心的搭建(Config Server)

1、首先,我们要创建一个新的git仓库,作为统一配置仓库:springcloud-config

https://github.com/jiguiquan/springcloud-config

新建三个配置文件,分别为:

  • config-dev.yml

  • config-prod.yml

  • config-test.yml

2、新建配置中心模块 cloud-config-center3344

pom.xml:

<?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.jiguiquan.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-center3344</artifactId>

    <dependencies>
        <!--springcloud config server-->
        <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>
        <!--公共服务模块依赖-->
        <dependency>
            <groupId>com.jiguiquan.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--springboot项目web和actuator最好一起走-->
        <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>

        <!--热部署devtools-->
        <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>
        </dependency>
    </dependencies>
</project>

3、配置文件application.yml:

server:
  port: 3344
spring:
  application:
    name: cloud-config-center
  cloud:
    config:
      server:
        git:
          uri: git@github.com:jiguiquan/springcloud-config.git
          search-paths:
            - springcloud-config
      label: master
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka

4、主启动类:ConfigCenterMain3344.java

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

5、修改windows下的host文件,增加映射:

127.0.0.1  eureka7001.com
127.0.0.1  eureka7002.com
127.0.0.1  config3344.com   #增加此项

6、启动服务,测试是否可以从github上获取到配置信息:

启动后,访问一下路径: http://config3344.com:3344/master/config-dev.yml 

21.jpg

成功读取到!

7、几种常用的读取配置文件规则:——官网5种

  • /{lable}/{application}-{profile}.yml: {lable}分支号——上文的配置方式;

  • /{application}-{profile}.yml:省略了{lable}号,默认为master分支;

  • /{application}/{profile}[/{lable}]:这种方式将配置数据读取到后,需要自己去解析读取到的信息;——还是上面的较好

22.jpg


三、Config客户端配置与测试

1、新建模块cloud-config-client3355

pom.xml:

<?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.jiguiquan.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-client3355</artifactId>

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

        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--公共服务模块依赖-->
        <dependency>
            <groupId>com.jiguiquan.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--springboot项目web和actuator最好一起走-->
        <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>

        <!--热部署devtools-->
        <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>
        </dependency>
    </dependencies>
</project>

2、配置文件bootstrap.yml:

为什么是bootstrap.yml,而不再是application.yml,这两者的区别:

  • application.yml:用户级,资源配置项

  • bootstrap.yml:系统级,优先级更高

使用bootstrap.yml,SpringCloud会创建一个“Bootstrap Context”,它是“Application Context”的父级上下文,初始化的时候,“Bootstrap COntext”负责从外部源加载配置属性并解析配置。

这两个上下文共享一个从外部获取的“Environment”;

“Bootstrap”属于高优先级,默认情况下,它们不会被本地配置所覆盖。“Bootstrap Context”和“Application Context”有着不同的约定,所以增加了一个“bootstrap.yml”文件,保证“Bootstrap Context”和“Application Context”配置文件的分离;

要将Client模块下的application.yml文件改为bootstrap.yml,这是很关键的,因为“bootstrap.yml”的优先级更高!

bootstrap.yml:

server:
  port: 3355
spring:
  application:
    name: config-client
  cloud:
    config:
      lable: master
      name: config         #配置文件名称
      profile: dev         #配置文件后缀
      uri: http://localhost:3344     #配置中心地址

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka

3、主启动类 ConfigClientMain3355.java

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

4、写一个简单的业务类ConfigClientController:

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

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

5、启动服务进行测试:访问链接: http://localhost:3355/configInfo 

23.jpg

显然config-client通过config-server成功地读取到了github上面的配置信息;

6、现在我们尝试将github上对应的文件文件进行修改,比如将version修改为2.0:

此时我们访问3344服务: http://localhost:3344/master/config-dev.yml 

24.jpg

显然,配置服务器3344已经感知到了配置文件的变化;

但是当我们访问3355服务时,发现配置信息并没有变化: http://localhost:3355/configInfo

25.jpg

必须要重启3355服务后才可以生效!

那么问题来了:南岛我们每次修改配置信息后,都需要重启服务吗?显然不可以,所以我们要实现服务3355对配置文件的动态刷新!


四、Config客户端配置的动态刷新

1、动态刷新的目的?

避免每一次更新配置文件斗殴要重启客户端微服务!

2、确保服务添加了监控依赖:

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

3、在配置文件bootstrap.yml中,暴露监控端点:

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

4、在业务类ConfigClientController中增加注解 @RefreshScope

5、再次启动3355程序,并在github修改配置文件 version为3.0,观察3344/3355服务的读取结果:

26.jpg

3344服务肯定没有问题,但是3355服务还是没有自动刷新,我们还需要再做最后一件事情;

6、向服务3355发送一次POST请求,刷新一次服务: curl -X POST "http://localhost:3355/actuator/refresh"

刷新请求会返回这样的结果:

27.jpg

此时我们再次访问: http://localhost:3355/configInfo 

28.jpg

这样我们就在没有重启3355微服务的情况下,自动刷新了它的配置文件;

最后,思考:

如果只有一两个服务还好,如果我们有成百个服务呢,南岛每次都要挨个发POST请求进行手动刷新操作吗?

可否通过广播,一次通知,处处生效!——以实现大范围的自动刷新!

这样就引入了我们的 消息总线——BUS!

个人此项目代码地址(持续更新):

https://github.com/jiguiquan/cloud2020

jiguiquan@163.com

文章作者信息...

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>

相关推荐