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

面试题:Rabbitmq怎么保证消息的可靠性?

1.消费端消息可靠性保证

消息确认(Acknowledgements):(自动(默认),手动)

消费者在接收到消息后,默认情况下RabbitMQ会自动确认消息(autoAck=true)。为保证消息可靠性,可以设置autoAck=false,使得消费者在处理完消息后手动发送确认(basicAck)。如果消费者在处理过程中发生异常或者未完成处理就终止运行,那么消息在超时时间内将不会被删除,会再次被RabbitMQ投递给其他消费者。缺点:代码冗余多,容易出现死循环。

死信队列(Dead Letter Queue)

当消息不能被正常消费时(比如达到最大重试次数),可以通过设置TTL(Time To Live)或者死信交换器(Dead Letter Exchange)将消息路由至死信队列,从而有机会后续分析和处理这些无法正常消费的消息。(人工干预)

2.生产端消息可靠性保证:

  1. 消息持久化

当生产者发布消息时,可以选择将其标记为持久化(persistent).这意味着即使 RabbitMQ 服务器重启,消息也不会丢失,因为它们会被存储在磁盘上。(默认就是这)

2.确认(Confirm)机制:(发布者确认(Publisher Confirms)

开启confirm回调模式后,RabbitMQ会在消息成功写入到磁盘并至少被一个交换器接受后,向生产者发送一个确认(acknowledgement)。若消息丢失或无法投递给任何队列,RabbitMQ将会发送一个否定确认(nack). 生产者可以根据这些确认信号判断消息是否成功送达并采取相应的重试策略。

RabbitMQ作为消息中间件并启用publisher confirms(发布者确认)publisher returns(发布者退回)机制时,可以确保消息从生产者到交换机的投递过程得到更准确的状态反馈。

发布者确认-Publisher Confirms

作用: Publisher Confirm机制允许RabbitMQ服务器通知生产者一个消息是否已经被交换机正确接收。当publisher-confirm-type设置为CORRELATED时,RabbitMQ会向生产者发送确认或否定响应,确认消息已到达交换机,但不保证消息已被路由到至少一个队列中。

2.1.配置:

spring.rabbitmq.publisher-confirm-type = CORRELATED

setConfirmCallback:

 (写到交换机,b为true.没写到交换机b为false)

发布者退回-Publisher Returns

作用: Publisher Return机制用于当消息无法按照路由键规则路由到任何队列时,或者由于其他原因(例如队列满、消息过大等)而被交换机拒绝时,RabbitMQ将消息返回给生产者。

交换机到队列的确认(消息是否正常发送到了其中任何一个队列)

通过实现 ReturnCallback 接口,发送消息失败返回,比如交换机路由不到队列时触发回调:

1.只有消息没有路由到队列的时候,才触发该回调 .

2.只要有一个队列接受到消息了,它就认为成功.

 配置

spring.rabbitmq.publisher-returns = true

returnedMessage:

(这是找到交换机了,但是路由错了,没有找到对列;这在直连交换机能测出来,广播交换机没路由,只要有绑定的队列就能发送成功)

完整代码

@Service
@Slf4j
public class ConfirmProvider {@Autowiredprivate RabbitTemplate rabbitTemplate;public void send(OrderingOk msg) {rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {@Overridepublic void confirm(CorrelationData correlationData, boolean b, String s) {//没找到交换机就会falseif (b){String id = correlationData.getId();log.info("消息发送成功");}else {log.info("消息发送失败");}}});rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {@Overridepublic void returnedMessage(Message message, int i, String s, String s1, String s2) {log.info("消息发送失败");log.info("消息主体: {}", message);log.info("应答码: {}", i);log.info("描述:{}", s);log.info("消息使用的交换器 exchange : {}", s1);log.info("消息使用的路由键 routing : {}", s2);}});CorrelationData correlationData = new CorrelationData("980520");rabbitTemplate.convertAndSend("d_ex01", "erew", msg, correlationData);}
}

代码模版:

public void send(OrderingOk msg){// 设置确认回调rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {/*** 确认消息是否被交换机接收。** @param correlationData 包含消息相关数据的对象,用于识别消息的唯一性。* @param ack 表示消息是否被交换机确认接收。* @param cause 如果消息未被接收,提供未接收的原因。*/@Override //线程Bpublic void confirm(CorrelationData correlationData, boolean ack, String cause) {if(ack){//该订单状态  10 -> 20String id = correlationData.getId();// 通过这个id改订单状态} else {log.error("{]",cause);}}});// 设置退回回调, 之后投递失败的时候才会触发rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {/*** 记录被交换机退回的消息信息。** @param message 消息对象,包含消息体。* @param replyCode 返回的响应代码,用于指示退回的原因。* @param replyText 返回的响应文本,提供关于退回的详细信息。* @param exchange 退回时涉及的交换机名称。* @param routingKey 退回时使用的路由键。*/@Overridepublic void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {System.out.println("Message was returned: " + new String(message.getBody()));System.out.println("Reply code: " + replyCode);System.out.println("Reply text: " + replyText);System.out.println("Exchange: " + exchange);System.out.println("Routing key: " + routingKey);}});//CorrelationData 创建一个关联数据,用于消息的跟踪,大部分都是业务单据的idCorrelationData correlationData = new CorrelationData("201408145676676");rabbitTemplate.convertAndSend("ordering_ok","",msg,correlationData);}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 电脑桌面管理如何做?2024电脑桌面终极管理方法分享
  • 【安全靶场】-DC-5
  • 『基础』OS-1计算机系统概述_操作系统发展历程及它的运行环境
  • 机器人蓝牙通信绕坑
  • 【pip镜像设置】pip使用清华镜像源安装
  • <数据集>无人机航拍不同高度牧羊识别数据集<目标检测>
  • day06_算法训练
  • 星露谷模组开发教程#6 烹饪和制造配方
  • 免费高画质提取PPT/Word/Excel中的图片工具
  • 华为OD题目 csv格式的数据 字符串 用C没写出来
  • OS-Copilot:自学习的通用计算机智能体
  • day 10 贪心算法
  • 优化 WinForms 应用程序的 DataGridView 性能
  • 【三维重建】2D Gaussian Splatting:几何准确的2D辐射场(更新中)
  • RocketMQ源码分析 - 环境搭建
  • Bytom交易说明(账户管理模式)
  • Effective Java 笔记(一)
  • Java 23种设计模式 之单例模式 7种实现方式
  • Java 多线程编程之:notify 和 wait 用法
  • Java应用性能调优
  • jquery ajax学习笔记
  • js中的正则表达式入门
  • leetcode-27. Remove Element
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • mysql中InnoDB引擎中页的概念
  • PV统计优化设计
  • python3 使用 asyncio 代替线程
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • Rancher-k8s加速安装文档
  • Solarized Scheme
  • 聚簇索引和非聚簇索引
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 实习面试笔记
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 异步
  • ​Spring Boot 分片上传文件
  • "无招胜有招"nbsp;史上最全的互…
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • #HarmonyOS:Web组件的使用
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #php的pecl工具#
  • #控制台大学课堂点名问题_课堂随机点名
  • %check_box% in rails :coditions={:has_many , :through}
  • (C#)获取字符编码的类
  • (Charles)如何抓取手机http的报文
  • (层次遍历)104. 二叉树的最大深度
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (每日一问)设计模式:设计模式的原则与分类——如何提升代码质量?
  • (十)c52学习之旅-定时器实验
  • (图)IntelliTrace Tools 跟踪云端程序
  • (一)基于IDEA的JAVA基础10
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • ****三次握手和四次挥手
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .gitignore文件使用