RabbitMQ消息的确认机制
RabbitMQ提供了两种方式来解决消息投递的可靠性,避免消息丢失或消息投递失败的情况
- confirm确认模式
- return退回模式
springboot中配置开启才可以使用,如果不设置消息投递失败后,默认丢弃消息,不会进行回调
spring:
rabbitmq:
publisher-confirm-type: correlated
publisher-returns: true
工作机制
消息从producer投递到exchange,会返回一个confirmCallback。无论是否投递成功,都会返回。当ack=true,表示成功,当ack=fase,表示失败
消息从exchange投递到queue,投递失败则会返回一个returnCallback
确认模式:
设置ConnectionFactory的publisher-confirm-type=correlated,开启confirm确认模式
使用rabbitTemplate.setConfirmCallback设置回调函数,当消息发送到Exchange后回调confirm方法,在方法中判断ack,如果为true,则发送成功。如果为false,则发送失败
回退模式:
设置ConnectionFactory的publisher-returns=true,开启return确认模式
使用rabbitTemplate.setReturnCallback设置spring.rabbitmq.publisher-returns=true,当消息由Exchange路由到queue失败后,如果设置了 spring.rabbitmq.template.mandatory=true,则消息回回退给消息生产者producer,并执行回调函数
ConsumerASK
ack指Acknowledge,确认。 表示消费端收到消息后的确认方式。
三种确认方式:
acknowledge=“none” 消费端没有异常,则调用channel。basicAck(deliveryTag,false)确认签到消息
acknowledge=“manual” 出现异常,则在catch中调用basicNack或basicReject拒接消息,让重新发消息
根据异常情况确认:acknowledge=“auto”,(使用麻烦,不演示)
自动确认是指,当消息一旦被Consumer接收到,则自动确认收到,并将相应 message 从 RabbitMQ 的消息缓存中移除。但是在实际业务处理中,很可能消息接收到,业务处理出现异常,那么该消息就会丢失。
手动确认方式,则需要在业务处理成功后,调用channel.basicAck(),手动签收,如果出现异常,则调用channel.basicNack()方法,让其自动重新发送消息。
消费端限流
设置每次处理的请求数,达到限流的作用。mq能够削峰填谷
prefetch属性是一次去拉取多少,消费端的确认模式一定要为手动。
TTL过期时间
rabbitmq可以设置队列的过期时间和消息单独的过期时间,假如都设置了以时间短的为主,
可以应用的场景,例如 下单后 24小时以为完成支付。
Rabbitmq的过期消除方法是当消息在队列的顶端等待被消费的时候才会激活,
但是队列的过期时间到达就会移除里面全部的消息。
用法:
设置队列过期时间使用参数:x-message-ttl,单位:ms(毫秒),会对整个队列消息统一过期。
设置消息过期时间使用参数:expiration。单位:ms(毫秒),当该消息在队列头部时(消费时),会单独判断这一消息是否过期。
如果两者都进行了设置,以时间短的为准。
死信队列
什么是死信队列?
一般来说,producer将消息投递到queue中,consumer从queue取出消息进行消费,但某些时候由于特定的原因导致queue中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信(Dead Letter),所有的死信都会放到死信队列中。“死信”消息会被RabbitMQ进行特殊处理,如果配置了死信队列信息,那么该消息将会被丢进死信队列中,如果没有配置,则该消息将会被丢弃
如何能成为死信
- 消息被拒绝(basic.reject或basic.nack)并且requeue=false.
- 消息TTL过期
- 队列达到最大长度(队列满了,无法再添加数据到mq中)
延迟队列
延迟队列存储的对象肯定是对应的延时消息,所谓"延时消息"是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费。
普通队列中的元素总是等着希望被早点取出处理,而延时队列中的元素则是希望被在指定时间得到取出和处理 。
但是RabbitMQ可以用TTL+死信队列实现延迟队列。