rabbitmq的消费确认机制主要分为三个类型:
1.none
2.自动auto(默认)
3.手动manual
在配置文件中通过以下进行配置
spring.rabbitmq.listener.simple.acknowledge-mode=auto
spring.rabbitmq.listener.simple.acknowledge-mode= none
spring.rabbitmq.listener.simple.acknowledge-mode = manual
AUTO
rabbitmq默认的确认方式为auto,即自动确认,即消费者消费消费消息后会自动给broker发送确认信息,但在消费过程中发生异常的话,要分以下情况:
1.抛出AmqpRejectAndDontRequeueException异常时,消息会被拒绝,且不会回到消息队列
2.抛出ImmediateAcknowledgeAmqpException异常会被消费确认。
3.抛出其他异常,消息会重新回到队列,重新推送给消费者,一直到消费成功,否则会一直循环,所以在消费自动确认模式下,需要配置消息重试机制,合理处理发生异常重试的消息。
Manual
手动确认的模式下,在消费端需要手动向broker发生消息确认,broker会根据返回的ack删除该已消费的消息 。但是如果发送异常且没有手动处理并进行消息确认、拒绝、失败的操作,即broker没有收到任何的ack信息,消息队列仍然会保留该消息,并在后续进行重新投递,直到该消息被确认或拒绝。所以在开发中应该妥善处理异常情况,并搭配重试机制,死信队列。手动模式下,确认方式有以下3种:
1.basicAck
basicAck(long deliveryTag, boolean multiple),表示成功确认,broker会删除该消息,参数deliveryTag表示消息的唯一序号,multiple表示是否一次消费多条消息,false表示只确认该序号对应的消息,true表示确认所有比此序号小的消息。
2.basicNack
basicNack(long deliveryTag, boolean multiple, boolean requeue),表示失败确认,一般在消费异常的时候用到,参数requeue表示是否重新入队列。false表示不会重新入队列,直接丢弃。
3.basicReject
basicReject(long deliveryTag, boolean requeue),表示拒绝该消息,requeue表示是否重回队列,与basicNack的区别在于不能进行批量拒绝。
根据官网的描述:
在basicNack和basicReject中,requeue参数为false时分别有以下情况:
1.配置了死信队列
false表示不重新入队进行消费,配置了死信队列,则消息进入死信队列
2.未配置死信队列
false表示不重新入队进行消费,没有配置了死信队列,则消息直接删除丢弃
根据上面的描述可知,上面的三个确认方法,basicNack和basicReject的requeue=false时,都会将消息队列的消息删除。
在手动模式下,如果连接中断、消费异常时,消息会自动重新入队:
这种情况下,可能会出现消息幂等性的问题,即消费者接受到的消息可能是之前传递给其他消费者的消息,但有一个参数redeliver表示,为true表示是重新消费的。
在手动和自动模式下,如果都配置了重试机制,但消费者抛出异常时,两种模式的消息重试不同
- 自动模式下,消费者抛出异常,消息重新入队,多次消费失败了,达到重试上限了,会自动丢弃。
- 手动模式下,消费者抛出一行,消息重试,但如果消息一直没有被确认或者拒绝,消息则会处于unacked状态,导致消息积压。
消息进入死信队列的前提是,消息生产队列需绑定死信队列,且消息确认为失败或拒绝时