RabbitMQ 架构分析
文章目录
- 前言
- 一、RabbitMQ架构分析
- 1、Broker
- 2、Vhost
- 3、Producer
- 4、Messages
- 5、Connections
- 6、Channel
- 7、Exchange
- 7、Queue
- 8、Consumer
- 二、消息路由机制
- 1、Direct Exchange
- 2、Topic Exchange
- 3、Fanout Exchange
- 4、Headers Exchange
- 5、notice
- 5.1、备用交换机(Alternate Exchange)
- 5.2、Mandatory标志
- 5.3、Dead Letter Exchange(死信交换机)
前言
RabbitMQ是一款功能强大、利用广泛的消息中间件,通常用于分布式系统和微服务架构中的异步通信。理解其架构有助于正确配置和优化系统,实现高效可靠的消息传递
一、RabbitMQ架构分析
架构图

1、Broker
我们要使用 RabbitMQ 来收发消息,必须要安装一个 RabbitMQ 的服务,可以安装在 Windows 上面也可以安装在 Linux 上面,默认是 5672 的端口。
这台 RabbitMQ 的服务器我们把它叫做 Broker。
2、Vhost
我们每个需要实现基于 RabbitMQ 的异步通信的系统,都需要在 Broker 上创建自己要用到的交换机、队列和它们的绑定关系。
如果某个业务系统不想跟别人混用一个 Broker,有办法不需要安装多个 RabbitMQ 的服务吗?那就是建立一个新的虚拟主机 VHOST。 VHOST 除了可以提高硬件资源的利用率之外,还可以实现资源的隔离和权限的控制。
它的作用类似于其他编程语言中的 namespace 和 package,不同的 VHOST 中可以有同名的 Exchange 和 Queue,它们是完全独立的。
我们可以为不同的业务系统创建专属于他们自己的 VHOST,然后再为他们创建专属的用户,给用户分配对应的 VHOST 的权限。
我们安装 RabbitMQ 的时候会自带一个默认的 VHOST,名字是“/”。
3、Producer
消息生产者(Producer)是发送消息的应用程序。在RabbitMQ中,生产者将消息发送到交换机(Exchange)而不是直接发给队列。
生产者可以是任何能够与RabbitMQ服务器进行通信并使用AMQP协议发送消息的应用。
4、Messages
消息是由生产者发送给RabbitMQ的内容单元,每条消息由负载(payload)和一些元数据(metadata)组成。负载是消息的实际内容,而元数据包含消息的属性或标识。
5、Connections
生产者和消费者与RabbitMQ服务器之间的TCP长连接,每个连接用于消息的传递和通信。
6、Channel
如果所有的生产者发送消息和消费者接收消息,都直接创建和释放 TCP 长连接的话,对于 Broker 来说肯定会造成很大的性能损耗,也会浪费时间。
在 AMQP 里面引入了 Channel (消息信道)的概念,它是一个虚拟的连接。这样我们就可以在保持的 TCP 长连接里面去创建和释放Channel,大大了减少了资源消耗。
不同的 Channel 是相互隔离的,每个 Channel 都有自己的编号。每个客户端线程独占一个channel。
Channel 是 RabbitMQ 原生 API 里面的最重要的编程接口,也就是说我们定义交换机、队列、绑定关系,发送消息,消费消息,调用的都是Channel 接口上的方法。
7、Exchange
现在我们来思考一个问题,如果要把一条消息发送给多个队列,给多个消费者消费,如果交给生产者来做,当有成千上万个队列的时候,那要发送大量消息,耗费太多资源。
如何更优雅的处理呢?RabbitMQ考虑到了这一点,它设计了一个帮我们路由消息的组件,叫做 Exchange。
不管有多少个队列需要接收消息,我都只需要发送到 Exchange 就OK了,由它帮我来分发。Exchange 是不会存储消息的,它只做一件事情,根据规则分发消息。 分发就需要有规则,并且与队列绑定,然后进行个性话分发。
Exchange 和队列是多对多的绑定关系,也就说,一个交换机的消息一个路由给多个队列,一个队列也可以接收来自多个交换机的消息。
绑定关系建立好之后,生产者发送消息到 Exchange,也会携带一个特殊的标识。 当这个标识跟绑定的标识匹配的时候,消息就会发给一个或者多个符合规则的队列。
创建Exchange可以配置相关的属性
| 属性 | 含义 |
|---|---|
| name | 交换机的名称 |
| type | 交换机的类型决定了它如何路由消息。主要有以下几种类型。Direct:路由规则是完全匹配路由键。 Fanout:把接收到的消息广播到所有绑定的队列上,不需要匹配键。 Topic:根据路由键的通配符模式进行路由。 Headers:根据消息头属性进行匹配,而不是路由键。 |
| durable | 是否持久化(重启 rabbitmq 之后, 交换机是否还存在),默认false |
| autoDelete | 当所有绑定到这个交换机的队列都不再使用时,交换机会自动删除。默认为false |
| internal | 交换机将是内部的,不能被生产者直接发送消息,只能用于交换机到交换机的绑定(即路由)。默认为false |
| arguments | 一个字典,可以包含与RabbitMQ插件或未来版本兼容的其他设置。具体参数可能会依赖于具体的交换机类型和业务需求,比如 alternate-exchange:配置一个备用交换机(当消息无法路由时,消息将发送到这个备用交换机) |
7、Queue
在 Broker 上有一个对象用来存储消息,在 RabbitMQ 里面这个对象叫做 Queue。
队列也是生产者和消费者的纽带,生产者发送的消息到达队列,在队列中存储,消费者从队列获取消息进行消费。
队列的相关属性
| 属性 | 含义 |
|---|---|
| name | |
| durable | (默认为false)设置队列是否为持久化队列。如果设置为true,即使RabbitMQ服务器重启,队列仍然存在。 |
| exclusive | (默认为false)设置队列是否为排他队列。如果设置为true,队列仅限于首次声明它的连接(Connection)使用,并且连接关闭时队列会自动删除。这个参数优先级高于autoDelete |
| autoDelete | (默认为false)设置队列是否在所有消费者断开连接后自动删除。如果设置为true,当不再有任何消费者订阅该队列时,它会被删除。 |
| arguments | x-message-ttl: 每个消息的生存时间(以毫秒为单位)。如果消息在队列中停留超过这个时间则会被删除。 x-expires: 在队列空闲(没有消费者订阅)超过指定时间(以毫秒为单位)后,队列会被删除。 x-max-length: 队列允许的最大消息数。超过限制时,新消息将从队列的头部移除(可选丢弃策略)。 x-max-length-bytes: 队列允许的最大字节数。超过限制时,新消息将从队列的头部移除(可选丢弃策略)。 x-dead-letter-exchange: 设置消息从该队列被移除(由于TTL、长度限制等)后发送到的备用交换机(Dead Letter Exchange)。 x-dead-letter-routing-key: 设置消息重新投递到备用交换机时使用的路由键。 x-max-priority: 队列的最大优先级,如果设置,队列将成为一个优先级队列。 x-queue-mode: 可以设置为 lazy,表明队列应尽可能保存消息到磁盘而不是内存中,以减少RAM的占用。 x-queue-master-locator: 用于集群模式下,控制队列主节点的分布策略。 |
8、Consumer
消费者消费消息有两种模式。
- Pull 模式,对应的方法是 basicGet。消息存放在服务端,只有消费者主动获取才能拿到消息。如果每隔一段时间获取一次消息,消息的实时性会降低。但是好处是可以根据自己的消费能力决定获取消息的频率
- Push 模式,对应的方法是 basicConsume,只要生产者发消息到服务器,就马上推送给消费者,消息保存在客户端,实时性很高,如果消费不过来有可能会造成消息积压。
Spring AMQP 是 push 方式,通过事件机制对队列进行监听,只要有消息到达队列,就会触发消费消息的方法。
RabbitMQ 中 pull 和 push 都有实现。而 kafka 和 RocketMQ 只有 pull。
由于队列有 FIFO 的特性,只有确定前一条消息被消费者接收之后,Broker 才会把这条消息从数据库删除,继续投递下一条消息。
一个消费者是可以监听多个队列的,一个队列也可以被多个消费者监听。 但是在生产环境中,我们一般是建议一个消费者只处理一个队列的消息。
如果需要提升处理消息的能力,可以增加多个消费者。这个时候消息会在多个消费者之间轮询。
二、消息路由机制
RabbitMQ 中一共有四种类型的交换机,Direct、Topic、Fanout、Headers(不常用)。
1、Direct Exchange
特点:
- 直接交换机根据消息的路由键(Routing Key)与绑定键(Binding Key)进行精确匹配,将消息路由到绑定的队列。
工作原理:
- 当生产者发送消息时,需要指定路由键。
- 交换机会查找与该路由键完全匹配的绑定队列,并将消息路由到这些队列。

例如发送如下消息
# 只有 binding key = rabbit 能收到消息
channel.basicPublish(“MY_DIRECT_EXCHANGE”,”rabbit”,”msg 1”);# 匹配不上,消息丢失
channel.basicPublish(“MY_DIRECT_EXCHANGE”,”rabbit0000”,”msg 1”);
应用场景:
- 适用于需要精确匹配路由键的场景,比如日志系统中不同级别的日志(“info”, “error”)可以精确路由到不同的队列进行处理。
2、Topic Exchange
特点:
- 主题交换机通过模式匹配路由键和绑定键来路由消息,支持部分匹配和通配符。
工作原理:
- 生产者发送消息时指定带有模式的路由键,路由键可以包含点号(.)分隔的多个单词,例如 a.bc.def 是 3 个单词。
- 绑定键可以包含通配符:"*“匹配一个单词,”#"匹配零个或多个单词,可以当前缀也可以当后缀。

分析:
- rabbit.#:支持路由键以 rabbit 开头的消息路由,后面可以有单词,也可以没有
- #.rocket:支持路由键以 rocket 结尾,前面可以有也可以没有单词的消息路由
- kafka.*:支持路由键以 kafka 开头,并且后面是一个单词的消息路由
例如发送如下消息
# 只有 binding key = rabbit.# 能收到消息
channel.basicPublish("MY_TOPIC_EXCHANGE","rabbit.abc.jvm","msg 2");# 只有 binding key = kafka.* 能收到消息
channel.basicPublish("MY_TOPIC_EXCHANGE","kafka.jvm","msg 2");# 只有 binding key = #.rocket 能收到消息
channel.basicPublish("MY_TOPIC_EXCHANGE","kafka.abc.rocket","msg 2");# binding key = rabbit.# , binding key = #.rocket 能收到消息
channel.basicPublish("MY_TOPIC_EXCHANGE","rabbit.dad.rocket","msg 2");# binding key = #.rocket , binding key = kafka.* 能收到消息
channel.basicPublish("MY_TOPIC_EXCHANGE","kafka.rocket","msg 2");
应用场景:
- 适用于多层次、复杂的路由场景,例如新闻系统可以根据新闻类别和地区进行路由。
3、Fanout Exchange
特点:
- 广播交换机会将接收到的每条消息路由到所有绑定的队列,而不考虑路由键。
工作原理:
- 生产者发送消息时无需指定路由键。
- 消息会被广播到所有与交换机绑定的队列中。

例如发送如下消息
# 三个队列都会收到 msg 4
channel.basicPublish("MY_FANOUT_EXCHANGE", "", "msg 4");
应用场景:
- 适用于广播场景,将一条消息分发给多个消费者,常用于发布-订阅模式。比如广告、日志等
4、Headers Exchange
特点:
- 头交换机不是通过路由键,而是通过消息头(Headers)中的属性进行匹配路由。
工作原理:
- 绑定包含一组键值对,消息头也包含键值对。
- 交换机将消息头与绑定键值对进行匹配来路由消息,可选择完全匹配或者部分匹配。
应用场景:
- 适用于消息头包含丰富信息,且需要基于多属性进行路由的场景。例如,需要根据多种复杂条件路由的应用。
5、notice
Topic Exchange 和 Direct Exchange 匹配不上都可能导致消息丢失。
可以按照如下方式处理
5.1、备用交换机(Alternate Exchange)
备用交换机是RabbitMQ提供的一种机制,用来处理没有匹配队列的消息。你可以为一个交换机配置一个备用交换机,当消息未能被路由到任何队列时,这些消息会被发送到备用交换机进行处理。
配置备用交换机步骤:
- 创建一个备用交换机。
- 在主要交换机上设置该备用交换机。
示例:
- 假设我们有一个主交换机名为primary_exchange和一个备用交换机名为alternate_exchange,你可以用以下方式设置:
// 当消息在primary_exchange中没有匹配的队列时,消息将被路由到alternate_exchange。
Map<String, Object> args = new HashMap<String, Object>();
args.put("alternate-exchange", "alternate_exchange");
channel.exchangeDeclare("primary_exchange", "direct", true, false, args);
5.2、Mandatory标志
Mandatory标志是RabbitMQ的消息属性之一。在生产者发送消息时,如果设置了mandatory标志为true,而消息未能找到匹配的队列,那么消息不会被丢弃,Broker会将消息返回给生产者。
如何使用:
- 在生产者发送消息时,可以配置mandatory标志。
String message = "Hello World!";
channel.basicPublish(exchangeName, routingKey, true, null, message.getBytes());
Callback机制可以用来处理返回的未路由消息。需要设置ReturnCallback:
channel.addReturnListener(new ReturnCallback() {public void handle (Return r){
// 处理未路由的消息System.out.println("Returned message: " + new String(r.getBody()));}
});
5.3、Dead Letter Exchange(死信交换机)
未被正确路由的消息有时会被重定向到称为死信交换机(DLX)的特殊交换机。当一个队列的消息变为死信时,这些消息可以被路由到一个死信交换机上。
一些情况会导致消息变为死信:
- 消息被拒绝(basic.reject 或 basic.nack)并且 requeue 属性设置为 false。
- 消息在队列中存活时间超过TTL(Time to Live)。
- 队列的消息数超过了最大长度(队列溢出)。
你可以配置队列使用死信交换机:
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-dead-letter-exchange", "dlx_exchange");
channel.queueDeclare("queue_name", true, false, false, args);
相关文章:
RabbitMQ 架构分析
文章目录 前言一、RabbitMQ架构分析1、Broker2、Vhost3、Producer4、Messages5、Connections6、Channel7、Exchange7、Queue8、Consumer 二、消息路由机制1、Direct Exchange2、Topic Exchange3、Fanout Exchange4、Headers Exchange5、notice5.1、备用交换机(Alter…...
127周一复盘 (165)玩法与难度思考
1.上午测试,小改了点东西, 基本等于啥也没干。 匆忙赶往车站。 从此进入春节期间,没有开发,而思考与设计。 2.火车上思考玩法与难度的问题。 目前的主流作法实际上并不完全符合不同玩家的需求, 对这方面还是要有自…...
Spring--SpringMVC使用(接收和响应数据、RESTFul风格设计、其他扩展)
SpringMVC使用 二.SpringMVC接收数据2.1访问路径设置2.2接收参数1.param和json2.param接收数据3 路径 参数接收4.json参数接收 2.3接收cookie数据2.4接收请求头数据2.5原生api获取2.6共享域对象 三.SringMVC响应数据3.1返回json数据ResponseBodyRestController 3.2返回静态资源…...
git Bash通过SSH key 登录github的详细步骤
1 问题 通过在windows 终端中的通过git登录github 不再是通过密码登录了,需要本地生成一个密钥,配置到gihub中才能使用 2 步骤 (1)首先配置用户名和邮箱 git config --global user.name "用户名"git config --global…...
在计算机上本地运行 Deepseek R1
Download Ollama on Linux Download Ollama on Windows Download Ollama on macOS Deepseek R1 是一个强大的人工智能模型,在科技界掀起了波澜。它是一个开源语言模型,可以与 GPT-4 等大玩家展开竞争。但更重要的是,与其他一些模型不同&…...
基于51单片机和ESP8266(01S)、LCD1602、DS1302、独立按键的WiFi时钟
目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、延时2、定时器03、串口通信4、DS13025、LCD16026、独立按键 四、主函数总结 系列文章目录 前言 之前做了一个WiFi定时器时钟,用八位数码管进行显示,但是定时器时钟的精度较低࿰…...
机器学习 ---逻辑回归
逻辑回归是属于机器学习里面的监督学习,它是以回归的思想来解决分类问题的一种非常经典的二分类分类器。由于其训练后的参数有较强的可解释性,在诸多领域中,逻辑回归通常用作 baseline 模型,以方便后期更好的挖掘业务相关信息或提…...
拟合损失函数
文章目录 拟合损失函数一、线性拟合1.1 介绍1.2 代码可视化1.2.1 生成示例数据1.2.2 损失函数1.2.3 绘制三维图像1.2.4 绘制等高线1.2.5 损失函数关于斜率的函数 二、 多变量拟合2.1 介绍2.2 代码可视化2.2.1 生成示例数据2.2.2 损失函数2.2.3 绘制等高线 三、 多项式拟合3.1 介…...
【C++基础】多线程并发场景下的同步方法
如果在多线程程序中对全局变量的访问没有进行适当的同步控制(例如使用互斥锁、原子变量等),会导致多个线程同时访问和修改全局变量时发生竞态条件(race condition)。这种竞态条件可能会导致一系列不确定和严重的后果。…...
Linux常见问题解决方法--1
常见安全工具、设备 工具 端口及漏洞扫描:Namp、Masscan 抓包:Wireshark,Burpsuite、Fiddler、HttpCanary Web自动化安全扫描:Nessus、Awvs、Appscan、Xray 信息收集:Oneforall、hole 漏洞利用:MSF、…...
银行卡三要素验证接口:方便快捷地实现银行卡核验功能
银行卡三要素验证API:防止欺诈交易的有力武器 随着互联网的发展,电子支付方式也越来越普及。在支付过程中,银行卡是最常用的支付工具之一。然而,在一些支付场景中,需要对用户的银行卡信息进行验证,以确保支…...
利用JSON数据类型优化关系型数据库设计
利用JSON数据类型优化关系型数据库设计 前言 在关系型数据库中,传统的结构化存储方式要求预先定义好所有的列及其数据类型。 然而,随着业务的发展,这种设计可能会显得不够灵活,尤其是在需要扩展单个列的描述功能时。 JSON数据…...
极简壁纸js逆向
首先抓包,翻页可以看到数据储存在该包 可以看到随着页面变化,只有current在变化 而且载荷都没有加密,看来不用js逆向了 爬取代码 import os import asyncio import aiohttp import jsonheaders {"accept": "application/j…...
Kafka 入门与应用实战:吞吐量优化与与 RabbitMQ、RocketMQ 的对比
前言 在现代微服务架构和分布式系统中,消息队列作为解耦组件,承担着重要的职责。它不仅提供了异步处理的能力,还能确保系统的高可用性、容错性和扩展性。常见的消息队列包括 Kafka、RabbitMQ 和 RocketMQ,其中 Kafka 因其高吞吐量…...
JAVA 接口、抽象类的关系和用处 详细解析
接口 - Java教程 - 廖雪峰的官方网站 一个 抽象类 如果实现了一个接口,可以只选择实现接口中的 部分方法(所有的方法都要有,可以一部分已经写具体,另一部分继续保留抽象),原因在于: 抽象类本身…...
数据结构与算法再探(六)动态规划
目录 动态规划 (Dynamic Programming, DP) 动态规划的基本思想 动态规划的核心概念 动态规划的实现步骤 动态规划实例 1、爬楼梯 c 递归(超时)需要使用记忆化递归 循环 2、打家劫舍 3、最小路径和 4、完全平方数 5、最长公共子序列 6、0-1背…...
使用PC版本剪映制作照片MV
目录 制作MV模板时长调整拖动边缘缩短法分割删除法变速法整体调整法 制作MV 导入音乐 导入歌词 点击歌词 和片头可以修改字体: 还可以给字幕添加动画效果: 导入照片,自动创建照片轨: 修改片头字幕:增加两条字幕轨&…...
Python爬虫获取custom-1688自定义API操作接口
一、引言 在电子商务领域,1688作为国内领先的B2B平台,提供了丰富的API接口,允许开发者获取商品信息、店铺信息等。其中,custom接口允许开发者进行自定义操作,获取特定的数据。本文将详细介绍如何使用Python调用1688的…...
Autogen_core: Reflection
目录 代码代码逻辑解释:数据类定义:CoderAgent 类:ReviewerAgent 类:主程序: 完成的功能: 代码 from dataclasses import dataclassdataclass class CodeWritingTask:task: strdataclass class CodeWritin…...
GitHub 仓库的 Archived 功能详解:中英双语
GitHub 仓库的 Archived 功能详解 一、什么是 GitHub 仓库的 “Archived” 功能? 在 GitHub 上,“Archived” 是一个专门用于标记仓库状态的功能。当仓库被归档后,它变为只读模式,所有的功能如提交代码、创建 issue 和 pull req…...
.NET Core缓存
目录 缓存的概念 客户端响应缓存 cache-control 服务器端响应缓存 内存缓存(In-memory cache) 用法 GetOrCreateAsync 缓存过期时间策略 缓存的过期时间 解决方法: 两种过期时间策略: 绝对过期时间 滑动过期时间 两…...
Ubuntu 20.04安装Protocol Buffers 2.5.0
个人博客地址:Ubuntu 20.04安装Protocol Buffers 2.5.0 | 一张假钞的真实世界 安装过程 Protocol Buffers 2.5.0源码下载:https://github.com/protocolbuffers/protobuf/tree/v2.5.0。下载并解压。 将autogen.sh文件中以下内容: curl htt…...
【贪心算法】洛谷P1090 合并果子 / [USACO06NOV] Fence Repair G
2025 - 01 - 21 - 第 45 篇 【洛谷】贪心算法题单 -【 贪心算法】 - 【学习笔记】 作者(Author): 郑龙浩 / 仟濹(CSND账号名) 洛谷 P1090[NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G 【贪心算法】 文章目录 洛谷 P1090[NOIP2004 提高组] 合并果子 / [USACO06…...
14.模型,纹理,着色器
模型、纹理和着色器是计算机图形学中的三个核心概念,用通俗易懂的方式来解释: 1. 模型:3D物体的骨架 通俗解释: 模型就像3D物体的骨架,定义了物体的形状和结构。 比如,一个房子的模型包括墙、屋顶、窗户等…...
【微服务与分布式实践】探索 Dubbo
核心组件 服务注册与发现原理 服务提供者启动时,会将其服务信息(如服务名、版本、所在节点的网络地址等)注册到注册中心。服务消费者则可以从注册中心发现可用的服务提供者列表,并与之通信。注册中心会存储服务的信息,…...
Scale AI 创始人兼 CEO采访
Scale AI 创始人兼 CEO 亚历山大王(Alexander Wang)首次亮相节目接受采访。他的公司专注于为人工智能工具提供准确标注的数据。早在 2022 年,王成为世界上最年轻的白手起家亿万富翁。 美国在全球人工智能竞赛中的地位,以及它与中…...
Java 大视界 -- Java 大数据在生物信息学中的应用与挑战(67)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
NeuIPS 2024 | CoT推理的新突破:推理边界框架(RBF)
近年来,大型语言模型(LLMs)在推理任务上的能力不断提升,尤其是 思维链(Chain-of-Thought, CoT) 技术,使得模型可以逐步推演逻辑,提高预测准确率。然而,当前的CoT推理仍然…...
【C】memory 详解
<memory.h> 是一个 C 标准库头文件,提供了一组内存管理函数,用于分配、释放和操作动态内存。这些函数主要操作的是未初始化的内存块,是早期 C 编程中常用的内存操作工具。 尽管在现代 C 编程中更推荐使用<cstring>或<memory&…...
linux——进程树的概念和示例
一些程序进程运行后,会调用其他进程,这样就组成了一个进程树。 比如,在Windows XP的“运行”对话框中输入“cmd”启动命令行控制台,然后在命令行中输入“notepad”启动记事本,那么命令行控制台进程“cmd.exe”和记事本进程“note…...
