rabbitMQ

参考原文链接

什么是MQ

消息总线(Message Queue),是一种跨进程、异步的通信机制,用于上下游传递消息。由消息系统来确保消息的可靠传递。

RabbitMQ

RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在不同的应用之间共享数据(跨平台跨语言)。RabbitMQ是使用Erlang语言编写,并且基于AMQP协议实现。

RabbitMQ的优势

  • 可靠性(Reliablity):使用了一些机制来保证可靠性,比如持久化、传输确认、发布确认
  • 灵活的路由(Flexible Routing):在消息进入队列之前,通过Exchange来路由消息。对于典型的路由功能,Rabbit已经提供了一些内置的Exchange来实现。针对更复杂的路由功能,可以将多个Exchange绑定在一起,也通过插件机制实现自己的Exchange
  • 消息集群(Clustering):多个RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker
  • 高可用(Highly Avaliable Queues):队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用
  • 支持多种协议:RabbitMQ除支持AMQP协议外,还通过插件的方式支持其它消息队列协议,比如STOMP、MQTT等

整体架构

在这里插入图片描述

消息流转

在这里插入图片描述

RabbitMQ各组件功能

在这里插入图片描述

  • Broker:标识消息队列服务器实体
  • Virtual Host:虚拟主机。标识一批交换机、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost本质上就是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器、绑定和权限机制。vhost是AMQP概念的基础,必须在链接时指定,RabbitMQ默认的vhost是 /
  • Exchange:交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列
  • Queue:消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走
  • Banding:绑定,用于消息队列和交换机之间的关联。一个绑定就是基于路由键将交换机和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表
  • Channel:信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟链接,AMQP命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说,建立和销毁TCP都是非常昂贵的开销,所以引入了信道的概念,以复用一条TCP连接
  • Connection:网络连接,比如一个TCP连接
  • Publisher:消息的生产者,也是一个向交换器发布消息的客户端应用程序
  • Consumer:消息的消费者,表示一个从一个消息队列中取得消息的客户端应用程序
  • Message:消息,消息是不具名的,它是由消息头和消息体组成。消息体是不透明的,而消息头则是由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(优先级)、delivery-mode(消息可能需要持久性存储[消息的路由模式])等

RabbitMQ的多种工作模式

Exchange分发消息时,根据类型的不同分发策略有区别。目前共四种类型:direct、fanout、topic、headers(headers匹配AMQP消息的header而不是路由键(Routing-key),此外headers交换器和direct交换器完全一致,但是性能差了很多,目前几乎用不到了。所以直接看另外三种类型。)。

fanout(广播)

exchange收到消息后,发送给所有绑定的队列,不处理routine key,优点就是快

direct(单播)

如果消息的路由键(routine key)和binding中的绑定键(binding key)一致,交换器就将消息发送到对应的队列中去,路由键与绑定键要完全匹配,如果路由键为dog,只装发给这个队列标记为dog的信息,不会转发dog.putty等其它信息

topic(组播)

topic交换器通过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。它将路由键(routing-key)和绑定键(bingding-key)的字符串切分成单词,这些单词之间用点隔开。它同样也会识别两个通配符:"#“和”*"。#匹配0个或多个单词,匹配不多不少一个单词。

通过通配符匹配发送到可以匹配的所有binding key的队列上

消息保存(消息持久化)

主要涉及Queue持久化,Message持久化,Exchange持久化

消息确认模式

为了保证客户端能够确定消息已经正确发送了
RabbitMQ提供了两种消息确认模式:

  • 一是通过AMQP协议里的事务机制
  • 二是把信道设置成确认模式

因为事务模式需要生产者同步的等待broke的执行结果,所以性能上会降低吞吐量,一般不适用

把信道设置成确认模式后,在该信道上发布的所有消息都会被分配一个唯一的ID,一旦消息被投递到匹配的队列中,该信道就会向生产者发送确认消息,在确认消息中包含了唯一ID,从而让生产者知道消息已经正确发送到队列

消费者应答

消息确认模式解决了从发送方发送到broke。

在实际任务中可能会出现消费者接收到消息,但是还没处理完就宕机了,这将会导致消息没正常处理就丢失了,为了避免这个问题,可以要求消费者在消费完消息后发送一个回执给RabbitMQ服务器,RabbitMQ服务器收到这个回执,才将消息从队列中删去。

两种消息回执模式:自动回执和手动回执

  • 自动回执:当broke成功发送消息给消费者后就会立即把消息从队列中删除,而不用等待消费者回送确认消息
  • 手动回执:当broke发送消息给消费者后不会立即删除,而是要等待消费者回送的确认消息后才会删除
拒绝消息

当消费者处理消息失败或者当前不能处理该消息时,可以给Broke发送一个拒绝消息的指令

流控机制

RabbitMQ可以对内存和磁盘的使用量设置阈值,当达到阈值后生产者将被阻塞。
RabbitMQ基于信用证的流控机制,在消息处理进程内部有一个信用组(initialCredit, MoreCreditAfter)表示生产者进程中对应于某一消费者的初始credit和消费者接受消息后返回给生产者的credit。

例如:生产者A向消费者B发送消息,每发送一条消息都会使A中的B的credit减1,如果A中的credit减为0,阻塞。
B每收到消息后就会发送应答,A每收到B的应答,就增加A中的B的credit增加MoreCreditAfter,

TTL

TTL(Time To Live):生存时间。RabbitMQ支持消息的过期时间,一共两种。

  • 在消息发送时可以进行指定。通过配置消息体的properties,可以指定当前消息的过期时间。
  • 在创建Exchange时可进行指定。从进入消息队列开始计算,只要超过了队列的超时时间配置,那么消息会自动清除。

死信队列DLX

死信队列(DLX Dead-Letter-Exchange):利用DLX,当消息在一个队列中变成死信(dead message)之后,它能被重新publish到另一个Exchange,这个Exchange就是DLX。

DLX也是一个正常的Exchange,和一般的Exchange没有区别,它能在任何的队列上被指定,实际上就是设置某个队列的属性。

当这个队列中有死信时,RabbitMQ就会自动的将这个消息重新发布到设置的Exchange上去,进而被路由到另一个队列。

消息变成死信的几种情况:
  • 消息被拒绝(basic.reject/basic.nack)并且requeue=false
  • 消息TTL过期
  • 队列达到最大长度

消费端ACK与NACK

消费端进行消费的时候,如果由于业务异常可以进行日志的记录,然后进行补偿。由于服务器宕机等严重问题,我们需要手动进行ACK保障消费端消费成功。

消费端重回队列是为了对没有成功处理消息,把消息重新返回到Broker。一般来说,实际应用中都会关闭重回队列,也就是设置为false。

生产者Confirm机制

  • 消息的确认,是指生产者投递消息后,如果Broker收到消息,则会给我们生产者一个应答。
  • 生产者进行接受应答,用来确认这条消息是否正常的发送到了Broker,这种方式也是消息的可靠性投递的核心保障!

如何保证幂等性

消费端实现幂等性,就意味着我们的消息永远不会消费多次,即使我们收到了多条一样的信息。

  • 唯一ID+指纹码机制,利用数据库主键去重
  • 利用redis的原子性去实现

如何保证可靠性?

生产端的可靠性投递
  • 保证消息的成功发出
  • 保障MQ节点的成功接受
  • 发送端收到MQ节点(Broker)确认应答
  • 完善消息的补偿机制

Channel模式和Connection模式

CHANNEL模式:程序运行期间ConnectionFactory会维护着一个Connection,所有的操作都会使用这个Connection,但一个Connection中可以有多个Channel,操作rabbitmq之前都必须先获取到一个Channel,否则就会阻塞(可以通过setChannelCheckoutTimeout()设置等待时间),这些Channel会被缓存(缓存的数量可以通过setChannelCacheSize()设置);

CONNECTION模式:这个模式下允许创建多个Connection,会缓存一定数量的Connection,每个Connection中同样会缓存一些Channel,除了可以有多个Connection,其它都跟CHANNEL模式一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值