必知必会!RabbitMQ消息确认机制

7,200 阅读6分钟

消息确认

RabbitMQ消息确认机制分为发送消息确认消息接收确认

image.png

发送消息确认

发送消息确认包含两部分。第一部分,用来确认生产者是否成功将消息发送到Broker ,第二部分,Broker上的交换机再将消息投递给队列 queue的过程中,消息是否成功投递。RabbitMQ为我们提供了两个回调ConfirmCallback和ReturnCallback来确保消息的投递。消息从生产者到 Broker有一个 ConfirmCallback确认模式,当消息被Broker接收到就会触发ConfirmCallback回调,因此,通过此回调函数就可以知道有没有到达Broker。消息从交换机到 队列 投递失败有一个ReturnCallback回退模式。🚨注意:在RedisTemplate中可以通过setMandatory(boolean mandatory)方法或者在yml配置文件中通过template.mandatory: true来配置当消息没能路由到指定队列时消息是重回生产者还是丢弃,当参数mandatory=false表示消息会被丢弃,当mandatory=true消息会返回给生产者,返回的消息可以从ReturnCallback回调中获取。下面详细介绍ConfirmCallback和ReturnCallback这两个回调。

使用两个消息回调之前需要到application.yml中配置一下消息确认回调、消息失败回调。

  1. publisher-confirm-type: 表示确认消息的类型,分别有none、correlated、simple这三种类型。

    • publisher-confirm-type: none:表示禁用发布确认模式,默认值,使用此模式之后,不管消息有没有发送到Broker都不会触发ConfirmCallback回调。

    • publisher-confirm-type: correlated:表示消息成功到达Broker后触发ConfirmCalllBack回调

    • publisher-confirm-type: simple:simple模式下如果消息成功到达Broker后一样会触发ConfirmCalllBack回调,发布消息成功后使用rabbitTemplate调用waitForConfirms或waitForConfirmsOrDie方法等待broker节点返回发送结果,根据返回结果来判定下一步的逻辑,🚨注意:waitForConfirmsOrDie方法如果返回false则会关闭channel信道,则接下来无法发送消息到broker。

  2. publisher-returns: true ,true表示开启失败回调,开启后当消息无法路由到指定队列时会触发ReturnCallback回调。

ConfirmCalllBack

发送消息时会触发该回调,消息投递到Broker成功或者失败都会返回一个ConfirmCallback,我们可以通过返回的ack来判断消息是否达到Broker。ConfirmCalllBack是一个接口,我们需要实现该接口并重写其comfirm方法。comfirm()方法如下,其中参数CorrelationData correlationData是用来做消息的唯一标识,我们在发送消息时可以附带这个唯一标识,在该回调中可以获取到当前消息的唯一标识。boolean ack表示消息发送到Broker的状态,true表示送达,false反之。String s表示发送失败的原因。

@Override
public void confirm(CorrelationData correlationData, boolean ack, String s) {
    //
}

ReturnCallBack

如果消息未能路由到目标队列则将触发回调 ReturnCallback,ReturnCallback也是一个接口,我们需要实现该接口并重写其returnedMessag方法。returnedMessag方法如下,其中参数Message message表示的是消息体,int replyCode表示响应码,String replyText表示响应内容,String exchange表示发送消息时指定的交换机,String routingKey表示发送消息时指定的routing key,这些参数就是记录下当前消息的详细投递数据,方便我们后面根据业务的需求做消息的重发或者补偿等操作。

@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
    //
}

消息接收确认(ACK)

消费者收到消息后需要对 RabbitMQ Server 进行消息ACK确认,RabbitMQ根据确认信息决定是删除队列中的该信息还是重新发送。

消息确认的三种模式:

  1. 手动确认 listener.simple.acknowledge-mode: manual,在该模式下,消费者消费消息后需要根据消费情况给Broker返回一个回执,是确认ack使Broker删除该条已消费的消息,还是失败确认返回nack,还是拒绝该消息。开启手动确认后,如果消费者接收到消息后还没有返回ack就宕机了,这种情况下消息也不会丢失,只有RabbitMQ接收到返回ack后,消息才会从队列中被删除。该模式下有三种确认方式,后面会介绍。

  2. 自动确认 listener.simple.acknowledge-mode: none,rabbitmq默认消费者正确处理所有请求。(不设置时的默认方式)

  3. 根据请况确认 listener.simple.acknowledge-mode: auto,主要分成以下几种情况:

    • 如果消费者在消费的过程中没有抛出异常,则自动确认。

    • 当消费者消费的过程中抛出AmqpRejectAndDontRequeueException异常的时候,则消息会被拒绝,且该消息不会重回队列。

    • 当抛出ImmediateAcknowledgeAmqpException异常,消息会被确认。

    • 如果抛出其他的异常,则消息会被拒绝,但是与前两个不同的是,该消息会重回队列,如果此时只有一个消费者监听该队列,那么该消息重回队列后又会推送给该消费者,会造成死循环的情况。

消费端手动确认的三种方式

  • basicAck(long deliveryTag, boolean multiple) basicAck方法表示成功确认,使用此方法后,消息会被rabbitmq broker删除,其中参数long deliveryTag为消息的唯一序号,boolean multiple表示是否一次消费多条消息,false表示只确认该序列号对应的消息,true则表示确认该序列号对应的消息以及比该序列号小的所有消息,比如我先发送2条消息,他们的序列号分别为2,3,并且他们都没有被确认,还留在队列中,那么如果当前消息序列号为4,那么当multiple为true,则序列号为2、3的消息也会被一同确认。

  • basicNack(long deliveryTag, boolean multiple, boolean requeue) basicNack方法表示失败确认,一般当我们消费消息时出现异常用到此方法,可以通过参数requeue设置是否将消息重新投递到队列。requeue表示消息是否重回队列,如果requeue=false表示消息不重回队列并且丢弃该消息,如果为requeue=true则消息重回队列。

  • basicReject(long deliveryTag, boolean requeue)basicReject方法表示拒绝消息,requeue=false表示被拒绝的消息会被丢弃,requeue=true表示消息会重回队列,该方法与basicNack()方法的区别就是不支持multiple批量确认。

🏁以上就是关于RabbitMQ消息确认机制的介绍,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助那就点个赞👍吧😋😻😍

默认标题_动态分割线_2021-07-15-0.gif