Federation是一个RabbitMQ官方插件。
Federation直译过来是联邦,它的设计目标是使 RabbitMQ 在不同的 Broker 节点之间进行消息传递而无须建
立集群。
那么它到底有什么用呢?我们可以从一个实际场景入手:
有两个服务分别部署在国内和海外,它们之间需要通过消息队列来通讯。
很明显无论RabbitMQ部署在海外还是国内,另一方一定得忍受连接上的延迟。因此我们可以在海外和国内各部署一个MQ,这样一来海外连接海外的MQ,国内连接国内,就不会有连接上的延迟了。
但这样还会有问题,假设某生产者将消息存入
海外MQ中的某个队列 queueB , 在国内的服务 想要消费 queueB 的 消息,消息的流转及
确认必然要忍受较大的网络延迟 ,内 部编码逻辑也会因这一 因素变得更加复杂。
此外,服务可能得维护两个MQ的配置,比如国内服务在生产消息时得使用国内MQ,消费消息时得监听海外MQ的队列,降低了系统的维护性。
可能有人想到可以用集群,但是RabbitMQ的集群对延迟非常敏感,建议是部署在局域网内,如果部署在广域网可能会产生网络分区等等问题。
这时候,Federation就派上用场了。它被设计成能够容忍不稳定的网络连接情况,完全能够满足这样的场景。
那使用Federation之后是怎样的业务流程呢?
首先我们在海外MQ上定义exchangeA,它通过路由键“rkA”绑定着queueA。
用Federation在exchangeA上建立一条单向连接到国内RabbitMQ,
Federation则自动会在国内RabbitMQ建立一个exchangeA交换器(默认同名)。
这时候,如果部署在国内的client C在国内MQ上publish了一条消息,这条消息会通过 Federation link 转发到
海外MQ的交换器exchangeA中,最终消息会存入与 exchangeA 绑定的队列 queueA 中,而client C也能立即得到返回。
补充:Federation插件实际上还会在国内MQ建立一个内部的交换器:exchangeA→ broker3 B(broker3是集群名),并通过路由键 "rkA"将它和国内MQ的exchangeA绑定起来。接下来还会在国内MQ上建立一个内部队列federation: exchangeA->broker3 B,并与内部exchange绑定。这些操作都是内部的,对客户端来说是透明的。
值得一提的是,Federation的连接是单向的,如果是在海外MQ的exchangeA上发送消息是不会转到国内的。
这种在exchange上建立连接进行联邦的,就叫做联邦交换器。一个联邦交换器接收上游(upstream)的信息,这里的上游指的是其他的MQ节点。
对比前面举的例子,国内MQ就是上游,联邦交换器能够将原本发送给上游交换器的消息路由到本地的某个队列中。
有联邦交换器自然也有联播队列,联邦队列则允许一个本地消费者接收到来自上游队列的消息 。
如图,海外MQ有队列A,给其设置一条链接,Federation则自动会在国内RabbitMQ建立一个队列A(默认同名)。
当有消费者 ClinetA连接海外MQ并通过
Basic . Consume 消费队列 queueA 中的消息时,如果队列 queueA中
本身有若干消息堆积,那么 ClientA直接消费这些消息,此时海外MQ中的queueA
并不会拉取国内中的 queueA 的消息;
如果队列 queueA中没有消息
堆积或者消息被消费完了,那么它会通过 Federation link 拉取上游队列 queueA 中的消息(如果有消息),然后存储到本地,之后再被消费者 ClientA进行消费 。
Federation可以通过命令行、HTTPAPi、WEB界面的方式去使用,本文采用简单友好WEB方式去操作,若对其余方式有兴趣的可自行搜索。
首先开启Federation 功能
rabbitmq-plugins enable rabbitmq_federation
其次开启Federation的管理插件
rabbitmq-plugins enable rabbitmq_federation_management
值得注意的是,当需要在集群中使用 Federation 功能的时候,集群中所有的节点都应该开启 Federation 插件。
接下来我们要配置两个事物,upstreams和Policies。
每个 upstream 用于定义与其他 Broker 建立连接的信息。
通用参数如下:
定义一个 Policy 用于匹配交换器:
^exchange意思是将匹配所有以exchange名字开头的交换器,为它们在上游创建连接。
这样就创建了一个 Federation link。