Spring Cloud Bus自动刷新配置
在之前的文章中,我讲述了统一配置中心(服务端和客户端)的基本使用,并且演示了从配置Git仓库到拉取配置的整个流程,请见 《统一配置中心》 这篇博客。在该博客中我们说到了,统一配置中心还有个好处就是动态更新配置文件,而无需手动重启服务,但是并没有演示或者实现。本文将记述如何通过Spring Cloud Bus自动刷新配置,以及自动刷新的原理。
自动刷新配置原理
实现配置的自动刷新是很有必要的,先看看使用Spring Cloud Bus实现配置的自动刷新的原理,如下图:
Spring Cloud Bus提供了批量刷新配置的机制,它使用轻量级的消息代理(例如RabbitMQ、Kafka等)连接分布式系统的节点,这样就可以通过Spring Cloud Bus广播配置的变化或者其他的管理指令。shop服务的所有实例通过消息总线连接到了一起,每个实例都会订阅配置更新事件。当其中一个微服务节点的/bus/refresh端点被请求时,该实例就会向消息总线发送一个配置更新事件,其他实例获得该事件后也会更新配置。
实现配置自动刷新
1、引入相关依赖和配置
1<dependency>
2 <groupId>org.springframework.cloud</groupId>
3 <artifactId>spring-cloud-starter-bus-amqp</artifactId>
4</dependency>
因为Spring Cloud Bus是需要通过消息队列来完成自动刷新配置的功能的,所以需要开启一个消息队列,并且在配置文件中配置一下消息队列,我这里采用的是RabbitMQ:
1spring:
2 application:
3 name: config
4 cloud:
5 config:
6 server:
7 git:
8 uri: https://gitee.com/zouchanglin/config-repo
9 username: zouchanglin
10 password: 00001010101
11 basedir: /root/config
12 rabbitmq:
13 host: 192.168.79.128
14 port: 5672
15 username: guest
16 password: guest
17
18eureka:
19 instance:
20 appname: config
21 client:
22 service-url:
23 defaultZone: http://localhost:8762/eureka
统一配置中心和Client启动后可以看到对应的消息队列:
2、暴露更新接口
1POST http://localhost:8080/actuator/bus-refresh
使用POST方式请求该接口,统一配置中心才知道Git仓库中的配置发生了变化,才会主动去拉取最新的配置,然后把配置更新的消息发送到消息队列,Config Client消费消息从而主动去配置中心拉取最新的配置,才完成了配置自动更新。但是actuator/bus-refresh
这个接口需要暴露出去,Git的WebHook才能访问到这个接口,所以还需要在统一配置中心的配置文件中加入以下内容:
1spring:
2 application:
3 name: config
4 cloud:
5 config:
6 server:
7 git:
8 uri: https://gitee.com/zouchanglin/config-repo
9 username: zouchanglin
10 password: 00101010101
11 basedir: /root/config
12 rabbitmq:
13 host: 192.168.79.128
14 port: 5672
15 username: guest
16 password: guest
17
18# 把actuator/bus-refresh接口暴露出去
19management:
20 endpoints:
21 web:
22 exposure:
23 include: "*"
24
25eureka:
26 instance:
27 appname: config
28 client:
29 service-url:
30 defaultZone: http://localhost:8762/eureka
更新完配置文件后,重启一下统一配置中心。
3、声明配置自动更新范围
shop-dev.yml配置如下,它的env属性是dev
1server:
2 port: 8090
3
4eureka:
5 client:
6 service-url:
7 defaultZone: http://localhost:8762/eureka/
8
9spring:
10 application:
11 name: shop
12 rabbitmq:
13 host: 192.168.79.128
14 port: 5672
15 username: guest
16 password: guest
17env: dev
我们在测试拿到的配置文件的内容的时候,写了这样的Controller,现在需要新加一个@RefreshScope注解,其实就是声明了配置自动更新的生效范围,所以需要加上@RefreshScope注解:
1@RestController
2@RequestMapping("/env")
3@RefreshScope
4public class EnvController {
5
6 @Value("${env}")
7 private String env;
8
9 @GetMapping("print")
10 public String printEnv(){
11 return env;
12 }
13}
但是通常不这样使用,我们往往是把配置集中到一起,然后在配置类上面声明,假设现在Git仓库的shop-dev.yml配置如下:
1server:
2 port: 8090
3
4eureka:
5 client:
6 service-url:
7 defaultZone: http://localhost:8762/eureka/
8
9spring:
10 application:
11 name: shop
12 rabbitmq:
13 host: 192.168.79.128
14 port: 5672
15 username: guest
16 password: guest
17env: dev
18
19boy:
20 name: Tim
21 age: 18
于是在config目录下新建一个JavaBean,叫做Boy,这时对这个Boy加上@RefreshScope:
1package xpu.edu.shop_service.config;
2
3@Data
4@Component
5@ConfigurationProperties(prefix = "boy")
6@RefreshScope
7public class Boy {
8 private String name;
9 private int age;
10}
此时Controller修改为如下:
1@RestController
2@RequestMapping("/env")
3public class EnvController {
4
5 @Autowired
6 private Boy boy;
7
8 @GetMapping("print")
9 public String printEnv(){
10 return "name:" + boy.getName() + " age:" + boy.getAge();
11 }
12}
通过手动访问/actuator/bus-refresh
接口,已经实现了刷新,如下图所示:
现在自动刷新就只差一步了,那就是配置Git的WebHook,只要发生更新或者是其他事件,Git托管平台便会自动访问我们的/actuator/bus-refresh
接口,从而自动刷新配置文件就完成了!