消息收发
- 消息发送:支持指定同步发送、异步发送;支持身份认证,客户端连接RabbitMQ服务端时使用SSL或账号密码验证;支持广播发送;支持发送持久化消息、非持久化消息。
- 消息消费:采用pull方式和push方式消费,多消费者间轮询消费。
消息发送可靠性
RabbitMQ消息发送可靠性有两个方法,一个是事务,另一个是Confirm机制。事务能够解决producer与broker之间消息确认的问题,只有消息成功被broker接受,事务提交才能成功,但会降低RabbitMQ的性能,为此RabbitMQ提供了一种低消耗的事务管理方式,将channel设置成confirm模式。confirm模式的channel,通过该channel发出的消息会生成一个唯一的有序ID(从1开始),一旦消息成功发送到相应的队列之后,RabbitMQ服务端会发送给生产者一个确认标志,包含消息的ID,这样生产者就知道该消息已经发送成功了。Confirm支持普通发送方确认模式、批量确认模式、异步监听发送方确认模式,可以满足发送可靠性和高性能需求。
消息确认
为了保证消息从队列可靠地到达消费者,RabbitMQ提供了消息确认机制。
- 消费者订阅队列的时候,可以指定autoAck参数,当autoAck为true的时候,RabbitMQ采用自动确认模式,RabbitMQ自动把发送出去的消息设置为确认,然后从内存或者硬盘中删除,而不管消费者是否真正消费到了这些消息。
- 当autoAck为false的时候,RabbitMQ会等待消费者回复的确认信号,收到确认信号之后才从内存或者磁盘中删除消息。
消息确认机制是RabbitMQ消息可靠性投递的基础,只要设置autoAck参数为false,消费者就有足够的时间处理消息,不用担心处理消息的过程中消费者进程挂掉后消息丢失的问题。
消息TTL
Time To Live,也就是生存时间,是一条消息在队列中的最大存活时间,单位是毫秒。
- RabbitMQ可以对消息和队列设置TTL。
- RabbitMQ支持设置消息的过期时间,在消息发送的时候可以进行指定,每条消息的过期时间可以不同。
- RabbitMQ支持设置队列的过期时间,从消息入队列开始计算,直到超过了队列的超时时间配置,那么消息会变成死信,自动清除。
- 如果两种方式一起使用,则过期时间以两者中较小的那个数值为准。
- 当然也可以不设置TTL,不设置表示消息不会过期;如果设置为0,则表示除非此时可以直接将消息投递到消费者,否则该消息将被立即丢弃。
持久化
RabbitMQ的持久化分为三个部分:交换器持久化、队列持久化和消息的持久化。
- 交换器持久化可以通过在声明队列时将durable参数设置为true。如果交换器不设置持久化,那么在RabbitMQ服务重启之后,相关的交换器元数据会丢失,不过消息不会丢失,只是不能将消息发送到这个交换器了。
- 队列的持久化能保证其本身的元数据不会因异常情况而丢失,但是不能保证内部所存储的消息不会丢失。要确保消息不会丢失,需要将其设置为持久化。队列的持久化可以通过在声明队列时将durable参数设置为true。
- 设置了队列和消息的持久化,当RabbitMQ服务重启之后,消息依然存在。如果只设置队列持久化或者消息持久化,重启之后消息都会消失。
对于可靠性不是那么高的消息可以不采用持久化处理以提高整体的吞吐量。在实际中,需要根据实际情况在可靠性和吞吐量之间做一个权衡。
延迟队列
一般的队列,消息一旦进入队列就会被消费者立即消费。延迟队列就是进入该队列的消息会被消费者延迟消费,延迟队列中存储的对象是的延迟消息,“延迟消息”是指当消息被发送以后,等待特定的时间后,消费者才能拿到这个消息进行消费。RabbitMQ提供TTL配合死信队列和延时队列插件两种方式来满足延时消息业务场景。
死信队列
当消息在一个队列中变成死信之后,他能被重新发送到另一个交换器中,这个交换器成为死信交换器,与该交换器绑定的队列称为死信队列。消息变成死信有下面几种情况:
- 消息被拒绝
- 消息过期
- 队列达到最大长度
DLX也是一个正常的交换器,和一般的交换器没有区别,他能在任何的队列上面被指定,实际上就是设置某个队列的属性。当这个队列中有死信的时候,RabbitMQ会自动将这个消息重新发送到设置的交换器上,进而被路由到另一个队列。当发生异常的时候,消息不能够被消费者正常消费,被加入到了死信队列中。后续的程序可以根据死信队列中的内容分析当时发生的异常,进而改善和优化系统。
优先级队列
优先级队列是指优先级高的消息往往放在队列的head头部,相比低优先级的消息,要优先投递给消费者进行处理。
在RabbitMQ中,我们可以设置消息的优先级,在发送消息时指定消息的优先级,可以分为10个级别,级别越高优先级越大。当多个消息拥有相同的优先级时,它们按照FIFO的顺序排序。
镜像队列
Rabbitmq支持镜像队列,队列的多个副本保存在不同实例节点。队列分为主备角色,对某个 queue 来说,只有 master 对外提供服务,而其他 slave 只提供备份服务,在 master 所在节点不可用时,选出一个 slave 作为新的 master 继续对外提供服务。无论客户端的请求打到 master 还是 slave 最终数据都是从 master 节点获取。
- 当请求打到 master 节点时,master 节点直接将消息返回给 client,同时 master 节点会通过 GM(Guaranteed Multicast)协议将 queue 的最新状态广播到 slave 节点。GM 保证了广播消息的原子性,即要么都更新要么都不更新。
- 当请求打到 slave 节点时,slave 节点需要将请求先重定向到 master 节点,master 节点将将消息返回给 client,同时 master 节点会通过 GM 协议将 queue 的最新状态广播到 slave 节点。