RabbitMQ详解

1. 消息中间件

消息中间件是基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统。

1.1 消息中间件应用场景

1.1.1 异步处理

场景:用户注册后,需要发注册邮件和注册短信,传统的做法有两种:1.串行的方式;2.并行的方式。

(1)串行方式:将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端。这有一个问题是,邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西。

8ac099260797495fbab908411227246f.png

(2)并行方式:将注册信息写入数据库后,发送邮件的同时,发送短信,以上三个任务完成后,返回给客户端,并行的方式能提高处理的时间。

7b47dd9981494cefbf202246da512cef.png 

(3)消息队列
引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理。

66c4591cceb742cdaf0a5a4d78b61a89.png

由此可以看出,引入消息队列后,用户的响应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计),引入消息队列后处理后,响应时间是串行的3倍,是并行的2倍。 

1.1.2 应用解耦

场景:双11是购物狂节,用户下单后,订单系统需要通知库存系统,传统的做法就是订单系统调用库存系统的接口。

7793053954dd400888cbd103ffc614b9.png

这种做法有一个缺点:当库存系统出现故障时,订单就会失败。并且订单系统和库存系统高耦合。

引入消息队列:

767739113654481fa61dfbcd419fd49e.png

订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。

库存系统:订阅下单的消息,获取下单消息,进行库操作。

就算库存系统出现故障,消息队列也能保证消息的可靠投递,不会导致消息丢失。

1.1.3 削峰限流

场景:秒杀活动,一般会因为流量过大,导致应用挂掉,为了解决这个问题,一般在应用前端加入消息队列。

397f14d68edd4a4f9fa15461a32af49e.png

用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,则直接抛弃用户请求或跳转到错误页面。

秒杀业务根据消息队列中的请求信息,再做后续处理。

1.2 消息队列优缺点

优点:在特殊场景下有其对应的好处,解耦、异步、削峰。

缺点:

1. 系统可用性降低:系统引入的外部依赖越多,越容易挂掉。

2. 系统复杂度提高:加入MQ 后,怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?

3. 一致性问题:A 系统处理完了直接返回成功了,B系统入库失败,数据一致性问题怎么处理?

2. 常用消息中间件

AMQP,即Advanced Message Queuing Protocol(高级消息队列协议),一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有RabbitMQ等。

JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。

2.1 常见MQ产品

ActiveMQ:基于JMS

RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好

RocketMQ``:基于JMS,阿里巴巴产品,目前交由Apache基金会

Kafka:分布式消息系统,高吞吐量

其实现在主流的消息中间件就4种:kafka、ActiveMQ、RocketMQ、RabbitMQ。

2.1.1 ActiveMQ

一般早些的项目在使用,现在已过时,不多介绍。

2.1.2 RabbitMQ

RabbitMQ出现后,国内大部分公司都从ActiveMQ切换到了RabbitMQ,基本代替了activeMQ的位置。它的社区还是很活跃的。它的单机吞吐量是万级,对于需要支持特别高的并发的情况,它是无法担当重任的。

在高可用上,它使用的是镜像集群模式,可以保证高可用。

在消息可靠性上,它是可以保证数据不丢失的,这也是它的一大优点。同时它也支持一些消息中间件的高级功能,如:消息重试、死信队列等。

但是,它的开发语言是erlang,国内很少有人精通erlang,所以导致无法阅读源码。对于大多数中小型公司,不需要面对技术上挑战的情况,使用它还是比较合适的。而对于一些BAT大型互联网公司,显然它就不合适了。

2.1.3 RocketMQ

它是阿里开源的消息中间件,久经沙场,非常靠谱。支持高吞吐量,能达到10万级,能承受互联网项目高并发的挑战。

在高可用上,它使用的是分布式架构,可以搭建大规模集群,性能很高。

在消息可靠性上,通过配置,可以保证数据的绝对不丢失。同时它支持大量的高级功能,如:延迟消息、事务消息、消息回溯、死信队列等等。

它非常适合应用于java系统架构中,因为它使用java语言开发的,我们可以去阅读源码了解更深的底层原理。目前来看,它没有什么特别的缺点,可以支持高并发下的技术挑战,可以基于它实现分布式事务,大型互联网公司和中小型公司都可以选择使用它来作为消息中间件使用,如果我来做技术选型,我首选的中间件就是它。

2.1.4 Kafka

kafka的吞吐量被公认为中间件中的翘楚,单机可以支持十几万的并发,相当强悍。

在高可用上同样支持分布式集群部署。

在消息可靠性上,如果保证异步的性能,可能会出现消息丢失的情况,因为它保存消息时是先存到磁盘缓冲区的,如果机器出现故障,缓冲区的数据是可能丢失的。

它的功能非常的单一,就是消息的接收与发送,因此不适合应用于许多场景。在行业内主要应用于大数据领域,使用它进行用户行为日志的采集和计算,来实现比如“猜你喜欢”的功能。所以,如果没有大数据的需求,一般不会选择它。

对比图:

f2ede314fae74bef9ab8bdf57ef428f0.png

3. 主流消息中间件介绍—RabbitMQ

RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。

3.1 RabbitMQ的集群架构

2ac4ee85ea434097a829349f820da4ae.png

mirror镜像队列,目的是为了保证 rabbitMQ数据的高可靠性解决方案,主要就是实现数据的同步,一般来讲是2 - 3个节点实现数据同步。对于100%数据可靠性解决方案,一般是采用 3个节点。

如上图所示,采用 mirror镜像模式,用 KeepAlived 做了 HA-Proxy 的高可用,然后有3 个节点的 MQ 服务,消息发送到主节点上,主节点通过 mirror队列把数据同步到其他的MQ节点,这样来实现其高可靠。

这就是RabbitMQ整个镜像模式的集群架构。

3.2 RabbitMQ的工作原理介绍

首先先介绍一个简单的一个消息推送到接收的流程,提供一个简单的图:

221ee317b2ac4f29921e723331e7a666.png

RabbitMQ的基本结构:

b1ea66454cee41b39f7e169be8a410b8.png

组成部分说明:
1.Channel(信道):多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚拟连接,复用TCP连接的通道。

2.Producer(消息的生产者):向消息队列发布消息的客户端应用程序。

3.Consumer(消息的消费者):从消息队列取得消息的客户端应用程序。

4.Message(消息):消息由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(消息优先权)、delivery-mode(是否持久性存储)等。

5.Routing Key(路由键):消息头的一个属性,用于标记消息的路由规则,决定了交换机的转发路径。最大长度255 字节。

6.Queue(消息队列):存储消息的一种数据结构,用来保存消息,直到消息发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将消息取走。需要注意,当多个消费者订阅同一个Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理,每一条消息只能被一个订阅者接收。

7.Exchange(交换器|路由器):提供Producer到Queue之间的匹配,接收生产者发送的消息并将这些消息按照路由规则转发到消息队列。交换器用于转发消息,它不会存储消息 ,如果没有 Queue绑定到 Exchange 的话,它会直接丢弃掉 Producer 发送过来的消息。交换器有四种消息调度策略(下面会介绍),分别是fanout, direct, topic, headers。

8.Binding(绑定):用于建立Exchange和Queue之间的关联。一个绑定就是基于Binding Key将Exchange和Queue连接起来的路由规则,所以可以将交换器理解成一个由Binding构成的路由表。

9.Binding Key(绑定键):Exchange与Queue的绑定关系,用于匹配Routing Key。最大长度255 字节。

10.Broker:RabbitMQ Server,服务器实体。

生产者发送消息流程:
1、生产者和Broker建立TCP连接。
2、生产者和Broker建立通道。
3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。
4、Exchange将消息转发到指定的Queue(队列)

消费者接收消息流程:
1、消费者和Broker建立TCP连接
2、消费者和Broker建立通道
3、消费者监听指定的Queue(队列)
4、当有消息到达Queue时Broker默认将消息推送给消费者。
5、消费者接收到消息。
6、ack回复

3.2.1 RabbitMQ 交换机类型

(1)Direct exchange(直连交换机)(路由模式)

383e18869172461b8d017578b68065b2.png

 直连型交换机(direct exchange)是根据消息携带的路由键(routing key)将消息投递给对应队列的,步骤如下:

1、将一个队列绑定到某个交换机上,同时赋予该绑定一个路由键(routing key)

2、当一个携带着路由值为R的消息被发送给直连交换机时,交换机会把它路由给绑定值同样为R的队列。

(2)Fanout exchange(扇型交换机)(订阅模式|广播模式)

b48f5fc2f0ed43edb8bf073adb4c69cd.png 

扇型交换机(funout exchange)将消息路由给绑定到它身上的所有队列。不同于直连交换机,路由键在此类型上不起作用。如果N个队列绑定到某个扇型交换机上,当有消息发送给此扇型交换机时,交换机会将消息的发送给这所有的N个队列

(3)Topic exchange(主题交换机)(通配符模式)

9355b9fa1f2d448cb34a0faa1d9733a4.png

 主题交换机(topic exchanges)中,队列通过路由键绑定到交换机上,然后,交换机根据消息里的路由值,将消息路由给一个或多个绑定队列。

扇型交换机和主题交换机异同:

对于扇型交换机路由键是没有意义的,只要有消息,它都发送到它绑定的所有队列上。

对于主题交换机,路由规则由路由键决定,只有满足路由键的规则,消息才可以路由到对应的队列上

规则:

* (星号) 用来表示一个单词 (必须出现的)
# (井号) 用来表示任意数量(零个或多个)单词

通配的绑定键是跟队列进行绑定的,举个小例子:
队列Q1 绑定键为*.TT.* 队列Q2绑定键为TT.#
如果一条消息携带的路由键为A.TT.B,那么队列Q1将会收到;
如果一条消息携带的路由键为TT.AA.BB,那么队列Q2将会收到;

 

主题交换机的强大之处:

当一个队列的绑定键为 #(井号) 的时候,这个队列将会无视消息的路由键,接收所有的消息。</

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值