Rabbitmq原理和分析

1、基本原理

MQ全称为Message Queue,是一种分布式应用程序的的通信方法,它是消费-生产者模型的一个典型的代表,producer往消息队列中不断写入消息,而另一端consumer则可以读取或者订阅队列中的消息。

RabbitMQ是MQ产品的典型代表,是一款基于AMQP协议可复用的企业消息系统。业务上,可以实现服务提供者和消费者之间的数据解耦,提供高可用性的消息传输机制,在实际生产中应用相当广泛。本文意在介绍Rabbitmq的基本原理,包括rabbitmq基本框架,概念,通信过程等。

2、系统架构

Rabbitmq系统最核心的组件是Exchange和Queue,下图是系统简单的示意图。Exchange和Queue是在rabbitmq server(又叫做broker)端,producer和consumer在应用端。

注意:生产者、消费者、中间件不必在一台机器上,实际应用中也是绝大多数不在一起的。我们可以用一张图表示RabbitMQ的构造:

Producer

消息发送者,在MQ中被称为生产者(producer),一个发送消息的应用也被叫做生产者,用P表示。

Consumer

生产者“生产”出消息后,最终由谁消费呢?等待接受消息的应用程序,我们称之为消费者(Consuming ),用C表示。

Queue

消息只能存储在队列(queue)中。尽管消息在rabbitMQ和应用程序间流通,但是队列却是存在于RabbitMQ内部。

一个队列不受任何限制,它可以存储你想要存储的消息量,它本质上是一个无限的缓冲区。

多个生产者可以向同一个队列发送消息,多个消费者可以尝试从同一个消息队列中接收数据。

一个队列像下面这样(上面是它的队列名称)

消息队列,提供了FIFO的处理机制,具有缓存消息的能力。Rabbitmq中,队列消息可以设置为持久化,临时或者自动删除。

1)、设置为持久化的队列,queue中的消息会在server本地硬盘存储一份,防止系统crash,数据丢失。

2)、设置为临时队列,queue中的数据在系统重启之后就会丢失。

3)、设置为自动删除的队列,当不存在用户连接到server,队列中的数据会被自动删除。

Exchange

Exchange类似于数据通信网络中的交换机,提供消息路由策略。Rabbitmq中,producer不是通过信道直接将消息发送给queue,而是先发送给Exchange。一个Exchange可以和多个Queue进行绑定,producer在传递消息的时候,会传递一个ROUTING_KEY,Exchange会根据这个ROUTING_KEY按照特定的路由算法,将消息路由给指定的queue。和Queue一样,Exchange也可设置为持久化,临时或者自动删除。

Exchange有4种类型:direct(默认),fanout, topic, 和headers,不同类型的Exchange转发消息的策略有所区别:

1)、Direct 直接交换器,工作方式类似于单播,Exchange会将消息发送完全匹配ROUTING_KEY的Queue。

2)、fanout广播是式交换器,不管消息的ROUTING_KEY设置为什么,Exchange都会将消息转发给所有绑定的Queue。

3)、topic主题交换器,工作方式类似于组播,Exchange会将消息转发和ROUTING_KEY匹配模式相同的所有队列,比如,ROUTING_KEY为user.stock的Message会转发给绑定匹配模式为 * .stock,user.stock, * . * 和#.user.stock.#的队列。( * 表是匹配一个任意词组,#表示匹配0个或多个词组)。

4)、headers消息体的header匹配(ignore)。

Binding

所谓绑定就是将一个特定的 Exchange 和一个特定的 Queue 绑定起来。Exchange 和Queue的绑定可以是多对多的关系。

virtual host

在Rabbitmq server上可以创建多个虚拟的message broker,又叫做virtual hosts (vhosts)。每一个vhost本质上是一个mini-rabbitmq server,分别管理各自的exchange和bindings。vhost相当于物理的server,可以为不同app提供边界隔离,使得应用安全的运行在不同的vhost实例上,相互之间不会干扰。producer和consumer连接rabbit server需要指定一个vhost。

3、通信过程

假设P1和C1注册了相同的Broker,Exchange和Queue。P1发送的消息最终会被C1消费。基本的通信流程大概如下所示:

1)、1生产消息,发送给服务器端的。

2)、 ExchangeExchange收到消息,根据ROUTINKEY,将消息转发给匹配的Queue1。

3)、 Queue1收到消息,将消息发送给订阅者C1。

4)、 C1收到消息,发送ACK给队列确认收到消息。

5)、 Queue1收到ACK,删除队列中缓存的此条消息。

Consumer收到消息时需要显式的向rabbit broker发送basic.ack消息或者consumer订阅消息时设置auto_ack参数为true。在通信过程中,队列对ACK的处理有以下几种情况:

1)、如果consumer接收了消息,发送ack,rabbitmq会删除队列中这个消息,发送另一条消息给consumer。

2)、 如果cosumer接受了消息,但在发送ack之前断开连接,Rabbitmq会认为这条消息没有被deliver,在consumer在次连接的时候,这条消息会被redeliver。

3)、 如果consumer接受了消息,但是程序中有bug,忘记了ack,Rabbitmq不会重复发送消息。

4)、 Rabbitmq2.0.0和之后的版本支持consumer reject某条(类)消息,可以通过设置requeue参数中的reject为true达到目地,那么Rabbitmq将会把消息发送给下一个注册的consumer。

4、应用场景

异步处理

场景:用户注册后,发送短信和邮箱通知等。

1)、串行逻辑耗时150s。

2)并行逻辑耗时100s。

3.mq消息队列处理耗时55s。

发送注册短信及邮箱通知不是必须的逻辑,所以放在mq中慢慢的消费,提高了系统的整体的性能。

应用解耦

场景:双11购物节的时候,用户下单后,订单系统会及时通知库存系统。

1)、传统的做法:订单系统接口调用库存系统。

设想下,如果订单系统正在调用库存系统的时候,库存系统发生崩溃了,那么这个订单就没有成功,直接的造成了成交单的损失。

2)mq逻辑解耦。

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

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

这样即使库存系统发生崩溃,但是订单的下单信息仍然存在消息队列中,等库存系统恢复正常后,继续调用库存接口,消息不会丢失,保证了成交量。

并发削峰

针对高并发请求,比如双11并发量超大的情况下,可以将用户的下单消息先存到消息队列中,这就极大的削弱了请求的并发量,然后慢慢消费消息队列中的消息,很好的避免了卡着不动的局面,用户体验也会好很多。



作者:xiaonian0430
链接:https://www.jianshu.com/p/ff665a17473a
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值