rabbit mq 手动重试机制
消息手动确认模式的几点说明
监听的方法内部必须使用channel进行消息确认,包括消费成功或消费失败
如果不手动确认,也不抛出异常,消息不会自动重新推送(包括其他消费者),因为对于rabbitmq来说始终没有接收到消息消费是否成功的确认,并且Channel是在消费端有缓存的,没有断开连接
如果rabbitmq断开,连接后会自动重新推送(不管是网络问题还是宕机)
如果消费端应用重启,消息会自动重新推送
如果消费端处理消息的时候宕机,消息会自动推给其他的消费者
如果监听消息的方法抛出异常,消息会按照listener.retry的配置进行重发,但是重发次数完了之后还抛出异常的话,消息不会重发(也不会重发到其他消费者),只有应用重启后会重新推送。因为retry是消费端内部处理的,包括异常也是内部处理,对于rabbitmq是不知道的(此场景解决方案后面有)
spring.rabbitmq.listener.retry配置的重发是在消费端应用内处理的,不是rabbitqq重发
可以配置MessageRecoverer对异常消息进行处理,此处理会在listener.retry次数尝试完并还是抛出异常的情况下才会调用,默认有两个实现:
- RepublishMessageRecoverer:将消息重新发送到指定队列,需手动配置,如:
- @Bean
- public MessageRecoverer messageRecoverer(RabbitTemplate rabbitTemplate){
- return new RepublishMessageRecoverer(rabbitTemplate, "exchangemsxferror", "routingkeymsxferror");
- }
- RejectAndDontRequeueRecoverer:如果不手动配置MessageRecoverer,会默认使用这个,实现仅仅是将异常打印抛出,源码如下:
- public class RejectAndDontRequeueRecoverer implements MessageRecoverer {
- protected Log logger = LogFactory.getLog(RejectAndDontRequeueRecoverer.class);
- @Override
- public void recover(Message message, Throwable cause) {
- if (this.logger.isWarnEnabled()) {
- this.logger.warn("Retries exhausted for message " + message, cause);
- }
- throw new ListenerExecutionFailedException("Retry Policy Exhausted", new AmqpRejectAndDontRequeueException(cause), message);
- }
- }
可以通过给队列(Queue)绑定死信队列,使用nack反馈给mq,会将消息转发到死信队列里面,此种方式需要自己在消费消息的方法内部将异常处理掉
- //声明队列,并给队列增加x-dead-letter-exchange和x-dead-letter-routing-key参数,用于指定死信队列的路由和routingKey
- @Bean
- public Queue queue(){
- Map<String, Object> args = new HashMap<String, Object>();
- args.put("x-dead-letter-exchange",IntegralConstant.DEAD_EXCHANGE_NAME);
- args.put("x-dead-letter-routing-key",IntegralConstant.DEAD_ROUTING_KEY);
- return new Queue(IntegralConstant.QUEUE_NAME, true, false, false, args);
- }
- //消息确认时使用nack,并且requeue参数传false
- channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
- 消息变成死信有以下几种情况:
- 消息被拒绝(basic.reject/ basic.nack)并且requeue=false
- 消息TTL过期(参考:RabbitMQ之TTL(Time-To-Live 过期时间))
- 队列达到最大长度
总结
- 消息监听内必须使用channel对消息进行确认,不管是确认消费成功还是确认消费失败
- 消息监听内的异常处理有两种方式:
- 内部catch后直接处理,然后使用channel对消息进行确认
- 配置RepublishMessageRecoverer将处理异常的消息发送到指定队列专门处理或记录
- 监听的方法内抛出异常貌似没有太大用处。因为抛出异常就算是重试也非常有可能会继续出现异常,当重试次数完了之后消息就只有重启应用才能接收到了,很有可能导致消息消费不及时。当然可以配置RepublishMessageRecoverer来解决,但是万一RepublishMessageRecoverer发送失败了呢。。那就可能造成消息消费不及时了。所以即使需要将处理出现异常的消息统一放到另外队列去处理,个人建议两种方式:
- catch异常后,手动发送到指定队列,然后使用channel给rabbitmq确认消息已消费
- 给Queue绑定死信队列,使用nack(requque为false)确认消息消费失败
rabbit mq 手动重试机制的更多相关文章
- Rabbit MQ 消息确认和持久化机制
一:确认种类 RabbitMQ的消息确认有两种.一种是消息发送确认,用来确认生产者将消息发送给交换器,交换器传递给队列的过程中消息是否成功投递.发送确认分为两步,一是确认是否到达交换器,二是确认是否到 ...
- RabbitMq手动确认时的重试机制
本文转载自RabbitMq手动确认时的重试机制 消息手动确认模式的几点说明 监听的方法内部必须使用channel进行消息确认,包括消费成功或消费失败 如果不手动确认,也不抛出异常,消息不会自动重新推送 ...
- 分布式消息中间件Rabbit Mq的了解与使用
MQ(消息队列)作为现代比较流行的技术,在互联网应用平台中作为中间件,主要解决了应用解耦.异步通信.流量削锋.服务总线等问题,为实现高并发.高可用.高伸缩的企业应用提供了条件. 目前市面比较流行的消息 ...
- Rabbit MQ config文件解析
Rabbit MQ config文件解析 tcp_listeners:用于监听AMQP连接的端口或主机名/对(不带TLS),默认端口:5672 2.numtcpacceptors :将接受TCP侦听器 ...
- rabbit MQ 消息队列
为什么会需要消息队列(MQ)? 一.消息队列概述消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有 ...
- celery rabbit mq 详解
Celery介绍和基本使用 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, ...
- RocketMQ-消费重试机制
介绍: RocketMQ的消息重试及时分为两种,一种是Producer端重试,一种是Consume端重试. 1.Producer端重试 : 1.1消息发没发成功,默认情况下是3次重试. 2.Consu ...
- SpringCloud | FeignClient和Ribbon重试机制区别与联系
在spring cloud体系项目中,引入的重试机制保证了高可用的同时,也会带来一些其它的问题,如幂等操作或一些没必要的重试. 今天就来分别分析一下 FeignClient 和 Ribbon 重试机制 ...
- Rocket重试机制,消息模式,刷盘方式
一.Consumer 批量消费(推模式) 可以通过 consumer.setConsumeMessageBatchMaxSize(10);//每次拉取10条 这里需要分为2种情况 Consumer端先 ...
随机推荐
- autojump 之 git本地安装
1.克隆autojump的repo,Terminal下执行: git clone git://github.com/joelthelion/autojump.git 然后进入c ...
- JavaWeb学习——了解Servlet
JavaWeb学习——了解Servlet 摘要:本文主要学习了什么是Servlet,以及如何使用Servlet进行开发. 基础知识 背景 随着互联网技术的发展,基于HTTP和HTML的web应用急速增 ...
- go笔记--json包使用
目录 Marshal Unmarshal 处理json对象 @ json包实现了json对象的编解码,参见RFC 4627.Json对象和go类型的映射关系主要通过Marshal和Unmarshal函 ...
- golang协程同步的几种方法
目录 golang协程同步的几种方法 协程概念简要理解 为什么要做同步 协程的几种同步方法 Mutex channel WaitGroup golang协程同步的几种方法 本文简要介绍下go中协程的几 ...
- vue2y引入iview,在ie11报错的解决办法
在ie11中打开vue项目一片空白,F12打开控制台发现如下错误 只需要在build/webpack.base.conf.js中加一行代码即可
- Burp Suite渗透操作指南 【暴力破解】
1.1 Intruder高效暴力破解 其实更喜欢称Intruder爆破为Fuzzing.Intruder支持多种爆破模式.分别是:单一字典爆破.多字段相同字典爆破.多字典意义对应爆破.聚合式爆破.最常 ...
- About learn《The C programming Language,Second Edition》
Today,My last week buy C language book arrived. Today,I week earnest study. No matter what difficult ...
- Goland快捷键(Macbook)
Goland快捷键(Macbook) 基础编辑快键键 向上或向下移动当前行 ⇧⌘↑ ⇧⌘↓ 复制并粘贴当前选中的语句 ⌘D 删除当前行 ⌘⌫ 行注释 ⌘/ 块注释 ⌥⌘/ 在当前打开的文件中寻找 ⌘F ...
- 一条简单的更新语句,MySQL是如何加锁的?
看如下一条sql语句: # table T (id )) delete : MySQL在执行的过程中,是如何加锁呢? 在看下面这条语句: : 那这条语句呢?其实这其中包含太多知识点了.要回答这两个问题 ...
- 生产环境Shell脚本Ping监控主机是否存活(多种方法)
在网上针对shell脚本ping监控主机是否存活的文档很多,但大多都是ping一次就决定了状态,误报率会很高,为了精确判断,ping三次不通再发告警,只要一次ping通则正常.于是,今天中午抽出点时间 ...