接上一篇文章:Spring Cloud Config 实现分布式配置中心及动态刷新机制配置,针对动态刷新配置存在的问题:
无法真正实现:一处通知、处处生效;无法实现精确通知,只通知集群中的某些服务(精确通知,比如有100台机器,只通知前98台)带着上面这两个问题,我们来聊聊 Spring Cloud Bus 服务总线。
附送直达飞机票:Spring Cloud Bus 官网
在微服务架构的系统中,通常会使用 轻量级的消息代理 来构建一个共用的消息主题,并让系统中所有的微服务示例都连接上来。由于 该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便的广播一些需要让其他连接在该主题上的实例都知道的消息。
Spring Cloud Bus 是用来将 分布式系统的节点与 轻量级消息系统连接起来的框架,它整合了 Java 的事件处理机制和消息中间件的功能。Spring Cloud Bus目前仅支持 RabbitMQ 和 Kafka。
Config 客户端示例,都去监听 MQ 中的同一个 topic(默认是 springCloudBus)。当一个服务刷新数据的时候,它会把这个消息放入到 Topic 中,这样其他监听同一 Topic 的服务就能够得到通知,然后去更新自身的配置。通过 MQ 消息队列的 Topic 机制,达到广播的效果。
执行流程
App A/B/C 是三个客户端,他们都监听同一个Topic(MQ 就是Cloud Bus,Bus目前仅支持RabbitMQ和Kafka)配置信息修改后,通过 Push 方式,提交到GitHub服务端 Config Server 能够实时接收远程 GitHub 数据的改动手动通过Post方式进行 /bus/refresh 刷新操作 (本图是通过客户端方式进行触发)此时App A 会将消息发送给 Cloud Bus (也可以认为是 MQ),然后 App abc 同时接收消息,并做参数配置的修改选用 Spring Cloud Bus 进行 Topic 消息的发送,在技术选型上共有两种设计思想:
利用 消息总线,触发一个客户端 的 /bus/refresh 端点。通过客户端向 Bus 总线发送消息,实现刷新所有客户端的配置。
利用消息总线,触发一个服务端 的 /bus/refresh 端点。通过Config Server 服务端向 Bus 总线发送消息,实现刷新所有客户端的配置。
根据架构图显然 图二 更加合适,所以推荐使用 触发服务端 Config Server 的方式。图一触发客户端方式 不适合的原因如下:
打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新的职责;破坏了微服务各个节点之间的对等性(比如说:3355/3366/3377 集群方式提供服务,此时 3355 还需要消息通知,影响节点的对等性)有一定的局限性,当微服务迁移时,网络地址会经常发生变化,如果此时需要做到自动刷新,则会增加更多的修改。Spring Cloud Bus 目前仅支持 RabbitMQ 和 Kafka。 此处选型 RabbitMQ,Rabbit MQ 需要 Erlang 环境。所以我们先来安装 Erlang 和 Rabbit MQ
Erlang 下载地址:http://erlang.org/download/otp_win64_21.3.exe RabbitMQ 下载地址:https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.14/rabbitmq-server-3.7.14.exe
上面下载的是 Window 版,傻瓜式安装,下一步→ 下一步→完成,OK 搞定以后通过 cmd 命令行进入 Rabbit MQ 安装目录 sbin 下,使用命令:rabbitmq-plugins enable rabbitmq_management 启动 RabbitMQ的同时,添加了 Rabbit 的可视化插件。
Mac可以直接使用 brew 包管理工具进行安装 brew install rabbitmq,没有安装过brew,可以使用以下命令进行安装(如果报错可参考该文章使用脚本安装)
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"但是我们这里使用本地安装不实用brew包管理工具,我的系统是 MacOS Big Sur 11.0 Beta 版本 用brew 包管理工具有问题,暂未支持有点难受…
通过浏览器打开http://localhost:15672/用户名和密码 是 guest/guest
根据上文:Spring Cloud Config 实现分布式配置中心、动态刷新机制配置,根据 product-service 8771 来启动两个客户端 product-service 8772。与 8771 组成集群模式,方便接下来 Bus 定点通知 效果的演示。
如何启动两个,此处不再介绍。(自行百度)可参考下图
在 服务端 配置中心 Config Server (3344)、客户端集群(3355/3366) 中引入 Bus 总线依赖
<!--添加消息总线支持--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>启动:服务端配置中心 Config Server (3344)、客户端集群(8771/8772)、Eureka Server(7001)。修改 GitHub 参数配置,然后向 服务端 发送 Post 请求,命令:
curl -X POST "http://localhost:3344/actuator/bus-refresh",当向 Config Server 发送 Post 请求后,总线上的各个实例(客户端 8771/8772 )都能够及时 监听和消费 配置的变更。使用广播的方式,真正的实现 一处通知,处处生效。测试如图所示:
使用 MQ 广播的方式,实现 一处通知,处处生效 的效果。此时我们登陆 Rabbit MQ 客户端,在 Exchanges 模块,就能够看到一个叫做 springCloudBus 的 Topic。
与本文 2.2 Bus 原理 中介绍吻合:Config 客户端示例,都去监听 MQ 中的同一个 topic(默认是 springCloudBus)。当一个服务刷新数据的时候,它会把这个消息放入到 Topic 中,这样其他监听同一 Topic 的服务就能够得到通知,然后去更新自身的配置。
如果需要 差异化通知,并不想进行全局广播,此时就用到了 Bus 的 定点通知 功能。
此次我们通过客户端集群(8771/8772)演示。GitHub 远程配置修改后 ,进行差异化定点通知,只通知 8771,不通知 8772。此处命令和全局广播有点不同,命令为:http://配置中心IP:配置中心的端口号/actuator/bus-refresh/{destination}
通过指定 /bus/refresh 请求 不再发送到具体的服务实例上,而是发给 Config Server 并通过 {destination} 参数 来指定需要更新配置的服务或实例。
{destination} 参数 = 微服务名 :端口号。8771 微服务名为:product-service。此处最终发送的 Post 请求命令为:
curl -X POST http://localhost:3344/actuator/bus-refresh/product-service:8771真正的实现 精确通知 功能。测试如图所示:
https://blog.csdn.net/lzb348110175/article/details/107403161