分布式系统基础-消息队列之RabbitMQ

1、RabbitMQ概述

RabbitMQ是挑战Java/JMS消息中间件的产物,也是第二代消息中间件,它是实现了AMQP消息模型的重要产品,所以我们需要先了解一下AMQP模型相关的内容。AMQP模型如下图所示,每个Exchange (信箱/交换机)绑定(Binding)了0到N个Queue(队列),当收到Publisher发布的Message后,Exchange会根据自身的类型结合路由规则来确定此消息要路由到哪个Queue上并被该队列上的Consumer消费。

这里写图片描述

我们看到AMQP模型其实借鉴了传统的IP网络模型,Exchange就是集交换机与路由器功能于一身的三层交换机,而Bindings其实就是路由或交换规则,Queue就是交换机上的一个转发端口。此外,与 JMS模型一样,AMQP消息中间件既可以将消息分发到订阅了某些Queue的Consumer上,也可以让Consumer自己根据需要主动从Queue中拉取消息。

AMQP定义了Message(消息)的格式,每个Message都包括如下基本属性。

  1. Content type与Content encoding:消息内容的类型和编码,类似于HTTP中相应的Header的含义。
  2. Routing key:也经常被称为roxiting_key属性,即用于消息路由的重要属性,其完整属性名为x-amqp-0-10.routing-key,是一个字符串的属性。
  3. Delivery mode:消息投递模式,持久化消息或者临时消息,类似于JMS中的定义。
  4. Message priority:消息优先级。
  5. Producer application id、 Message publishing timestamp与Expiration period:其 Producer产生的id、产生时间及过期时间。

Binding是将Exchange与Queue捆绑的一个专有术语,每个Queue可以设定一个binding_key属性,比如 Queue A 的binding_key=email 表明 Queue A 接收拥有“routing_key=email”的Message,当Exchange收到这样的Message后,就会将其路由到Queue A,但具体情况还需要结合Exchange的类型来区别对待。Exchange 的类型有 4 种 Direct Exchange、Topic Exchange、Fanout Exchange及 Header Exchange,接下来我们一一介绍。

首先是Direct Exchange的路由模式,在这种模式下,它会把Message路由到那些binding key与 routing key 完全匹配的Queue中去,如下图所示。

这里写图片描述

3个消息会路由到binding key 分别为Cucumber、Banana及 Blueberry的Queue中,如果我们以其他routing key发送消息,则消息不会路由到这3个Queue中,变成了 Dead Message。如果用Message里的其他属性来代替routing key进行路由,就属于Header Exchange路由模式了,但实际应用过程中这种类型的Exchange很少被使用到。

其次是Topic Exchange路由模式,这种模式主要用来实现消息广播,此时Queue的 binding key可以使用通配符*与#,如下所示。

这里写图片描述

binding key=log.表示匹配routing key是以log开头的字符串的所有 Message, 同样的binding key=.critical 的 Queue 匹配了 binding key=log.critical 与binding key=alert.critical 这两个 Message,于是我们看到在 Topic Exchange 模式下binding key为 log.critical的 Message被广播到了两个Queue上。

接下来是Fanout Exchange路由模式,它是标准的消息广播模式,会把消息发送给绑定到 Exchange上的全部Queue。如下所示是Fanout Exchange的路由示意图。

这里写图片描述

我们看到每个Message (不同颜色区分)都被广播到全部的3个Queue上。

接下来 ,我们说说 AMQP 0-9-1规范中提出的Virtual Hosts (对应RabbitMQ的vHost) 概念,每个Virtual Hosts里都可以部署一套完全独立的MQ(Exchange+Queue)用于收发消息,而不同的 Virtual Host之间是完全隔离的 。这个概念与 Apache Server里的虚拟主机(virtual hosts)或者Nginx里的server blocks类似,更确切地说,它是一个Namespace (命名空间)的概念,是为了解决多租户(Multi-tenent)的需求而诞生的,每个租户有一个Virtual Host,不同租户之间的M essage彻底隔离。如下所示是A、B、C 三个租户分别使用3个Virtual Host的示意图。

这里写图片描述

2012年10月发布的AMQP 1.0规范于2014年被批准为ISO标准(ISO/IEC 19464)。然而,AMQP 1.0却和之前的版本“完全不同”(completely different),1.0版本规范改变了 AMQP的模型:移除了 Exchange和 Binding的概念,代之以Queue和 Link,此外 AMQP 1.0定义的MQ不再是传统的Client/Server模式,而是采用了 P2P (peer-to-peer) 的对等网格模式。如下所不是 AMQP1.0的概念及组件结构示意图 UML类图)。

这里写图片描述

AMQP 1.0将 Node (节点)作为交流的对等实体,常见的节点类型有Producer、Consumer、Queue及 Service, —个或多个Node被聚合到Container中,一个Container就是OS上运行的一个进程。Container有两种类型:一种是客户应用(Client Application),另一种是Broker。Node之间通过Link(单向链路)传递Message,而真实的数据传输实际在Connection对象上,Message也被划分为 Frame帧进行传输,这个过程中还有Session对象(包含多个Link)存在 。Connection/Session/Link的设计一方面为了精确描述AMQP概念与模型,另一方面实际上给出 了编程的参考实现。

2、RabbitMQ的特点及集群实现

RabbitMQ对于Queue中的Message有两种保存方式:Disk和 Ram。如果采用Disk则需要把 Exchange、Queue、Delivery mode 都设置成 durable 模式。 Disk 方式的好处是当 RabbitMQ 节点失效时 Message仍然可以在重启之后恢复。当使用Ram方式时RabbitMQ能够承载的访问量则取决于可用的内存数了,当内存不足时也有参数来实现消息限流及控制内存消息交换到磁盘中保存的保障机制。正常情况下 Ram模式处理Message的效率要高出Disk模式很多倍,所以在有其他HA手段保障的情况下选用Ram方式可以在很大程度上提高消息队列的工作效率并加快处理速度。如果RabbitMQ组成集群,则至少要保证有一个节点是Disk模式,否则所有节点宕机后RabbitMQ集群的所有元数据(metdata)信息都丢失不见而且无法恢复了。

由于RabbitMQ基于Erlang编写,所以天然支持Clustering,以集群方式部署RabbitMQ是保证系统可靠性的重要手段之一,同时可以通过水平扩展达到增加消息吞吐量的目的。RabbitMQ可以通过三种方法来部署分布式集群系统,分别是cluster、federation及 shovel。下面我们分别说说这几种集群模式的特点。

RabbitMQ cluster是最常用的集群方式,工作于局域网里,不支持跨网段的机器,运行期可以随意增加或者减少集群节点,一个集群里各个节点的RabbitMQ与Erlang版本需要保持一致。如下图所示的RabbitMQ cluster是3个RabbitMQ节点组成的集群,从逻辑上讲,这个集群时单一的Message Broker,Client可以连接集群中的任一节点收发消息。如果配合负载均衡器(硬件或者HAProxy),则Client只需访问单一地址,由负载均衡器负责load balance,将访问请求分发给各个RabbitMQ节点。

这里写图片描述

RabbitMQ Cluster集群模式又可以细分为两种:普通模式和镜像模式。

  1. 普通模式下,Message只存在于其中一个Node的Queue中(Queue的Owner Node), 但 Consumer可以在任意Node上获取这个Message,如果Consumer是通过其他Node而非Owner Node去访问这个Message的,则Message从Owner Node复制到该Node上再发送给Consumer。为了避免这种低效行为,建议Client连接所有Node。
  2. 镜像模式其实是RabbitMQ HA 高可用性的一种方案,在这种模式下,Message会主动在镜像Node之间进行同步复制,缺点就是集群内部的同步通信会占用大量的网络带宽。镜像模式下,可以配置ha-mode参数为下面几个选项。

(1)只复制N个副本。
(2)集群中的所有节点都复制。
(3)仅仅在某几个指定的节点上复制。

RabbitMQ fedemtion与shovel模式则适用于广域网这种网络性能比较差的环境,两者都是通过 RabbitMQ Plugin插件的方式实现的。RabbitMQ federation插件可以在多个Broker或者 Cluster之间通过AMQP协议传输Message。连接的双方可以使用不同的user和virtual host,甚至双方的RabbitMQ和 Erlang版本也不一致,RabbitMQ federation提供的功能也很灵活。

RabbitMQ shovel相对更为简单,在本质上shovel可以类比为一个“水泵”,负责把某个源Broker上收到的Message重新发送到目标Broker上。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RonTech

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值