(三)RabbitMQ——ACK消息确认入门

参考:https://blog.csdn.net/weixin_34367257/article/details/91849513
https://www.cnblogs.com/aijiaxiang/p/12803591.html

参考:https://www.cnblogs.com/yuefeng123/p/12658531.html

参考:https://blog.csdn.net/wufaliang003/article/details/108314339


一、发送消息的过程

发送消息(发送端- 交换机- 队列) (实际是2个过程)

总结:只有当消息确认ack为true且未执行失败回调方法时,才保证发送端消息已经成功发送!
执行失败的回调方法时,说明消息已经发送到(broker)交换机(第一个过程是OK的),交换机路由到队列出现了问题(第二个过程)。此时需要我们自己来解决:

发送端信息成功到交换机确认机制:
前提:开启消息确认
connectionFactory.setPublisherConfirms(true);

    如果成功,会给发送端一个为true的ack,表示发送成功!
    如果失败,会给发送端一个为false的ack,表示发送失败!
代码如下:
        /**
         * 发送端是否发送到交换机
         */
        public class RabbitmqConfirm implements RabbitTemplate.ConfirmCallback {
        
            /**
             * 发送端回调方法
             * @param correlationData 发送到mq时传入的业务参数(例如:业务id)
             * @param ack  结果标志
             *             true: 发送端 ——> 交换机 成功
             *             false:发送端 ——> 交换机 失败
             * @param message 结果消息:ack为true时,返回为null
             *                        ack为false时,返回失败消息
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String message) {
                System.out.println(correlationData.getId());
                System.out.println(ack);
                System.out.println(message);
            }
        }

交换机信息成功路由到队列确认机制:
前提:开启消息确认
connectionFactory.setPublisherConfirms(true);
开启失败回调
rabbitTemplate.setMandatory(true);

    如果成功,则不会调用失败回调方法!
    如果失败,则会调用失败回调方法!    

代码如下:

        /**
         * 交换机是否发送到队列
         */
        public class RabbitmqReturnConfirm implements RabbitTemplate.ReturnCallback {
        
            /**
             * 交换机发送队列失败回调:
             *
             * 采用一个不存在的routingKey可做测试
             * @param message    发送的消息+消息配置信息
             * @param replyCode  状态码
             * @param replyText  状态内容
             * @param exchange   交换机
             * @param routingKey 路由键
             */
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                System.out.println(message);
                System.out.println(replyCode);
                System.out.println(replyText);
                System.out.println(exchange);
                System.out.println(routingKey);
            }
        }    

二、Message acknowledgment 消息确认机制

//消费者成功消费消息后,给Rabbitmq服务器一个应答
默认情况下,RabbitMQ 会顺序的分发每个Message。当分发后,会将该Message删除,然后将下一个Message分发到下一个Consumer。这种分发方式叫做round-robin。

每个Consumer可能需要一段时间才能处理完收到的数据。如果在这个过程中,Consumer出错了,异常退出了,而数据还没有处理完成,那么非常不幸,这段数据就丢失了。因为我们采用no-ack的方式进行确认,也就是说,每次Consumer接到数据后,而不管是否处理完成,RabbitMQ Server会立即把这个Message标记为完成,然后从queue中删除了。

如果一个Consumer异常退出了,它处理的数据能够被另外的Consumer处理,这样数据在这种情况下就不会丢失了(注意是这种情况下)。

为了保证数据不被丢失,RabbitMQ支持消息确认机制,即acknowledgments。为了保证数据能被正确处理而不仅仅是被Consumer收到,那么我们不能采用no-ack。而应该是在处理完数据后发送ack。

在处理数据后发送的ack,就是告诉RabbitMQ数据已经被接收,处理完成,RabbitMQ可以去安全的删除它了。

如果Consumer退出了但是没有发送ack,那么RabbitMQ就会把这个Message发送到下一个Consumer。这样就保证了在Consumer异常退出的情况下数据也不会丢失。

这里并没有用到超时机制。RabbitMQ仅仅通过Consumer的连接中断来确认该Message并没有被正确处理。也就是说,RabbitMQ给了Consumer足够长的时间来做数据处理。

消息确认,对于spring-boot来说,就是一个开关,它就是spring.rabbitmq.listener.simple.acknowledge-mode
acknowledgeMode有三值:

  • A、NONE = no acks will be sent (incompatible with channelTransacted=true).
    RabbitMQ calls this “autoack” because the broker assumes all messages are acked without any action from the consumer.

  • B、MANUAL = the listener must acknowledge all messages by calling Channel.basicAck().

  • C、AUTO = the container will acknowledge the message automatically, unless the MessageListener throws an exception.
    Note that acknowledgeMode is complementary to channelTransacted - if the channel is transacted then the broker requires a commit notification in addition to the ack. This is the default mode. See also txSize.
    (注意,acknowledgement emode是对channelTransacted的补充——如果通道被处理了,那么除了ack,代理还需要一个commit通知。这是默认模式。也看到txSize。)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值