从 AMQP 到 RabbitMQ:核心组件设计与工作原理(二)
五、RabbitMQ 工作原理全揭秘
在深入了解了 RabbitMQ 的核心组件之后,接下来让我们深入探究 RabbitMQ 的工作原理,揭开其在消息生产、投递、消费以及可靠性保障等方面的神秘面纱。
5.1 消息生产与投递流程
- 建立连接与信道:生产者首先通过 ConnectionFactory 创建与 RabbitMQ Broker 的 TCP 连接(Connection),这就像是在生产者和 Broker 之间搭建了一条高速公路,为后续的数据传输奠定基础。然后,在这个连接之上创建一个或多个信道(Channel),信道就像是高速公路上的不同车道,每个信道都可以独立地进行数据传输,实现了在同一个 TCP 连接上的并发操作,提高了系统的性能和资源利用率。
- 声明交换机、队列及绑定关系:生产者通过信道声明所需的交换机(Exchange)、队列(Queue)以及它们之间的绑定(Binding)关系。交换机就像是一个智能的快递分拣中心,负责接收生产者发送的消息,并根据路由规则将消息路由到相应的队列中;队列则是用于存储消息的数据结构,遵循先进先出(FIFO)的原则;绑定关系则规定了消息从交换机到队列的路由路径。在一个电商订单处理系统中,可能会声明一个直连交换机,一个订单队列,并将它们通过订单 ID 作为路由键进行绑定,确保订单消息能够准确地路由到订单队列中。
- 发送消息:生产者创建消息,消息包含消息头、消息体和属性等信息。在发送消息时,生产者会指定一个路由键(Routing Key),这个路由键就像包裹上的收件地址,用于标识消息的路由规则。然后,生产者通过信道将消息发送到指定的交换机。例如,在上述电商订单处理系统中,当用户下单后,订单信息作为消息被发送到直连交换机,消息的路由键设置为订单 ID。
- 交换机路由消息:交换机根据接收到的消息的路由键以及绑定关系,将消息路由到一个或多个匹配的队列中。对于直连交换机,如果队列通过某个路由键与交换机绑定,那么当交换机接收到具有相同路由键的消息时,就会将该消息发送到这个队列中;对于主题交换机,通过通配符的方式进行模式匹配,实现更灵活的消息路由;对于扇形交换机,则会将消息广播到所有与之绑定的队列中,不考虑路由键。
5.2 消息消费机制
- 建立连接与信道:与生产者类似,消费者首先通过 ConnectionFactory 创建与 RabbitMQ Broker 的 TCP 连接(Connection),并在连接上创建信道(Channel),为接收消息搭建通道。
- 订阅队列:消费者通过信道声明并订阅感兴趣的队列。订阅队列后,消费者就可以从队列中接收消息。在一个订单处理系统中,订单处理模块作为消费者,会订阅订单队列,等待接收订单消息进行处理。
- 获取并处理消息:消费者从队列中获取消息进行处理。在获取消息时,消费者可以选择自动确认模式或手动确认模式。在自动确认模式下,当消费者收到消息并将其处理完毕后,RabbitMQ 会自动将该消息标记为已确认,然后将其从队列中删除;在手动确认模式下,消费者在成功处理完消息后,需要显式地向 RabbitMQ 发送 ACK(确认)消息,告知 RabbitMQ 该消息已经被处理完毕,可以从队列中删除。手动确认模式提高了消息处理的可靠性,避免了因消费者在处理消息过程中出现异常而导致消息丢失的情况。
- ACK 机制:ACK(Acknowledgement)机制是 RabbitMQ 保证消息被正确处理的关键。当消费者采用手动确认模式时,在处理完消息后,会向 RabbitMQ 发送 ACK 消息。如果 RabbitMQ 在一定时间内没有收到消费者的 ACK 消息,并且消费此消息的消费者已经断开连接,则服务器端会安排该消息重新进入队列,等待投递给下一个消费者(也可能还是原来的那个消费者),确保消息不会丢失。
5.3 消息持久化、确认机制与重试机制
- 消息持久化:为了确保消息在 RabbitMQ 服务器重启或故障时不会丢失,RabbitMQ 提供了消息持久化机制。消息持久化包括交换机持久化、队列持久化和消息持久化三个方面。通过将交换机和队列声明为持久化(durable=true),可以保证它们在服务器重启后仍然存在;将消息的投递模式(deliveryMode)设置为 2(持久化),可以确保消息在服务器重启后依然存在。例如,在一个电商订单处理系统中,将订单队列和相关交换机设置为持久化,并且将订单消息设置为持久化,即使 RabbitMQ 服务器出现故障,订单消息也不会丢失,保证了业务的连续性。
- 确认机制:确认机制主要包括生产者确认机制和消费者确认机制。生产者确认机制用于确保生产者发送的消息被 RabbitMQ 服务器正确接收。生产者可以通过将信道设置为 confirm 模式(channel.confirmSelect ()),然后添加 ConfirmCallback 回调函数来处理消息确认。当消息被发送到 Broker 后,如果 Broker 成功地将消息路由到目标队列,则会调用 ConfirmCallback 回调函数的 handleAck () 方法,表示消息已被确认;如果 Broker 无法将消息路由到目标队列,则会调用 handleNack () 方法,表示消息未被确认。消费者确认机制则是消费者在接收到消息并处理完毕后,向 RabbitMQ 服务器发送 ACK 消息,告知服务器消息已被成功处理。消费者可以选择自动确认或手动确认模式,手动确认模式下,消费者可以根据业务处理的结果来决定是否发送 ACK 消息,提高了消息处理的可靠性。
- 重试机制:当消息处理失败时,重试机制可以帮助处理这种情况。在消费者处理消息过程中,如果出现异常导致消息处理失败,消费者可以根据业务需求选择将消息重新放回队列(basicNack 或 basicReject 并设置 requeue=true),等待下次重试。为了避免消息无限循环重试,通常会结合死信队列(Dead Letter Queue)来实现更复杂的消息处理逻辑。当消息在队列中被多次重试后仍然处理失败时,可以将其发送到死信队列中,在死信队列中可以对这些消息进行单独的处理,如记录日志、人工干预等,确保消息不会被丢失,同时也不会影响正常的消息处理流程。
六、案例实战:Spring Boot 集成 RabbitMQ
6.1 环境搭建
在 Spring Boot 项目中集成 RabbitMQ,首先需要引入 Spring Boot Starter AMQP 依赖。在pom.xml文件中添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
添加依赖后,在application.yml或application.properties配置文件中配置 RabbitMQ 的连接信息,示例如下:
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
上述配置中,host指定了 RabbitMQ 服务器的地址,port为服务器端口,username和password是连接 RabbitMQ 服务器的用户名和密码。
6.2 配置队列、交换机与绑定关系
接下来,通过配置类来声明队列、交换机并建立它们之间的绑定关系。创建一个配置类,例如RabbitMQConfig.java,代码如下:
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
// 声明队列
@Bean
public Queue orderQueue() {
return new Queue("orderQueue", true); // 第二个参数表示是否持久化
}
// 声明交换机
@Bean
public DirectExchange orderExchange() {
return new DirectExchange("orderExchange");
}
// 队列绑定到交换机
@Bean
public Binding orderBinding() {
return BindingBuilder.bind(orderQueue()).to(orderExchange()).with("orderRoutingKey");
}
}
在上述代码中,首先通过@Bean注解声明了一个名为orderQueue的队列,并设置为持久化队列;然后声明了一个直连交换机orderExchange;最后通过BindingBuilder将队列orderQueue与交换机orderExchange通过路由键orderRoutingKey进行绑定 ,这样当有消息发送到orderExchange交换机且路由键为orderRoutingKey时,消息就会被路由到orderQueue队列中。
6.3 消息生产与消费代码实现
生产者通过AmqpTemplate发送消息,创建一个生产者服务类,例如RabbitMQProducer.java,代码如下:
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RabbitMQProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendOrderMessage(String message) {
rabbitTemplate.convertAndSend("orderExchange", "orderRoutingKey", message);
System.out.println("Sent message: " + message);
}
}
在上述代码中,RabbitMQProducer类通过@Autowired注解注入了RabbitTemplate,在sendOrderMessage方法中,使用rabbitTemplate的convertAndSend方法将消息发送到指定的交换机orderExchange,并指定路由键orderRoutingKey。
消费者通过@RabbitListener注解监听队列并接收消息,创建一个消费者服务类,例如RabbitMQConsumer.java,代码如下:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@Service
public class RabbitMQConsumer {
@RabbitListener(queues = "orderQueue")
public void receiveOrderMessage(String message) {
System.out.println("Received message: " + message);
// 处理接收到的消息,如更新订单状态、处理库存等业务逻辑
}
}
在RabbitMQConsumer类中,@RabbitListener注解标记了receiveOrderMessage方法,该方法监听名为orderQueue的队列,当队列中有消息时,会自动调用该方法接收并处理消息。在实际应用中,可以在方法内部编写具体的业务处理逻辑,如更新订单状态、处理库存等操作。通过以上步骤,就完成了 Spring Boot 与 RabbitMQ 的集成,实现了消息的生产和消费功能 。
七、总结与展望
通过对 AMQP 协议以及 RabbitMQ 核心组件设计与工作原理的深入探究,我们对这一强大的消息队列技术有了全面而深刻的理解。AMQP 协议作为消息队列领域的基石,为消息的可靠传输和灵活路由提供了坚实的保障,其丰富的特性和规范的设计理念,为各种消息队列实现提供了统一的标准和框架。
RabbitMQ 作为 AMQP 协议的杰出实现者,凭借其高可靠性、灵活的路由机制、丰富的功能特性以及对多种编程语言的支持,在分布式系统中得到了广泛的应用。无论是在传统企业的核心业务系统,还是在新兴的互联网、物联网应用中,RabbitMQ 都能发挥其独特的优势,为系统的高效稳定运行保驾护航。
展望未来,随着分布式系统、云计算、大数据等技术的不断发展,消息队列技术也将迎来新的机遇和挑战。未来的消息队列技术可能会朝着以下几个方向发展:
- 更高的性能和扩展性:随着业务规模的不断扩大,对消息队列的吞吐量、延迟和扩展性提出了更高的要求。未来的消息队列将不断优化底层架构,采用更高效的数据存储和传输方式,以实现更高的性能和更好的扩展性,满足大规模分布式系统的需求。
- 云原生支持:云计算的普及使得云原生应用成为发展趋势,消息队列也将更加紧密地与云平台结合,提供弹性伸缩、自动化运维等云原生特性,方便用户在云端快速部署和管理消息队列服务。
- 与大数据和人工智能的融合:在大数据时代,消息队列将成为大数据处理流程中的重要一环,与大数据存储、计算框架深度融合,实现数据的实时采集、传输和处理。同时,人工智能技术的发展也将为消息队列带来智能化的路由、监控和管理,提高系统的智能化水平和运维效率。
- 增强的安全性和可靠性:在信息安全日益重要的今天,消息队列将进一步加强安全防护机制,如身份验证、加密传输、访问控制等,确保消息的安全性和隐私性。同时,通过更完善的容错机制和备份策略,提高系统的可靠性和可用性,保证业务的连续性。
作为开发者,我们需要紧跟技术发展的步伐,不断学习和探索新的技术和应用场景,充分发挥 AMQP 和 RabbitMQ 等消息队列技术的优势,为构建更加高效、可靠、智能的分布式系统贡献自己的力量。
相关文章:
从 AMQP 到 RabbitMQ:核心组件设计与工作原理(二)
五、RabbitMQ 工作原理全揭秘 在深入了解了 RabbitMQ 的核心组件之后,接下来让我们深入探究 RabbitMQ 的工作原理,揭开其在消息生产、投递、消费以及可靠性保障等方面的神秘面纱。 5.1 消息生产与投递流程 建立连接与信道:生产者首先通过 …...

MySql(十二)
目录 MySql约束 1.添加主键约束 语法格式 1)创建一个带主键的表 查看表结构 2)创建表的时候指定主键名称 查看表结构 3)创建一个表然后,然后再使用alter为列添加主键 查看表结构 4)为表添加数据 1---正常数据 2---主键…...

51c视觉~3D~合集3
我自己的原文哦~ https://blog.51cto.com/whaosoft/13954440 #SceneTracker 在4D时空中追踪万物!国防科大提出首个长时场景流估计方法 本篇分享 TPAMI 2025 论文SceneTracker: Long-term Scene Flow Estimation Network,国防科大提出首…...
windows11安装编译QtMvvm
windows11安装编译QtMvvm 1 从github下载代码2 官方的Download/Installtion3 自行构建编译QtMvvm遇到的问题3.1 `qmake`问题执行命令报错原因分析qmake报错:找不到编译器 cl解决方案3.2 `make qmake_all`问题执行命令报错原因分析make命令未识别解决方案3.3 缺少`perl`问题执行…...

【2025年电工杯数学建模竞赛A题】光伏电站发电功率日前预测问题+完整思路+paper+源码
本人7年数学建模竞赛经验,历史获奖率百分之百。团队成员都是拿过全国一等奖的硕博,有需要数模竞赛帮助的可以私信我 本题主要涉及数据预测,数据分析,机器学习,时间序列等知识 1.问题背景与问题描述 2.解题思路分析 …...

OpenCv高阶(十九)——dlib关键点定位
文章目录 一、什么是人脸关键点定位?二、关键点模型的下载及关键信息的理解三、dlib关键点定位的简单实现(1)导入必要的库(2)从指定路径读取图像文件(3)创建dlib的正面人脸检测器对象࿰…...

BUUCTF之[ACTF2020 新生赛]BackupFile
打开环境就一句话 找出源文件! 结合题目名字:BackupFile 先用dirsearct扫描网站文件 发现一个index.php.bak ,拼接url下载 打开发现php代码 <?php include_once "flag.php";if(isset($_GET[key])) {$key $_GET[key];if(!is_numeric($key)) {exit…...

头歌之动手学人工智能-Pytorch 之autograd
目录 第1关:Variable 任务描述 编程要求 测试说明 没有伟大的愿望,就没有伟大的天才。——巴尔扎克开始你的任务吧,祝你成功! 第2关:Variable 属性 任务描述 编程要求 测试说明 真正的科学家应当是个幻想家&a…...
OIer常用的软件
前言 现在许多软件的官网多不好找,所以我今天就将常用的一些软件官网地址翻了出来,并简单介绍了他的用法。 正文 1.DEV-C DEV-C 用途:c编译软件,是OIer的生涯之路的必备软件 2.Katex KATex 用途:展现公式的软件&…...
Centos7.x内网环境Jenkins前端打包环境配置
Centos7.x内网环境Jenkins前端打包环境配置 参考地址: https://www.cnblogs.com/guangdelw/p/18763336 https://2048.csdn.net/682c1be8606a8318e857d687.html 前言:环境描述和目标 最近公司新接了一个项目,要求是:需要再桌面…...

Kafka集成Flume/Spark/Flink(大数据)/SpringBoot
Kafka集成Flume Flume生产者 ③、安装Flume,上传apache-flume的压缩包.tar.gz到Linux系统的software,并解压到/opt/module目录下,并修改其名称为flume Flume消费者 Kafka集成Spark 生产者 object SparkKafkaProducer{def main(args:Array[S…...

Scratch节日 | 拯救屈原 | 端午节
端午节快乐! 这款特别为端午节打造的Scratch游戏 《拯救屈原》,将带你走进古代中国,感受历史与文化的魅力! 🏮 游戏介绍 扮演勇敢的探险者,穿越时空回到古代,解锁谜题,完成任务&…...

rabbitmq Direct交换机简介
在实际开发中,需求可能变得复杂,如消息的收发和处理。以支付系统为例,成功支付后需要改变订单状态并通知用户,而失败则不需要。为处理这种情况,提出了使用Direct交换机,它可以根据规则将消息路由到指定队列…...

Git实战--基于已有分支克隆进行项目开发的完整流程
Git克隆项目开发流程 ✅ 一、完整流程概述✅ 二、详细操作步骤Step 1:克隆仓库(如果尚未克隆)Step 2:获取远程分支信息并切换到 feature/ 获取所有远程分支Step 3:创建并切换到你的新分支Step 4:开始开发新…...
MapReduce(期末速成版)
起初在B站看3分钟的速成视频,感觉很多细节没听懂。 具体例子解析(文件内容去重) 对于两个输入文件,即文件A 和文件B,请编写MapReduce 程序,对两个文件进行合并,并剔除 其中重复的内容,得到一个新的输出文件…...
鸿蒙OSUniApp 移动端直播流播放实战:打造符合鸿蒙设计风格的播放器#三方框架 #Uniapp
UniApp 移动端直播流播放实战:打造符合鸿蒙设计风格的播放器 在移动互联网时代,直播已经成为一种主流的内容形式。本文将详细介绍如何使用 UniApp 框架开发一个优雅的直播流播放器,并融入鸿蒙系统的设计理念,实现一个既美观又实用…...

C3、C2f、C3K2、C2PSA的具体结构
YOLOV5 C3 Bottleneck C2f...

2_MCU开发环境搭建-配置MDK兼容Keil4和C51
MCU开发环境搭建-配置MDK兼容Keil4和C51 一、概述 本文以MDK-ARM V5.36版本基础介绍DMK-ARM工程兼容Keil4和C51的配置。 注:在阅读本文前,请先安装和配置完成MDK-ARM(Keil5)。 二、工具包下载 链接: https://pan.baidu.com/s/1Tu2tDD6zRra4xb_PuA1Wsw 提取码: 81pp 三、…...

通过远程桌面连接Windows实例提示“出现身份验证错误,无法连接到本地安全机构”错误怎么办?
本文介绍通过远程桌面连接Windows实例提示“出现身份验证错误无法连接到本地安全机构”错误的解决方案。 问题现象 通过本地电脑内的远程桌面连接Windows实例提示“出现身份验证错误,无法连接到本地安全机构”错误。 问题原因 导致该问题的可能原因如下&#x…...

百度golang研发一面面经
输入一个网址,到显示界面,中间的过程是怎样的 IP 报文段的结构是什么 Innodb 的底层结构 知道几种设计模式 工厂模式 简单工厂模式:根据传入类型参数判断创建哪种类型对象工厂方法模式:由子类决定实例化哪个类抽象工厂模式&#…...

TC3xx学习笔记-启动过程详解(一)
文章目录 前言Firmware启动过程BMHD Check流程ABM启动Internal Flash启动Bootloader ModeProcessing in case no valid BMHD foundProcessing in case no Boot Mode configured by SSW 总结 前言 之前介绍过UCB BMHD的使用,它在启动过程中起着重要的作用࿰…...

Scratch节日 | 六一儿童节抓糖果
六一儿童节怎么能没有糖果?这款 六一儿童节抓糖果 小游戏,让你变身小猫,开启一场甜蜜大作战! 🎮 游戏玩法 帮助小猫收集所有丢失的糖果,收集越多分数越高! 小心虫子一样的“坏糖果”ÿ…...
系统调用与程序接口的关系
程序接口类型 系统调用:是操作系统提供给应用程序的接口 ,允许应用程序请求操作系统执行特定操作,像文件操作(打开、读写、关闭文件 )、进程管理(创建、终止进程 )、设备管理(操作磁…...
从线性方程组角度理解公式 s=n−r(3E−A)
从线性方程组角度理解公式 sn−r(3E−A) 这个公式本质上是 齐次线性方程组解空间维度 的直接体现。下面通过三个关键步骤解释其在线性方程组中的含义: 1. 公式对应的线性方程组 考虑矩阵方程: (3E−A)x0 其中: x 是 n 维未知向量3E−…...

通信算法之280:无人机侦测模块知识框架思维导图
1. 无人机侦测模块知识框架思维导图, 见文末章节。 2. OFDM参数估计,基于循环自相关特性。 3. 无人机其它参数估计...

【Doris基础】Apache Doris中的Coordinator节点作用详解
目录 1 Doris架构概述 2 Coordinator节点的核心作用 2.1 查询协调与调度 2.2 执行计划生成与优化 2.3 资源管理与负载均衡 2.4 容错与故障恢复 3 Coordinator节点的关键实现机制 3.1 两阶段执行模型 3.2 流水线执行引擎 3.3 分布式事务管理 4 Coordinator节点的高可…...
软考 系统架构设计师之考试感悟3
接前一篇文章:软考 系统架构设计师之考试感悟2 上周六(2025年5月24日),本人第三次参加了软考系统架构师的考试。和前两次一样,考了一天,身心俱疲。不过这次感觉比上一次要稍微好点,可能也是考的…...

【Kubernetes-1.30】--containerd部署
文章目录 一、环境准备1.1 三台服务器1.2 基础配置(三台机通用)1.3 关闭 Swap(必须)1.4 关闭防火墙(可选)1.5 加载必要模块 & 配置内核参数 二、安装容器运行时(containerd 推荐)…...
Flutter 嵌套H5 传参数
你可以通过在加载 H5 页面时,将 token 作为 URL 参数拼接,或者通过 WebView 的 JavaScript 通信功能(如 runJavaScript 或 addJavaScriptChannel)传递 token。常用方式如下: 方式一:URL 拼接参数 假设你的…...
什么是线程上下文切换?
导语: 线程上下文切换(Context Switch)是Java并发编程中一个常见但容易被忽视的概念。在高并发场景下,它直接影响系统性能。本文将从面试官角度深入剖析这个话题,帮你理解底层原理、掌握优化思路、规避项目中的常见陷阱…...