Bus
Table of Contents generated with DocToc (opens new window)
# Bus
前言
在上节的SpringCloud Config中,遇到了必须手动发请求去刷新配置的问题,这里使用消息总线Bus来实现配置的动态刷新全局广播
# 概述
# 是什么
Bus支持两种消息代理:RabbitMQ和Kafka
Spring Cloud Bus 配合Spring Cloud Config 使用可以实现配置的动态刷新
。
Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架, 它整合了Java的事件处理机制和消息中间件的功能。
# 能干嘛
Spring Cloud Bus能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当作微服务间的通信通道
# 为何称为总线
# 什么是总线
在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。
# 基本原理
ConfigClient实例都监听MQ中同一个Exchange交换机(默认名字是springCloudBus)。当一个服务刷新数据的时候,它会把这个信息放入到Topic中,这样其它监听同一Topic的服务就能得到通知,然后去更新自身的配置。
# RabbitMQ
参考https://www.zaiolos.top/my-notes/pages/f015b1/
# 动态刷新全局广播
# 按3355新建3366
3366只有controller需要加一些
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${server.port}")
private String serverPort;
@Value("${server.name}")
private String serverName;
@GetMapping("/configInfo")
public String getConfigInfo(){
return "serverPort:"+serverPort+"\t\n\n configInfo:"+serverName;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 设计思想
1、利用消息总线触发一个客户端/bus/refresh,而刷新所有客户端的配置
2、用消息总线触发一个服务端ConfigServer的/bus/refresh端点,而刷新所有客户端的配置
显然图二更合适
原因:
- 打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新的职责
- 破坏了微服务各节点的对等性
- 有一定的局限性。例如,微服务在迁移时,它的网络地址尝尝会发生变化,此时如果想要做到自动刷新。那就回增加更多的修改
# 3344Server端配置
# pom
新增消息总线依赖
<!-- 消息总线-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2
3
4
5
# yaml
新增yaml配置
spring:
# RabbitMQ相关配置
rabbitmq:
host: 106.55.240.216
port: 5672
# 这里要注意 因为使用的是云服务器,guest只能在localhost登录 所以要使用别的用户进行登录认证
username: admin
password: 123456
# 暴露bus刷新配置的端点 必须要有actuator的依赖
management:
endpoints:
web:
exposure:
include: 'bus-refresh'
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3355、3366Client端配置
# pom
同上新增消息总线依赖
# yaml
只需要新增RabbitMQ的相关配置,management的不用动
# 测试
启动3344、3355、3366程序,访问3355、3366获取当前配置,成功
然后git修改config-dev.yaml,server.name的值为 update-66666
然后发送请求到配置中心3344,注意url的正确
curl -X POST "http://localhost:3344/actuator/busrefresh"
执行以后,再去测试3355和3366,发现两个都立刻就刷新了
# 动态刷新定点通知
有些时候,我们只需要部分微服务读取新的配置,部分保持不动,就需要进行定点通知
简单来说,就是指定某一个实例生效,而不是全部
做法
公式:curl -X POST http://localhost:3344/actuator/busrefresh/{destination}
刷新的请求不再发送到具体的服务实例上,而是发给config server通过destination
参数类指定需要更新配置的服务或实例
# 实操
这里以只刷新3355端口的config-client为例,不通知3366
再次将config-dev.yaml文件的server.name修改为
update-8848
运行命令
curl -X POST "http://localhost:3344/actuator/busrefresh/cloud-config-client:3355"
1
结果正如我们期望的
这里要注意,作为{destination}
cloud-config-client:3355
的构成是,spring.application.name:server.port,即服务名称:服务端口号
如果我们不写端口号,就会通知这个服务名下的所有存在服务的端口上的实例