概述

AMQP

RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。

AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。

  • 功能:能够管理和传播分布式系统间的消息,就像一个分布式执行器,可用与广播状态更改、事件推送等,也可以当作微服务间的通信通道

    SpringCloud Bus可以结合SpringCloud Config实现配置的自动更新

SpringCloud Bus消息总线 - 图2

在之前使用SpringCloud Config的时候,更新客户端的配置需要每一个客户端都发送一个请求

上图中,第3步,我们只需要通知其中一台客户端更新,然后这个更新的消息就会通过SpringCloud Bus广播到所有的客户端,然后所有的客户端自动去配置中心拉取配置,以实现自动更新配置的功能

  • 为什么被称为消息总线

    • 在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。
  • 基本原理

    • ConfigClient实例都监听MQ中同一个topic(默认是springCloudBus)。当一个服务刷新数据的时候,它会把这个信息放入到Topic中,这样其它监听同一Topic的服务就能得到通知,然后去更新自身的配置。

RabbitMQ安装

动态刷新全局广播

  1. 为了演示广播效果,需要多个客户端,再创建一个客户端,和之前的SpringCloud Config除了端口号之外一模一样

    SpringCloud Bus消息总线 - 图3

  1. 两种通知思想

    1. 利用消息总线触发一个客户端ConfigClient的/bus/refresh端点,然后刷新所有客户端的配置

      SpringCloud Bus消息总线 - 图4

  1. 利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,然后刷新所有客户端的配置

    SpringCloud Bus消息总线 - 图5

  1. 更推荐触发服务器的方式,理由如下

    • 通知客户端的方式打破了微服务的单一职责原则,它只是提供服务的一方,不应该承担配置刷新的职责
    • 破坏了微服务节点之间的对等性。比如都是同一个微服务模块,有的有通知功能,有的没有通知功能。
  2. 实现触发服务端的全局广播

    1. 服务端添加依赖并且添加Endpoint

      SpringCloud Bus消息总线 - 图6

添加依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  4. </dependency>

修改配置文件

添加rabbitmq配置并且暴露刷新配置的端点

SpringCloud Bus消息总线 - 图7

  1. 客户端修改

    同样添加rabbitmq依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  4. </dependency>

配置RabbitMQ并且对外暴露所有的端点

SpringCloud Bus消息总线 - 图8

  1. 测试

    配置服务器修改配置

SpringCloud Bus消息总线 - 图9

服务端已经更新为最新的值

SpringCloud Bus消息总线 - 图10

由于客户端还未进行通知,所以未更新

SpringCloud Bus消息总线 - 图11

发送请求到服务端的refresh端点http://localhost:3344/actuator/bus-refresh

SpringCloud Bus消息总线 - 图12

查看两个客户端,都已经更新为最新的配置

SpringCloud Bus消息总线 - 图13

查看RabbitMQ的topic就已经有了我们的通知topic

SpringCloud Bus消息总线 - 图14

动态刷新定点通知

  • 指定一个实例生效,其他都不生效

    SpringCloud Bus消息总线 - 图15

  • 测试

    使某个实例生效,其他不生效http://localhost:3344/actuator/bus-refresh/{destination}

比如,让3355生效,3366不生效

SpringCloud Bus消息总线 - 图16

SpringCloud Bus消息总线 - 图17

发送请求,指定3355更新

SpringCloud Bus消息总线 - 图18

结果3355更新了,3366并未更新!至此就实现了定点通知

SpringCloud Bus消息总线 - 图19