当前位置: 首页 > news >正文

rabbitmq学习笔记 ----- 多级消息延迟始终为 20s 问题排查

问题现象

在实现多级延迟消息功能时,发现每次消息延迟间隔始终为20s,无法按照预期依次使用20s→10s→5s的延迟时间。日志显示每次处理时移除的延迟时间都是20000L。

问题代码片段

1.生产者

@Testvoid sendDelayMessage2() {List<Long> expireTimeList = new ArrayList<>();{expireTimeList.add(20000L);expireTimeList.add(10000L);expireTimeList.add(5000L);}delayMessage<String> msg = new delayMessage<>("hello,world222!", expireTimeList);rabbitTemplate.convertAndSend("delay.exchange", "hi",msg, message -> {message.getMessageProperties().setDelay(msg.removeDelayTime().intValue());return message;});}

2.消费者

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "delay.queue", durable = "true"),exchange = @Exchange(value = "delay.exchange", delayed = "true"),key = "hi"))public void listenMultiDelay(delayMessage<String> msg) {log.info("收到消息: {}" , msg.getMessage());if(msg.hasExpireTime()){log.info("消息还有延迟时间,继续投递,剩余延迟时间:" );rabbitTemplate.convertAndSend("delay.exchange", "hi",msg, message -> {message.getMessageProperties().setDelay(msg.removeDelayTime().intValue());return message;});}}

3.延迟消息类

@Data
public class delayMessage<T> {private T message;private List<Long> expireTime;public delayMessage() {}public delayMessage(T message, List<Long> expireTime) {this.message = message;this.expireTime = expireTime;}public Long removeDelayTime(){System.out.println("removeDelayTime: "+expireTime.get(0));return expireTime.remove(0);}public boolean hasExpireTime(){return !expireTime.isEmpty();}}

4.启动配置

    @Beanpublic MessageConverter messageConverter() {return new Jackson2JsonMessageConverter();}

核心原因分析

问题根源Jackson2JsonMessageConverter的序列化特性与业务逻辑设计之间的冲突有关:

  • Jackson2JsonMessageConverter工作机制

    • 发送消息时,将对象序列化为JSON字符串(数据快照)
    • 接收消息时,将JSON字符串重新反序列化为全新的对象实例,而非复用原对象
  • 对delayMessage对象的影响

    • 发送端调用removeDelayTime()后,内存中对象的expireTime列表已变为[10000L, 5000L]
    • 但序列化保存的是操作前的状态快照(包含20000L的完整列表)
    • 消费者接收时,反序列化创建的是新对象,expireTime列表恢复为初始状态[20000L, 10000L, 5000L]
    • 导致每次处理都从20000L开始,形成无限循环
  • 总结:说人话就是 Jackson2JsonMessageConverter 将消息转换成json格式前,delayMessage中的expireTime还没有收到removeDelayTime()的影响而改变

解决方案: 先改对象,再序列化

修正后代码:生产者(消费者同理)

    @Testvoid sendDelayMessage2() {List<Long> expireTimeList = new ArrayList<>();{expireTimeList.add(20000L);expireTimeList.add(10000L);expireTimeList.add(5000L);}delayMessage<String> msg = new delayMessage<>("hello,world222!",expireTimeList);// 先进行延迟时间的更新Long delaytime = msg.removeDelayTime();rabbitTemplate.convertAndSend("delay.exchange", "hi",msg, message -> {message.getMessageProperties().setDelay(delaytime.intValue());return message;});}

通过以上调整,多级延迟消息可按预期依次使用20s→10s→5s的延迟时间,最终解决了始终20s延迟的问题。

http://www.dtcms.com/a/356251.html

相关文章:

  • OpenCV 图像预处理核心技术:阈值处理与滤波去噪
  • LubanCat-RK3568 UART串口通信,以及遇到bug笔记
  • CRYPT32!CryptMsgUpdate函数分析和asn.1 editor nt5inf.cat 的总览信息
  • 第八篇 永磁同步电机控制-MTPA、MTPV
  • 深入解析Qt节点编辑器框架:数据流转与扩展机制(三)
  • 实时音视频延迟优化指南:从原理到实践
  • 零知开源——基于STM32F407VET6和ADXL345三轴加速度计的精准运动姿态检测系统
  • Blender模拟结构光3D Scanner(三)获取相机观测点云的真值
  • OpenCV 基础知识总结
  • 无懈可击的 TCP AIMD
  • 亚马逊季节性产品运营策略:从传统到智能化的演进
  • kimi浏览器助手-月之暗面推出的智能浏览器扩展
  • docker中的mysql有中文显示问题跟大小写区分问题?
  • Python从入门到高手9.4节-基于字典树的敏感词识别算法
  • 使用Python脚本执行Git命令
  • React 状态丢失:组件 key 用错引发的渲染异常
  • Rust 安装与运行指南
  • Custom SRP - LOD and Reflections
  • 柳州市委常委、统战部部长,副市长潘展东率队首访深兰科技集团新总部,共探 AI 赋能制造大市与东盟合作新局
  • Claude Code 完整手册:从入门、配置到高级自动化
  • 【python】相机输出图片时保留时间戳数据
  • Linux学习——sqlite3
  • 179-183动画
  • IntelliJ IDEA2025+启动项目提示 Failed to instantiate SLF4J LoggerFactory
  • 零基础json入门教程(基于vscode的json配置文件)
  • 【贪心算法】day4
  • HTML 核心标签全解析:从文本排版到媒体嵌入
  • 联想打印机2268w安装
  • 根据并发和响应延迟,实现语音识别接口自动切换需求
  • IP v 6