以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的更多相关文章

  1. SpringBoot集成RabbitMQ消息队列搭建与ACK消息确认入门

    1.RabbitMQ介绍 RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.Rabbi ...

  2. Python消息队列(RabbitMQ)

    RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用.可维护多个队列,可实现消息的一对一和广播等方式发送 RabbitMQ是一个开源的AMQP实现 ...

  3. 消息队列的使用<一>:介绍、使用场景和JMS概念知识

    目录 介绍 消息队列的理解 举个栗子 使用场景 消息队列的模型与概念理解 JMS模型 基本概念: 内容: JMS定义的消息结构: PTP式消息传递 PUB/SUB式消息传递 可靠性机制 事务 消息持久 ...

  4. 流处理与消息队列------《Designing Data-Intensive Applications》读书笔记16

    上一篇聊了聊批处理的缺点,对于无界数据来说,流处理会是更好的选择,"流"指的是随着时间的推移逐步增加的数据.消息队列可以将这些流组织起来,快速的在应用程序中给予反馈.但是消息队列与 ...

  5. RabbitMQ消息队列(六)-消息任务分发与消息ACK确认机制(.Net Core版)

    在前面一章介绍了在.Net Core中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消费者消费同一个队列怎么办?如果这几个消费者分任务的权重不同怎么办?怎么把 ...

  6. (六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版)

    原文:(六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版) 在前面一章介绍了在PHP中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消 ...

  7. 使用rabbitmq手动确认消息的,定时获取队列消息实现

    描述问题 最近项目中因为有些数据,需要推送到第三方系统中,因为数据会一直增加,并且需要与第三方系统做相关交互. 相关业务 本着不影响线上运行效率的思想,我们将增加的消息放入rabbitmq,使用另一个 ...

  8. RabbitMQ的消息确认ACK机制

    1.什么是消息确认ACK. 答:如果在处理消息的过程中,消费者的服务器在处理消息的时候出现异常,那么可能这条正在处理的消息就没有完成消息消费,数据就会丢失.为了确保数据不会丢失,RabbitMQ支持消 ...

  9. rabbitmq监控之消息确认ack

    rabbitmq springboot ack 监控 一.测试环境 二.启动测试 一直以来,学习rabbitmq都是跟着各种各样的教程.博客.视频和文档,撸起袖子就是干!!!最后,也成功了. 当然,成 ...

随机推荐

  1. P4258-[WC2016]挑战NPC【带花树】

    正题 题目链接:https://www.luogu.com.cn/problem/P4258 题目大意 给出\(n\)个球,\(m\)个篮筐,每个球都可以被放入一些特定的篮筐,每个球都要放,要求球的个 ...

  2. Redis 高可用篇:你管这叫主从架构数据同步原理?

    在<Redis 核心篇:唯快不破的秘密>中,「码哥」揭秘了 Redis 五大数据类型底层的数据结构.IO 模型.线程模型.渐进式 rehash 掌握了 Redis 快的本质原因. 接着,在 ...

  3. mybatis本地缓存&分布式缓存干货分享

    前言:干货记录学习mybatis实际开发中缓存的使用. 环境: springboot2.X + mybatis3.x Mybatis是一款持久层框架,它提供了一级缓存和二级缓存. 名词解释 一级缓存( ...

  4. iOS 15 无法弹出授权弹框之解决方案---Your app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request when reviewed on iOS 15.0

    2021年9月30日下午:我正愉快的期盼着即将到来的国庆假期,时不时刷新下appstoreconnect的网址,28号就提上去的包,今天还在审核中....由于这个版本刚升级的xcode系统和新出的iO ...

  5. vue+element实现省区市三级联动以及详细地址的输入

    Vue+elementui实现省区市三级联动+详细地址的输入 详细需求,需要手动更改用户所在的地址. 安装依赖项 npm install element-china-area-data -S 在组建中 ...

  6. VMware vSphere 7 Update 3 下载

    请访问原文链接:https://sysin.org/blog/vmware-vsphere-7-u3/,查看最新版.原创作品,转载请保留出处. vSphere 7 Update 3 已经宣布可用,即将 ...

  7. RabbitMQ的消息可靠性(五)

    一.可靠性问题分析 消息的可靠性投递是使用消息中间件不可避免的问题,不管是使用哪种MQ都存在这种问题,接下来要说的就是在RabbitMQ中如何解决可靠性问题:在前面 在前面说过消息的传递过程中有三个对 ...

  8. 洛谷4219 BJOI2014大融合(LCT维护子树信息)

    QWQ 这个题目是LCT维护子树信息的经典应用 根据题目信息来看,对于一个这条边的两个端点各自的\(size\)乘起来,不过这个应该算呢? 我们可以考虑在LCT上多维护一个\(xv[i]\)表示\(i ...

  9. SPOJ2939 QTREE5(LCT维护子树信息)

    QWQ嘤嘤嘤 此题正规题解应该是边分治??或者是树剖(总之不是LCT) 但是我这里还是把它当成一个LCT题目来做 首先,这个题的重点还是在update上 因为有\(makeroot\)这个操作的存在, ...

  10. javascript-jquery的ajax

    用一个例子来说明: html部分  <form action="name1"> <input class="class1" type=&quo ...