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

RabbitMQ可靠传输——持久性、发送方确认

一、持久性

前面学习消息确认机制时,是为了保证Broker到消费者直接的可靠传输的,但是如果是Broker出现问题(如停止服务),如何保证消息可靠性?对此,RabbitMQ提供了持久化功能:

持久化分为三种:1. 交换机持久化   2. 队列持久化   3.消息持久化

1.1 交换机持久化

一、交换机持久化方法

声明交换机时,将durable置为true即可,如果不指定,默认为true

二、交换机持久化的作用

避免了当Broker重启时,未重新执行交换机声明代码,而导致生产者消息无法路由


1.2 队列持久化

一、队列持久化方法

在声明队列时,使用durable方法声明的队列为持久化队列,使用nonDurable声明的队列为非持久化队列

对应管理界面:

二、队列持久化的作用

在RabbitMQ服务器重启时,未持久化的队列将丢失,持久化队列保留


1.3 消息持久化

 一、消息持久化方法

前面在发送消息时,都是直接指定一个字符串来发送消息,如:


我们先进入convertAndSend方法,观察其源码:

接下来再进入MessageProperties,观察其源码:

可以看到,不指定消息是否持久化,默认为持久化

也就是说,如果要指定消息为非持久化,就选哟给convertAndSend传入一个Message对象而不是仅传一个消息字符串,接下来学习如何设置消息非持久化:

1> 创建一个Message对象

 Message message = new Message("persistent test...".getBytes(),new MessageProperties());

2> 获取MessageProperties对象,通过setDeliveryMode方法设置消息非持久化


/*
*如果要设置为持久化,可以直接换一个String的消息,也可以将这里的
*MessageDeliveryMode.NON_PERSISTENT改为MessageDeliveryMode.PERSISTENT
*/
message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);

3> 将Message对象作为参数传递给converAndSend方法

rabbitTemplate.convertAndSend(Constants.NO_PERSISTENT_EXCHANGE,"",message);

整体代码:

二、消息持久化作用

RabbitMQ服务器重启时,未持久化的消息将丢失即使消息所在队列未持久化队列),持久化的消息将保留前提是消息所在的队列是持久化队列

但是,有了消息确认机制以及持久性就能保证消息传输的可靠性了吗?显然不是,因为消息确认机制保证的是Broker到消费者的可靠性 ,持久性保证的是Broker内部的可靠性,还有生产者到Broker的可靠性没有被保证,因此,RabbitMQ引入了publiser confirms(发送方确认)机制


二、发送方确认机制

前面已经学习了RabbitMQ核心机制之一——持久化,但是这就能保证消息传输的可靠性了吗?显然不是,如果发送方发送的消息没有到达Broker,又谈何持久化?因此,我们还需要了解RabbitMQ的发送方确认机制(通过事务也能解决,但是比较复杂,这里不谈)

publisher confirms 机制又包含两种模式

1> confirm确认模式

2> return退回模式

2.1 confirm确认模式

一、触发机制

Producer向Broker发送消息时,需要设置一个ConfirmCallback监听,这样消息无论是否到达exchange,这个监听都会触发,如果消息到达exchange,ACK为true,如果没有到达exchange,ACK为false


二、代码演示

1> 添加RabbitMQ配置

publisher-confirm-type: correlated #配置publisher confirm机制

2> 代码实现(队列、交换机随便声明一个就行,类型随意)

    @RequestMapping("/confirm")public String confirm(){//设置回调方法rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {System.out.println("执行confirm方法");if(ack){//ack为true,消息到达exchangeSystem.out.printf("接收到消息,消息ID:%s \n",correlationData==null ? null : correlationData.getId());}else {//ack为false,消息为到达exchangeSystem.out.printf("未接收到消息,消息ID:%s , cause: %s \n",correlationData==null ? null : correlationData.getId(),cause);}}});CorrelationData correlationData = new CorrelationData("1");//发送消息rabbitTemplate.convertAndSend(Constants.CONFIRM_EXCHANGE,"confirm","confirm test...",correlationData);return "消息发送成功";}

3>运行程序,测试接口

    1.正确发送消息(交换机名、routingKey存在)

消息发送成功,接下来查看控制台信息:

可以看到,交换机成功接收到消息

  2.错误发送消息(改为一个不存在的交换机名)

再次运行程序,访问接口,发送消息:

消息发送成功,查看控制台:

可以看到,消息并没有到达指定交换机,原因是不存在这个交换机。

  3.错误发送消息(改为一个不存在的routingKey)

运行程序,测试接口:

消息发送成功,查看控制台:

可以看到,在routingKey不存在的情况下,消息还是到达了交换机,但是这个消息一定是无法路由到队列的,因此就需要通过publsher confirm的 return退回模式 来解决

4> 上述代码编写存在的问题

  上面我们设置了ConfirmCallback监听经过测试,似乎并没有问题,但是仔细思考就会发现,我们在上面的代码中是通过rabbitTemplate这个对象来设置的,那岂不是前面所有使用rabbitTemplate的接口都被设置了监听?访问其它接口也一样会打印回调方法中的信息?

下面我们测试一下下面的方法:

运行程序,测试接口:

消息发送成功,查看控制台:

可以看到,同样会触发监听,为了避免这个问题,我们可以在config包中自己配置一个RabbitTemplate对象并注入进来:

@Configuration
public class RabbitTemplateConfig {@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);return rabbitTemplate;}@Beanpublic RabbitTemplate confirmRabbitTemplate(ConnectionFactory connectionFactory){RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);//消息到达exchange时的回调方法rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {System.out.println("执行confirm方法");if(ack){//ack为true,表示消息到达交换机System.out.printf("接收到消息,消息ID:%s \n",correlationData==null ? null : correlationData.getId());}else{//ack为false,表示消息未到达交换机System.out.printf("未接收到消息,消息ID:%s , cause: %s \n",correlationData==null ? null : correlationData.getId(),cause);//业务逻辑,如重发等}}});//消息退回时的回调方法rabbitTemplate.setMandatory(true);rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {@Overridepublic void returnedMessage(ReturnedMessage returned) {System.out.println("消息退回: " + returned);}});return rabbitTemplate;}
}

2.2 return退回模式

 一、触发机制

当消息到达exchange后,需要路由到queue中,如果一条消息无法被任何queue消费(routingKey不存在或队列不存在),可以把消息退回给producer,退回时可以设置一个回调方法ReturnCallback,对消息进行处理


二、代码演示

   //消息退回时的回调方法rabbitTemplate.setMandatory(true);rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {@Overridepublic void returnedMessage(ReturnedMessage returned) {System.out.println("消息退回: " + returned);}});

修啊routingKey为一个不存在的routingKey:

运行程序,测试接口:

查看控制台:

可以看到,消息被退回


2.3 总结

publisher confirms 机制可以保证消息从生产者到Broker的可靠性,其中confirm模式工作在生产者到exchange之间,return模式工作在exchange到queue之间 

相关文章:

RabbitMQ可靠传输——持久性、发送方确认

一、持久性 前面学习消息确认机制时,是为了保证Broker到消费者直接的可靠传输的,但是如果是Broker出现问题(如停止服务),如何保证消息可靠性?对此,RabbitMQ提供了持久化功能: 持久…...

AWS stop/start 使实例存储lost + 注意点

先看一下官方的说明: EC2有一个特性,当执行stop/start操作(注意,这个并不是重启/reboot,而是先停止/stop,再启动/start)时,该EC2会迁移到其它的底层硬件上。 对于实例存储来说,由于实例存储是由其所在的底层硬件来提供的,此时相当于分配到了一块全新的空的磁盘。 但是从…...

数字计数--数位dp

1.不考虑前导零 2.每一位计数,就是有点“数页码”的意思 P2602 [ZJOI2010] 数字计数 - 洛谷 相关题目:记得加上前导零 数页码--数位dp-CSDN博客 https://blog.csdn.net/2301_80422662/article/details/148160086?spm1011.2124.3001.6209 #include…...

掌握递归:编程中的优雅艺术

当然可以!你愿意迈出学习递归的重要一步,真的很棒!🌟 递归,虽然一开始看着有点绕,但掌握之后,你会发现它是编程中非常优雅且强大的工具。 我用简单又清晰的方式教你。请跟着我一步步来&#xf…...

无人机开启未来配送新篇章

低空物流(无人机物流)是利用无人机等低空飞行器进行货物运输的物流方式,依托低空空域(通常在120-300米)实现快速、高效、灵活的配送服务。它是低空经济的重要组成部分,广泛应用于快递配送、医疗物资运输、农…...

el-input宽度自适应方法总结

使用 style 或 class 直接设置宽度 可以通过内联样式或 CSS 类来直接设置 el-input 的宽度为 100%&#xff0c;使其自适应父容器的宽度 <template><div style"width: 100%;"><el-input style"width: 100%;" v-model"input">…...

Qt状态机QStateMachine

QStateMachine QState 提供了一种强大且灵活的方式来表示状态机中的状态&#xff0c;通过与状态机类(QStateMachine)和转换类(QSignalTransition&#xff0c; QEventTransition)结合&#xff0c;可以实现复杂的状态逻辑和用户交互。合理使用嵌套状态机、信号转换、动作与动画、…...

驱动开发学习20250523

kobj_type 功能&#xff1a;表示内核对象类型&#xff0c;描述通过ktype字段嵌入kobject的对象类型&#xff0c;控制在创建和销毁kobject时以及在读取或写入属性时发生的操作。 struct kobj_type {void (*realease)(struct kobject *);const struct sysfs_ops sysfs_ops;stru…...

Java详解LeetCode 热题 100(20):LeetCode 48. 旋转图像(Rotate Image)详解

文章目录 1. 题目描述2. 理解题目3. 解法一&#xff1a;转置 翻转3.1 思路3.2 Java代码实现3.3 代码详解3.4 复杂度分析3.5 适用场景 4. 解法二&#xff1a;四点旋转法4.1 思路4.2 Java代码实现4.3 代码详解4.4 复杂度分析4.5 适用场景 5. 详细步骤分析与示例跟踪5.1 解法一&a…...

CAU人工智能class4 批次归一化

归一化 在对输入数据进行预处理时会用到归一化&#xff0c;将输入数据的范围收缩到0到1之间&#xff0c;这有利于避免纲量对模型训练产生的影响。 但当模型过深时会产生下述问题&#xff1a; 当一个学习系统的输入分布发生变化时&#xff0c;这种现象称之为“内部协变量偏移”…...

Android11以上通过adb复制文件到内置存储让文件管理器可见

之前Android版本如果需要将文件通过adb push放到内置存储&#xff0c;push到/data/media/10下的目录即可&#xff0c;直接放/sdcard/文件管理器是看不到的。 现在最新的Android版本直接将文件放在/sdcard或/data/media/10下文件管理器也看不到 可以将文件再复制一份到一下路径…...

Keepalived 与 LVS 集成及多实例配置详解

一、Keepalived 扩展功能&#xff1a;LVS 集成与多实例管理 1. Keepalived LVS&#xff1a;四层负载均衡高可用方案 1.1 集成原理与架构 核心逻辑&#xff1a;Keepalived 通过 VRRP 实现 LVS 负载均衡节点的高可用&#xff0c;同时利用 LVS 的 IP 负载均衡技术&#xff08;N…...

篇章二 需求分析(一)

目录 1.知名MQ 2.需求分析 2.1 核心概念 2.2 生产者消费者模型的类别 2.3 BrokerServer 内部的关键概念&#xff08;MQ&#xff09; 1.虚拟主机&#xff08;Virtual Host&#xff09; 2.交换机&#xff08;Exchange&#xff09; 3.队列&#xff08;Queue&#xff09; 4…...

汽车充电过程中--各个电压的关系(DeepSeek)

在电动汽车的充电过程中&#xff0c;电池的充电机制涉及多个电压参数的协调控制&#xff0c;以下从原理到实际应用逐步分析&#xff1a; 1. 充电基础原理 电动汽车电池&#xff08;通常为锂离子电池组&#xff09;的充电本质是通过外部电源向电池注入电能&#xff0c;使锂离子…...

图解深度学习 - 机器学习简史

前言 深度学习并非总是解决问题的最佳方案&#xff1a;缺乏足够数据时&#xff0c;深度学习难以施展&#xff1b;某些情况下&#xff0c;其他机器学习算法可能更为高效。 若初学者首次接触的是深度学习&#xff0c;可能会形成一种偏见&#xff0c;视所有机器学习问题为深度学…...

Gmsh 代码深度解析与应用实例

在科学计算与工程仿真领域&#xff0c;Gmsh 是一款广受欢迎的开源有限元网格生成器&#xff0c;它不仅支持复杂的几何建模&#xff0c;还能高效生成高质量的网格&#xff0c;并具备强大的后处理功能。本文将深入解析几段具有代表性的 Gmsh 代码&#xff0c;从基础几何创建到高级…...

49页 @《人工智能生命体 新启点》中國龍 原创连载

《 人工智能生命体 新启点 》一书&#xff0c;以建立意识来建立起生命体&#xff0c;让其成为独立、自主的活动个体&#xff1b;也就可以理解为建立生命体的思想指导。 让我们能够赋予他灵魂&#xff01;...

量化研究---bigquant策略交易api研究

api接口来平台的代码整理&#xff0c;原理是读取bigquant的模拟测试信号&#xff0c;下单&#xff0c;可以完美的对接qmt交易&#xff0c;我优化了交易api的部分内容 我开发对接qmt的交易系统 看api源代码 源代码 # 导入系统包 import os import json import requests from ty…...

编译原理 期末速成

一、基本概念 1. 翻译程序 vs 编译程序 翻译程序的三种方式 编译&#xff1a;将高级语言编写的源程序翻译成等价的机器语言或汇编语言。&#xff08;生成文件&#xff0c;等价&#xff09;解释&#xff1a;将高级语言编写的源程序翻译一句执行一句&#xff0c;不生成目标文件…...

echarts之漏斗图

vue3echarts实现漏斗图 echarts中文官网&#xff1a;https://echarts.apache.org/examples/zh/index.html 效果图如下&#xff1a; 整体代码如下&#xff1a; <template><div id"funnelChart" style"width:100%;height:400px;"></div&g…...

零基础设计模式——第二部分:创建型模式 - 原型模式

第二部分&#xff1a;创建型模式 - 5. 原型模式 (Prototype Pattern) 我们已经探讨了单例、工厂方法、抽象工厂和生成器模式。现在&#xff0c;我们来看创建型模式的最后一个主要成员——原型模式。这种模式关注的是通过复制现有对象来创建新对象&#xff0c;而不是通过传统的…...

Honeywell TK-PRS021 C200

Honeywell C200/C200E 是一款高性能的集成控制与安全系统&#xff08;ICSS&#xff09;&#xff0c;采用紧凑型 A 系列机箱 设计&#xff0c;适用于工业自动化、过程控制和批处理管理。C200 控制器最初随 PlantScape R200 发布&#xff0c;而 C200E 则与 Experion PKS R400 兼容…...

java 进阶 1.0.3

Thread API说明 自己滚去看文档 CPU线程调度 每一个线程的优先使用权都是系统随机分配的&#xff0c;人人平等 谁先分配到就谁先用 也可以耍赖&#xff0c;就是赋予某一个线程拥有之高使用权&#xff1a;优先级 这样的操作就叫做线程调度 最基本的是系统轮流获得 java的做法是抢…...

从 Docker 到 runC

从 Docker 到 runC:容器底层原理详解 目录 1. Docker 与 runC 的关系 2. Docker 的核心组件 3. runC 的核心功能 4. 实战示例:从 Docker 到 runC 4.1 示例场景:运行一个简单容器 4.2 Docker 底层调用 runC 的流程 4.3 查看 runC 的调用 4.4 直接调用 runC 创建容器 …...

PET,Prompt Tuning,P Tuning,Lora,Qlora 大模型微调的简介

概览 到2025年&#xff0c;虽然PET&#xff08;Pattern-Exploiting Training&#xff09;和Prompt Tuning在学术界仍有探讨&#xff0c;但在工业和生产环境中它们已基本被LoRA/QLoRA等参数高效微调&#xff08;PEFT&#xff09;方法取代 。LoRA因其实现简单、推理零开销&#…...

02-jenkins学习之旅-基础配置

0 配置主路径 jenkins安装目录下找到jenkins.xml文件&#xff0c;C:\ProgramData\Jenkins\.jenkins目录下会存放jenkins相关的配置信息。 1 jdk配置 jenkins是java开发开源的项目&#xff0c;进而服务器需要jdk环境 1.1 服务器安装jdk 1.2 jenkins jdk配置 2 git配置 在je…...

互联网大厂Java求职面试:云原生架构与AI应用集成解决方案

互联网大厂Java求职面试&#xff1a;云原生架构与AI应用集成解决方案 场景一&#xff1a;短视频与直播平台的高并发架构设计 面试官提问 面试官&#xff08;技术总监&#xff09;&#xff1a; 郑薪苦&#xff0c;你有处理过千万级用户同时在线的直播系统吗&#xff1f;如何设…...

Python爬虫实战:研究Crawley 框架相关技术

1. Crawley 框架相关定义 1.1 网络爬虫定义 网络爬虫是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。它通过 HTTP 协议与 Web 服务器进行交互,获取网页内容并进行解析处理,是数据采集和信息检索的重要工具。 1.2 Crawley 框架定义 Crawley 是一个基于 Pytho…...

C#实现List导出CSV:深入解析完整方案

C#实现List导出CSV&#xff1a;深入解析完整方案 在数据交互场景中&#xff0c;CSV文件凭借其跨平台兼容性和简洁性&#xff0c;成为数据交换的重要载体。本文将基于C#反射机制实现的通用CSV导出方案&#xff0c;结合实际开发中的痛点&#xff0c;从基础实现、深度优化到生产级…...

Appium+python自动化(三)- SDK Manager

简介 一开始打算用真机做的&#xff0c;所以在前边搭建环境时候就没有下载SDK&#xff0c;但是考虑到绝大多数人都没有真机&#xff0c;所以顺应民意整理一下模拟器。SDK顾名思义&#xff0c;Android SDK Manager就是一个Android软件开发工具包管理器&#xff0c;就像一个桥梁&…...