Spring Cloud Config配置详解

Spring Cloud Config.png

在前文服务注册Eureka原理及集群配置中,我们配置Eureka集群时,可以通过--spring.profiles.active=peer1来指定微服务在启动时使用哪段配置。但往往在微服务架构中,需要维护大量的配置文件,在开发、测试、生产环境,这些配置文件又有所不同,同时还希望能做到修改配置文件时,微服务能够不停止服务。

也就是说在微服务架构中,对于配置文件,通常有如下的需求

  • 配置文件集中管理
  • 不同环境不同配置
  • 运行期间可动态调整配置

而Spring Cloud Config正是解决这问题的组件。

本文讲从基本配置步骤,动态刷新配置,以及Spring cloud config高可用三个三面讲解如何配置Spring cloud config.

配置步骤

如上图所示,用户将配置文件push到git仓库,配置文件按照{application}-{profile}.yml或者{application}-{profile}.properties格式命名。spring cloud config server连接git仓库,为所有config client(具体的微服务应用)提供配置服务。

config client 在配置文件中指向配置中心的地址。

准备配置文件
创建一个 spring-cloud-config文件夹,文件夹下创建子文件夹config,在子文件夹下创建以下四个文件,并上传本地gitlab仓库中http://gitlab.bill.com/billjiang/spring-cloud-config

  • hello.yml
  • hello-dev.yml
  • hello-test.yml
  • hello-production.yml

创建config server

分别对应默认、开发阶段、测试阶段、生成环境的配置文件,并在里面写入相应的内容,比如依次写入profile:defualt-1.0profile:dev-1.0profile:test-1.0profile:production-1.0内容,以便后续测试。

下面configserver项目为例,演示spring cloud config的配置,本文示例代码参考springcloud-demo下的configserver项目

  • 创建configserver项目,引入如下依赖
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
 </dependency>
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
   </dependency>

上面的pom.xml不仅引入了config-server还引入了security,主要是配置文件的信息比较重要,加上安全认证多个保障。

  • 启动类上加上@EnableConfigServer@EnableDiscoveryClient注解
    这个注解声明是config server,第二个注解是将其注册到注册中心,方便管理和横向扩展为集群。
  • 在配置文件中,加上如下配置
spring:
  cloud:
    config:
      server:
        git:
          uri: http://gitlab.bill.com/billjiang/spring-cloud-config.git
          search-paths: config
          username: billjiang
          password: '{cipher}2c50a112807ec405695dac19c15cc6da280d8d70e9998b82a9f11d202a6fb7b4'
        health:
          repositories:
            a-hello:
              label: master
              name: hello
              profiles: dev
security:
  basic:
    enabled: true
  user:
    name: user
    password: 123456
encrypt:
  key: billjiang

这里对配置文件进行了对称加密,也可以对放入git仓库(我在本地搭建了个gitlab)的敏感信息进行加密,对于密文的生成可以在项目启动后,使用curl http://user:123456@localhost:8090/encrypt -d [明文] 这样可以在控制台生成密文,比如2c50a112807ec405695dac19c15cc6da280d8d70e9998b82a9f11d202a6fb7b4,把生成的密文加上{cipher}前缀即可作为对称加密的信息。其中encrypt.key是对称加密的密钥。

需要注意的是:如果使用Dalston.SR2版本的Spring.cloud 在使用curl http://user:123456@localhost:8090/encrypt -d [明文]会报错,把Spring cloud换成Dalston.SR1就能解决,这是Dalston.SR2的一个bug。

启动项目后,使用http://localhost:8090/hello/dev可返回如下信息,说明config server已经从git仓库中读取了hello-dev.yml的配置信息

启动spring cloud config.png

在浏览器输入http://localhost:8090/hello-dev.yml还可以在界面输入配置文件的具体内容。

创建config client
下面以hello项目改造为例,说下client端如何从config server中获取配置。

  • 添加依赖
     <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
  • 在配置文件bootstrap.yml中添加如下配置
spring:
  application:
    name: hello
  cloud:
    config:
      uri: http://user:123456@localhost:8090/
      profile: dev
      label: master

之所以不在application.yml中配置,spring boot会优先加载bootstrap.yml,不然上下文中无法读取到配置而报错。这里指向了config server的地址,并且说明读取hello-dev.yml的配置,读取的是master分支。

  • 写一个测试的列子

    @Value("${profile}")
    private String profile;

    @GetMapping("/profile")
    public String  profile(){
        return this.profile;
    }
  • 启动hello项目,输入http://localhost:8000/profile即可在界面上看到dev-1.0的输出。说明客户端正常读取了指定的配置文件内容。

配置刷新

要在微服务运行期间动态刷新配置,可以通过调用/refresh实现,但这样只能针对单个服务,而且要手动操作;如果通过消息中间件,可以将刷新事件广播到所有相关的微服务,从而做到自动刷新。

调用/refresh 刷新

  • 引入依赖actuator
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>1.5.6.RELEASE</version>
        </dependency>`
  • 配置文件中增加
endpoints:
  refresh:
    enabled: true
    sensitive: false
  • 修改配置文件hello-dev.yml内容,改为dev-1.0-refresh,提交到gitlab中
  • 执行curl -X POST http://localhost:8000/refresh 或者用webhook提交该请求
  • 浏览器输入http://localhost:8000/profile查看输出,发现内容已经更改为dev-1.0-refresh

使用Spring Cloud Bus自动刷新

借助Spring Cloud Bus,可以将配置变更事件广播到相关微服务,从而使得相关微服务能够自动刷新配置。

那么刷新的事件可以从单个的服务发起,这样可以将配置更新事件广播到同类服务集群,如果N个微服务集群要更新服务,那么也要操作N次。而从config server发起刷新,则所有相关集群自动刷新配置,后一种明显更好。

config-server 配置spring-cloud-bus

  • 引入 spring-cloud-bus
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
  • 配置文件bootstrap.yml新增
endpoints:
  bus:
    enabled: true
    sensitive: false
spring: 
  rabbitmq:
    host: localhost
    port: 5673
    username: guest
    password: guest
  • 启动项目configserver
  • 修改配置文件hello-dev.yml内容为dev-1.0-bus并提交到gitlab
  • 执行curl -X POST http://user:123456@localhost:8090/bus/refresh刷新配置
  • 浏览器输入http://localhost:8000/profile
    发现内容变为dev-1.0-bus,说明自动化刷新已生效。

为了更好地测试上述效果,可以通过java -ar hello.jar --server.port=8001java -jar hello.jar --server.port=8002命令将单个微服务配置成集群,同时配置其他集群。变更多个配置文件后,刷新配置,看看是否都更新了。

大家可以按照以上步骤,在单个服务节点上配置spring cloud bus,看看刷新配置后,集群中其他节点的配置是否同步更新了。

局部刷新

可以通过/bus/refresh?destination=customers:8000,customers:8000是注册在Eureka Server上的微服务ID,即ApplicationContextID.

Spring cloud config高可用

作为微服务架构中一个十分重要的服务节点,spring cloud config要保证高可用,就要避免单点。这里要分两种情况,如果cloud server已经注册到Eureka Server,则仅仅需要多部署几个cloud server形成集群。如果没有注册到Eureka Server,就需要通过负载均衡器,讲请求转发到cloud server集群。

当然,也要保证消息中间件RabbitMQ的高可用。

以上就是Spring Cloud Config的配置。

推荐阅读更多精彩内容