消息队列手动确认Ack
以RabbitMQ为例,默认情况下 RabbitMQ 是自动ACK机制,就意味着 MQ 会在消息发送完毕后,自动帮我们去ACK,然后删除消息的信息。
这样依赖就存在这样一个问题:
如果消费者处理消息需要较长时间,最好的做法是消费端处理完之后手动去确认。
1、配置文件:
rabbitmq:
host: ${yun.activity.rabbitmq.host}
port: ${yun.activity.rabbitmq.port}
username: ${yun.activity.rabbitmq.username}
password: ${yun.activity.rabbitmq.password}
virtual-host: ${yun.activity.rabbitmq.virtual-host}
publisher-confirms: true
publisher-returns: true
template:
mandatory: true
listener:
simple:
acknowledge-mode: manual
通过acknowledge-mode: manual 设置为手动设置Ack模式。
2、消费者:
@RabbitListener(queues = "activity-eleven-first-notify", containerFactory = "activityElevenCainerFactory")
public void processNormalOrder(Message message, Channel channel) {
try {
dealInfo(message);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上代码通过,channel.basicAck去手动回复消息处理状态,
除了basicAck之外,RabbitMQ还提供了其他几个方法进行设置Ack,如下:
另外,消息的确认类型:
1)channel.basicAck(deliveryTag, multiple);
consumer处理成功后,通知broker删除队列中的消息,如果设置multiple=true,表示支持批量确认机制以减少网络流量。
例如:有值为5,6,7,8 deliveryTag的投递
如果此时channel.basicAck(8, true);则表示前面未确认的5,6,7投递也一起确认处理完毕。
如果此时channel.basicAck(8, false);则仅表示deliveryTag=8的消息已经成功处理。
2)channel.basicNack(deliveryTag, multiple, requeue);
consumer处理失败后,例如:有值为5,6,7,8 deliveryTag的投递。
如果channel.basicNack(8, true, true);表示deliveryTag=8之前未确认的消息都处理失败且将这些消息重新放回队列中。
如果channel.basicNack(8, true, false);表示deliveryTag=8之前未确认的消息都处理失败且将这些消息直接丢弃。
如果channel.basicNack(8, false, true);表示deliveryTag=8的消息处理失败且将该消息重新放回队列。
如果channel.basicNack(8, false, false);表示deliveryTag=8的消息处理失败且将该消息直接丢弃。
3)channel.basicReject(deliveryTag, requeue);
相比channel.basicNack,除了没有multiple批量确认机制之外,其他语义完全一样。
如果channel.basicReject(8, true);表示deliveryTag=8的消息处理失败且将该消息重新放回队列。
如果channel.basicReject(8, false);表示deliveryTag=8的消息处理失败且将该消息直接丢弃。
由此可见,手动Ack如果处理方式不对会发生一些问题。
1.没有及时ack,或者程序出现bug,所有的消息将被存在unacked中,消耗内存
如果忘记了ack,那么后果很严重。当Consumer退出时,Message会重新分发。然后RabbitMQ会占用越来越多的内存,由于 RabbitMQ会长时间运行,因此这个“内存泄漏”是致命的。
2.如果使用BasicNack,将消费失败的消息重新塞进队列的头部,则会造成死循环。
(解决basicNack造成的消息循环循环消费的办法是为队列设置“回退队列”,设置回退队列和阀值,如设置队列为q1,阀值为2,则在rollback两次后将消息转入q1)
综上,手动ack需要注意的是:
1.在消费者端一定要进行ack,或者是nack,可以放在try方法块的finally中执行
2.可以对消费者的异常状态进行捕捉,根据异常类型选择ack,或者nack抛弃消息,nack再次尝试
3.对于nack的再次尝试,是进入到队列头的,如果一直是失败的状态,将会造成阻塞。所以最好是专门投递到“死信队列”,
【When a message is requeued, it will be placed to its original position in its queue, if possible. If not (due to concurrent deliveries and acknowledgements from other consumers when multiple consumers share a queue), the message will be requeued to a position closer to queue head.】
————————————————
原文链接:https://blog.csdn.net/vtopqx/article/details/104019115
消息队列手动确认Ack的更多相关文章
- SpringBoot集成RabbitMQ消息队列搭建与ACK消息确认入门
1.RabbitMQ介绍 RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.Rabbi ...
- Python消息队列(RabbitMQ)
RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用.可维护多个队列,可实现消息的一对一和广播等方式发送 RabbitMQ是一个开源的AMQP实现 ...
- 消息队列的使用<一>:介绍、使用场景和JMS概念知识
目录 介绍 消息队列的理解 举个栗子 使用场景 消息队列的模型与概念理解 JMS模型 基本概念: 内容: JMS定义的消息结构: PTP式消息传递 PUB/SUB式消息传递 可靠性机制 事务 消息持久 ...
- 流处理与消息队列------《Designing Data-Intensive Applications》读书笔记16
上一篇聊了聊批处理的缺点,对于无界数据来说,流处理会是更好的选择,"流"指的是随着时间的推移逐步增加的数据.消息队列可以将这些流组织起来,快速的在应用程序中给予反馈.但是消息队列与 ...
- RabbitMQ消息队列(六)-消息任务分发与消息ACK确认机制(.Net Core版)
在前面一章介绍了在.Net Core中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消费者消费同一个队列怎么办?如果这几个消费者分任务的权重不同怎么办?怎么把 ...
- (六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版)
原文:(六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版) 在前面一章介绍了在PHP中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消 ...
- 使用rabbitmq手动确认消息的,定时获取队列消息实现
描述问题 最近项目中因为有些数据,需要推送到第三方系统中,因为数据会一直增加,并且需要与第三方系统做相关交互. 相关业务 本着不影响线上运行效率的思想,我们将增加的消息放入rabbitmq,使用另一个 ...
- RabbitMQ的消息确认ACK机制
1.什么是消息确认ACK. 答:如果在处理消息的过程中,消费者的服务器在处理消息的时候出现异常,那么可能这条正在处理的消息就没有完成消息消费,数据就会丢失.为了确保数据不会丢失,RabbitMQ支持消 ...
- rabbitmq监控之消息确认ack
rabbitmq springboot ack 监控 一.测试环境 二.启动测试 一直以来,学习rabbitmq都是跟着各种各样的教程.博客.视频和文档,撸起袖子就是干!!!最后,也成功了. 当然,成 ...
随机推荐
- Python项目生成requirements.txt文件之pipreqs的使用
生成requirements.txt时使用pip freeze > requirements.txt会将环境下所有的安装包都进行生成,再进行安装的时候会全部安装很多没有的包.耗时耗力其实是不可取 ...
- GKCTF 2021 Reverse Writeup
前言 GKCTF 2021所以题目均以开源,下面所说的一切思路可以自行通过源码对比IDA进行验证. Github项目地址:https://github.com/w4nd3r-0/GKCTF2021 出 ...
- Redux使用指南
Redux使用指南 00-简介 本文主要是用来记录Redux结合React的使用过程,帮助大家在使用Redux的时候,能够更好的理解Redux,从而更好地使用它 01-为什么需要Redux JavaS ...
- 聊聊我对 GraphQL 的一些认知
每隔一段时间就能看到一篇 GraphQL 的文章,但是打开文章一看,基本上就是简单的介绍下 GraphQL 的特性.很多文章其实就是 github 上找个 GraphQL 的项目,然后按照对应的 de ...
- JVM堆内存泄露分析
一.背景 公司有一个中间的系统A可以对接多个后端业务系统B,一个业务系统以一个Namespace代表, Namespace中包含多个FrameChannel(用holder保存),表示A连接到业务 ...
- 为什么下一个十年的主战场在 Serverless?
作者 | 不瞋 阿里云 Serverless 负责人 "唯有超越,才能让我们走下去." 这是不瞋在阿里的第十年.从 2010 年加入阿里云,不瞋参与了阿里云飞天分布式系统的研发,历 ...
- The Data Way Vol.4|开源是创造软件诸多方法中最好的一种形式
关于「The Data Way」 「The Data Way」是由 SphereEx 公司出品的一档播客节目.这里有开源.数据.技术的故事,同时我们关注开发者的工作日常,也讨论开发者的生活日常:我们聚 ...
- Apache ShardingSphere 元数据加载剖析
唐国城 小米软件工程师,主要负责 MIUI 浏览器服务端研发工作.热爱开源,热爱技术,喜欢探索,热衷于研究学习各种开源中间件,很高兴能参与到 ShardingSphere 社区建设中,希望在社区中努力 ...
- Apache Dubbo理解和应用
官网:https://dubbo.apache.org/ slogan:高性能.轻量级的开源Java RPC框架 提供了六大核心能力:面向接口代理的高性能RPC调用,智能容错和负载均衡,服务自动注册和 ...
- Java(23)常用API二
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228415.html 博客主页:https://www.cnblogs.com/testero ...