使用Spring Cloud Bus自动刷新配置

Spring Cloud版本:Hoxton.SR5

1. 简介

上一章已经实现了使用服务配置中心集中管理配置文件,并可/actuator/refresh手动刷新配置而不需重启。但如果所有微服务节点的配置都需要手动刷新,工作量也很大。所以本文将使用Spring Cloud Bus实现配置的自动刷新。

Spring Cloud Bus使用轻量级的消息代理(RabbitMQ、Kafka等)连接分布式系统节点,这样当其中一个节点的状态更改时可以自动广播到其他节点。


/actuator/bus-refresh

从Git拉取配置

获取配置

获取配置

获取配置

接收消息

接收消息

接收消息

发送消息

用户

Config Server

Git Repo

微服务A

微服务B

微服务C

Spring Cloud Bus


2. Spring Cloud Bus

2.1 实现自动刷新

  • 在配置中心scl-config-server和客户端scl-eureka-client-consumer中添加如下spring-cloud-starter-bus-amqp依赖。
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
  • 在两个项目的配置文件application.yml中都添加RabbitMQ相关配置,并在actuator中暴露bus-refresh端点
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
  endpoints:
    web:
      exposure:
        include: bus-refresh
  • 在配置中心scl-config-server中添加WebSecurityConfig配置类,关闭CSRF。否则刷新时无法通过校验
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        super.configure(http);
    }
}
  • 重启两个项目,然后访问http://localhost:8090/consumer/config
  • Spring Cloud Config 配置的动态刷新 springcloud bus配置中心刷新_配置文件

  • 修改配置文件并提交到Git仓库
profile: production-1.1-bus
  • 在Postman中使用Post请求访问http://localhost:8600/actuator/bus-refresh,并选择Basic校验,返回204 No Content,再次访问http://localhost:8090/consumer/config,可以看到配置已刷新
  • Spring Cloud Config 配置的动态刷新 springcloud bus配置中心刷新_Cloud_02


  • Spring Cloud Config 配置的动态刷新 springcloud bus配置中心刷新_java_03

  • 借助Git仓库的WebHooks,就可以实现配置的自动刷新。

2.2 问题

若使用/actuator/bus-refresh端点刷新后,没有通知其他节点;导致只有本节点配置更新,其他节点配置无更新。则可能跟Turbine聚合监控问题一样,都是因为交换器的问题。

  • 检查RabbitMQ的交互器
  • 将两个交换器进行绑定即可

3. 局部刷新

在某些场景下(如灰度发布),若指向刷新部分微服务的配置,可通过/actuator/bus-refresh/{destination}中的destination定位要刷新的应用范围

destination值为{spring.application.name}:{server.port}

  • 将客户端scl-eureka-client-consumer修改一个端口为8091再次启动,此时有两个客户端,端口分别为8090和8090
  • 修改配置文件并提交到Git仓库
profile: production-1.1-bus-update
  • 在Postman中使用Post请求访问http://localhost:8600/actuator/bus-refresh/scl-eureka-client-consumer:8091,并选择Basic校验,返回204 No Content,再次访问http://localhost:8090/consumer/config和http://localhost:8091/consumer/config,可以看到8091对应的配置已更新,但8090的未更新。局部更新成功
  • Spring Cloud Config 配置的动态刷新 springcloud bus配置中心刷新_配置文件_04


  • Spring Cloud Config 配置的动态刷新 springcloud bus配置中心刷新_java_05


  • Spring Cloud Config 配置的动态刷新 springcloud bus配置中心刷新_java_06

4. Spring Cloud Config与Eureka配合使用

前文中是在客户端中指定Config Server地址,这种方式无法利用服务发现组件的优势

  • 在配置中心scl-config-server中添加spring-cloud-starter-netflix-eureka-client依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <exclusions>
        <exclusion>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  • 修改配置中心的配置文件application.yml,将其注册到服务注册中心
eureka:
  client:
    fetch-registry: false
    service-url:
      defaultZone: http://root:123456@test1:8100/eureka-server1/eureka,http://root:123456@test2:8200/eureka-server2/eureka,http://root:123456@test3:8300/eureka-server3/eureka # 服务注册中心地址
  • 修改客户端scl-eureka-client-consumer的配置文件bootstrap.yml内容,并移除application.yml中eureka的配置
spring:
  cloud:
    config:
      profile: prod
      label: master
      username: root
      password: 123456
      discovery:
        enabled: true # 使用服务注册中心中的Config Server,默认false
        service-id: scl-config-server # 指定Config Server在服务注册中心的名称,默认是configserver
eureka: # 因为bootstrap.yml在application.yml之前加载,若将eureka配置放在application.yml里,启动时会从默认的服务注册中心抓取服务信息,导致失败
  client:
    register-with-eureka: true # 是否注册到服务注册中心
    fetch-registry: true # 是否从注册中心抓取信息,若不存在服务调用设置为false即可,反之则设置为true
    registry-fetch-interval-seconds: 5 # 每5秒刷新一下本地缓存
    service-url:
      defaultZone: http://root:123456@test1:8100/eureka-server1/eureka,http://root:123456@test2:8200/eureka-server2/eureka,http://root:123456@test3:8300/eureka-server3/eureka # 服务注册中心地址
  • 重启两个项目,测试发现一切正常。