一、基础概述
1、Bus支持两种消息代理:
-
RabbitMQ:
-
Kafka:
目标:SpringCloud Bus配合SpringCloud Config实现配置的全自动刷新;
SpringCloud Bus消息总线是用来将分布式系统的节点与轻量级消息系统链接起来的框架,它整合了Java的事件处理机制和消息中间件的功能。
2、SpringCloud Bus能管理和传播分布式系统间的消息,他就想一个分布式执行器,可用于广播状态更改、事件推送等,也可以当作微服务间的通讯通道!
3、什么是总线?
在微服务架构系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线;
在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息;
基本原理:
Config Client实例都监听MQ中同一个Topic(默认是SpringCloudBus),当一个服务刷新数据的时候,它会把这个信息放到Topic中,这样其它监听同一Topic的服务就能得到通知,然后去更新自身的配置;
二、Bus之RabbitMQ环境配置
1、下载Erlang,安装:
2、下载安装RabbitMQ:
3、进入RabbitMQ的安装目录下的sbin目录:
4、使用以下命令启动管理功能:
rabbitmq-plugins enable rabbitmq_management
这样,我们的Windows版的RabbitMQ就算是全部全部完成了;此时在我们的开始菜单,也能看到刚刚安装的RabbitMQ了:
5、访问一下地址,看看RabbitMQ是否安装成功: http://localhost:15672
使用默认账号,登录 guest:guest
三、Bus动态刷新全局广播的设计思想和技术选型
1、为了演示广播效果,增加复杂度,我们以3355项目为模板,再制作做一个项目3366,快速创建,过程就不需要再描述了:
2、设计思想:——有两种:
-
1).利用消息总线触发一个客户端/bus/refresh,而刷新所有客户端的配置;——顶部图1
-
2).利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,从而刷新所有客户端的配置;——顶部图2
显然,思想2的架构更加合适,思想1不合适的原因如下:
-
破坏了微服务的职责单一性原则,因为微服务本身是业务模块,它本不应该承担配置刷新的职责;
-
破坏了微服务各节点的对等性;
-
有一定的局限性,例如:在微服务迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改;
四、Bus动态刷新全局广播配置实现
1、在cloud-config-center3344配置中心服务端添加消息总线支持:
pom.xml:
<!--添加消息总线RabbitMQ的支持--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
application.yml:
#rabbitMQ的相关配置 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest #暴露bus总线刷新配置的端点 management: endpoints: web: exposure: include: 'bus-refresh'
2、给cloud-config-client3355和cloud-config-client3366添加消息总线的支持:
pom.xml:
<!--添加消息总线RabbitMQ的支持--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
bootstrap.yml:
#rabbitMQ的相关配置 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest #暴露监控端点 management: endpoints: web: exposure: include: "*"
3、启动项目7001/3344/3355/3366进行测试:
启动后,我们首先访问一下三个链接,记录结果:
现在我们修改github的版本号为version=4.0,不用想服务3344的结果肯定已经改变,但是如果不刷新,3355和3366服务的结果不会改变,这些都是我们之前验证过的:
4、使用POSTMAN向3344发送一次refresh请求: POST “http://3344/actuator/bus-refresh”
刷新成功,此时我们再去访问3344/3355/3366的链接:
至此,我们完成了通过消息总线Bus和RabbitMQ实现了 “一次修改、广播通知、处处生效”的效果!
5、其实我们还可以在RabbitMQ的管理界面-exchange中找到springCloudBus这个Topic;
五、Bus动态刷新的定点通知
在某些场景下,如果我们只想通知众多微服务中的一个,这样的需求又应该怎么处理,这里,就需要用到——定点通知!
指定某一个具体实例生效,而不是全部!
其实很简单,就是一个公式: http://localhost:3344/actuator/bus-refresh/{destination}
/bus/refresh请求不再发送到具体的实例上,而是发给config-server并通过destination参数指定需要更新配置的服务或实例;
1、测试,这次我们的配置刷新,只通知3355服务,而不通知3366服务;
将github上的version修改为5.0;
2、使用POSTMAN向3344服务发起一次定向通知的刷新请求: POST “http://localhost:3344/actuator/bus-refresh/config-client:3355”
刷新成功,此时我们在分别访问3344/3355/3366的链接:
显然,我们的服务3355的配置已经刷新了,但是服务3366的配置并没有刷新,这样我们就实现了 Bus 的定向通知!
到这里,消息总线 Bus 就全部结束了!
个人此项目代码地址(持续更新):