本文环境:springboot 1.5.8.RELEASE + amqp-client 4.0.3.jar

记一个很神奇的bug。

场景:开启生产者确认模式,指定了自定义ConfirmCallback实现类。

尝试投递到不存在的exchange,成功回调confim接口,随后再次重发该信息。

但意外的是,不止没有回调confirm接口。还导致整个rabbitMQ卡死,发送消息到其他交换机一样无作用。

原因:

上述操作:“尝试投递到不存在的exchange”,会产生一个ERROR:

ERROR org.springframework.amqp.rabbit.connection.CachingConnectionFactory - Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'noexist' in vhost '/', class-id=60, method-id=40)

这个error,不管是否开启了生产者确认模式,都是会触发的。

但在实现了生产者确认模式后,会在confirm接口回调完毕之后再触发

但因为在confirm回调中,又进行了重发消息的操作。

这样就形成了一个死循环:

  • confirm不完成,error就不触发
  • error不触发,RabbitMQ就不能提供服务
  • RabbitMQ不提供服务,重发消息就无法完成,阻塞在那里
  • 重发消息不完成,confirm就不能完成

禁止套娃

因此即使是发送到其他存在的交换机的信息,也会因为RabbitMQ无法提供服务,而阻塞。

但需要注意的是,其他任务是可以正常进行的(CPU没资源之类的除外)。辅助跑了个定时任务,是可以正常输出的。


解决办法:
很简单。就是不要在confirm里面重新发送,交给延迟队列或者定时任务完成,就解决了


直观的感受一下:

代码:

rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {System.out.println("---------触发confirm-----------");mqSender.reSendMiaoshaMessage(miaoshaMessage, System.out.println("----------confirm触发完成----------");}});
public void reSendMiaoshaMessage(MiaoshaMessage mm,CorrelationData correlationData) {System.out.println("重发消息");String msg = RedisService.beanToString(mm);rabbitTemplate.convertAndSend("notExist", MQConfig.MIAOSHA_ROUTING_KEY, msg, correlationData);System.out.println("重发消息完成");}

控制台输出:


这么神奇的bug,估计没几个人遇到,所以网上找过一轮都没有蛛丝马迹。

mark一下,能遇上这个bug的,感觉都是有缘人……


本文完,有误欢迎指出

RabbitMQ---重新投递到不存在的exchange 导致MQ无法提供服务相关推荐

  1. rabbitmq可靠性投递_解决RabbitMQ消息丢失问题和保证消息可靠性(一)

    工作中经常用到消息中间件来解决系统间的解耦问题或者高并发消峰问题,但是消息的可靠性如何保证一直是个很大的问题,什么情况下消息就不见了?如何防止消息丢失?下面通过这篇文章,我们就聊聊RabbitMQ 消 ...

  2. RabbitMq系列(九):主题交换Topic Exchange

    系列文章 RabbitMq系列(一):服务器搭建 RabbitMq系列(二):最简单的例子 RabbitMq系列(三):工作队列 RabbitMq系列(四):消息确认和持久性 RabbitMq系列(五 ...

  3. rabbitmq怎样确认是否已经消费了消息_阿里Java研发二面:了解RabbitMQ?说说RabbitMQ可靠性投递...

    上期写到高并发下RabbitMq消息中间件你应该介么玩今天给小伙伴说说!有自己看法的也可以在评论区留言探讨,也可以转发关注下我以后会长期分享! 目录: 确保消息发送到RabbitMQ服务器 确保消息被 ...

  4. rabbitmq可靠性投递_阿里Java研发二面:了解RabbitMQ?说说RabbitMQ可靠性投递

    上期写到高并发下RabbitMq消息中间件你应该介么玩今天给小伙伴说说!有自己看法的也可以在评论区留言探讨,也可以转发关注下我以后会长期分享! 目录:确保消息发送到RabbitMQ服务器 确保消息被正 ...

  5. rabbitmq可靠性投递_RabbitMQ 可靠投递

    背景 - confirmCallback 确认模式 - returnCallback 未投递到 queue 退回模式 - shovel-plugin 跨机房可靠投递 背景 在使用 RabbitMQ 的 ...

  6. rabbitmq可靠性投递_RabbitMQ可靠性

    添加 amqp 依赖 配置文件 application.properties 生产者 消费者 可以直接使用@RabbitListener注解,声明Queue和Exchange以及Binding关系.消 ...

  7. RabbitMQ可靠性投递与高可用架构

    一,可靠性投递 使用 RabbitMQ 实现异步通信的时候,消息丢了怎么办,消息重复消费怎么办? 在 RabbitMQ 里面提供了很多保证消息可靠投递的机制,这个也是 RabbitMQ 的一个特性. ...

  8. RabbitMQ第二话 -- Springboot基于四种Exchange(Direct、Fanout、Topic、Heders、延时队列)的实现和多虚拟主机下的生产消费者实现

    本文主要分享RabbitMQ exchange类型的功能和使用.RabbitMQ延时队列.一个springboot服务发送消息到多虚拟主机 1.RabbitMQ exchange exchange交换 ...

  9. rabbitmq消费端auto和manual区别;处理mq的requeue

    概述 auto和manual区别其实就如字面意思一般,auto代表自动确认消息,只要消费者的方法执行完了,就自动告诉mq当前消息确认.manual则是需要手动通知mq.不需要想的很复杂就是这么直接. ...

最新文章

  1. 关于rtsp的时间戳问题
  2. 堆晶结构_橄榄岩的特殊问题
  3. Java进阶:ReentrantLock实现原理解析(公平锁、非公平锁、可重入锁、自旋锁)
  4. CDQ 分治算法模板
  5. 汉诺塔V - ACM解决方法
  6. 【转载保存】java牛逼的开源项目汇总
  7. dataAdapter与dataSet和dataTable的填充
  8. SwipeListView 详解 实现微信,QQ等滑动删除效果
  9. 怎样复制百度文库中的内容?
  10. html5验证码制作,Html5生成验证码的示例代码
  11. 使用 Git 管理 Vim 插件
  12. MyScript ---LateX公式编辑排版
  13. 一元二次方程解法最新研究成果,秒算任何方程
  14. 概率论中PDF、PMF和CDF的区别与联系
  15. 显著性检测学习笔记(2):DMRA__2019_ICCV
  16. 【云速建站】微信公众平台中维护IP白名单
  17. Android开发,你所不知道的Android原生开发的现状
  18. 探秘app.asar
  19. 对学校的希望和寄语_给学校的祝福语
  20. 搭建SpringBoot+Vue 项目 完整流程

热门文章

  1. java到底能用来干什么?我来实事求是告诉你
  2. 重庆首家订餐网倒闭内幕(图)
  3. Idea常用插件整合
  4. 无法加载文件 D:\xxx\xxx\xxx\activate.ps1,因为在此系统上禁止运行脚本
  5. 2022-2028全球与中国经颅磁刺激线圈市场现状及未来发展趋势
  6. CentOS 安装多种解码器打造Linux的全能播放器
  7. 企业微信中如何开启远程协助
  8. Unique Snowflakes(2021-TRN1-M)
  9. 资源 | Python数据分析课程:从入门到实战
  10. 毫米波雷达与激光雷达两种类别的雷达技术究竟有什么区别?