RabbitMQ消息队列实战(1)—— RabbitMQ的体系

news2024/11/26 2:24:16

RabbitMQ是一个开源的消息代理和队列服务器,用来在不同的应用之间共享数据。1983年,被认为是RabbitMQ的雏形的Teknekron创建,首次提出了消息总线的概念。中间经历过数个阶段的发展,一直到2004年,AMQP(Advanced Message Queuing Protcol)协议开发完成,这是一款具有开放标准的通信协议,它允许任何人都可以执行这一标准,编码标准的任何人都可以和任何AMQP供应商提供的MQ服务器进行交互。直到2007年,RabbitMQ 1.0正式诞生,RabbitMQ开始在金融、电信领域大面积的使用。

RabbitMQ使得生产者和消费者真正做到了解耦。引入了代理服务器,可以实现高可用和弹性的横向拓展。通过增加服务器实例的方式,RabbitMQ可以做到每秒处理百万级别的消息。本文主要介绍RabbitMQ的逻辑体系结构,先是简单介绍其整个体系架构以及相关名词的介绍,然后介绍RabbitMQ三种消息路由的方式(因第四种Header模式基本不会使用,这里不包括在内),最后介绍其典型的应用场景。

一、RabbitMQ的体系架构

我们知道RabbitMQ最初被用来主要是做应用之间的解耦,所以它的整体的架构大概分为三个部分:生产者(Publisher),消费者(Consumer)和消息代理(Broker)。其中最核心的是消息代理,其内部结构稍显复杂,主要针对不同的应用场景,实现不同的消息处理逻辑。我们先来看下RabbitMQ的逻辑架构图:

下面,分别对这些名词进行解释:

Publisher:消息的生产者

Broker:消息代理,通常是一个服务实体。

VHost:Virtual Host,主要用来隔离一批交换机、队列,在每个虚拟主机中都可以创建自己的交换机、队列和绑定,虚拟主机之间互相不可见。

Connection:一个网络连接

Channel:信道,AMQP中引入了信道进行消息的传递。主要是因为操作系统中创建和销毁一个TCP连接代价非常昂贵,信道的引入就是为了复用一个TCP连接,通过多线程的方式来传递消息。通常情况下,一个信道对应一个线程。

Exchange:用来接受消息,并负责把消息传递给队列。

Queue:用来存放消息的容器。

Binding:用来关联交换机和队列的绑定,只有绑定了之后,交换机才知道向哪个队列发送消息。

二、RabbitMQ的路由策略

根据交换机的类型,RabbitMQ的的路由策略可以分为三种:直连默认(Direct)、主题模式(topic)、广播模式(fanout)。接下来,我们分别进行介绍。不过,在此之前,我们需要先了解下RabbitMQ的消息发布的命令,因为结合这个命令,我们才能购真正理解RabbitMQ这几种路由策略的原理,笔者以Java代码的API来解释这个命令:

channel.basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body);

exchange:交换机的名称,在直连模式下为空。

routingKey:路由键,直连模式下是队列的名称,主题模式下是主题的名称,广播模式下为空。

props:发送消息时附带的一些附加参数

body:发送的消息转换成的二进制数组

2.1 直连模式

所谓的直连模式,就是直连交换机直接将消息路由到对应的队列中。在直连模式下,使用basicPublish在publish消息时,routingKey必须设置成目标队列的名称。而exchange可以设置成我们创建的直连交换机的名称,如果设置则使用RabbitMQ安装时默认的直连交换机。

要想使用直连模式路由消息,必须先创建直连交换机。当安装完成RabbitMQ后,会默认创建1个直连交换机(下图中圈出部分),如果我们在basicPublish时不指定交换机名称,会使用这个默认交换机(直连模式下):

除此之外,我们也可以创建支持直连模式的交换机,如下:

channel.exchangeDeclare("my-direct-exchange", "direct", true, false, null);

如上,我们创建了一个名称为my-direct-exchange的交换机,第二个参数指定了交换机的类型为direct类型。完成了交换机的创建之后,接下来创建一个队列my-queue用来接受交换机的消息:

channel.queueDeclare("my-queue", true, false, false, null);

最后,创建一个binding,将交换机和队列关联起来:

channel.queueBind("my-queue", "my-direct-exchange", "my-queue");

queueBind的第1个参数是要关联的队列名称,第2个参数是要关联的交换机名称,第三个参数是路由键,在直连模式下要填写队列名称。

完成了上述的过程之后,我们就创建了一套完整的直连交换机、队列和绑定,实现了以direct的方式路由消息。发布消息时,路由键填写队列名称:

channel.basicPublish("direct-exchange", "my-queue",...);

2.2 主题模式

RabbitMQ的第二种路由模式是topic模式,topic类型的交换机会根据发送消息的topic寻找使用binding绑定了该topic的的队列,然后将消息路由到该队列上。

需要注意的是,这种交换机和队列的关系是一对多的,也就是是说,多个队列可以通过同一个主题和同一个交换机绑定:

使用主题模式的路由策略,同样先创建topic类型的交换机:

channel.exchangeDeclare("topic-exchange", "topic", true, false, null);

topic-exchange:交换机名称

topic:交换机类型,固定是topic

队列的创建,这里不再演示,因为队列没有direct、topic和fanout类型之分,我们还是沿用上面创建的队列my-queue来进行接下来的说明。与direct路由策略的bind不同,在为topic交换机和队列创建bind时要明确得指出主题:

channel.queueBind("my-queue", "topic-exchange", "fruit");

可以看到,在第3个参数路由键中,我们明确得指出了topic为fruit。

然后,在发布消息时,也要明确得指出消息的topic:

channel.basicPublish("topic-exchange", "fruit",...);

2.3 广播模式

RabbitMQ最后一种路由策略是fanout模式,该模式的路由原理如下图:

在该模式下,只要将队列和fanout交换机进行了绑定,那么向fanout交换机发布的所有的消息都会路由到所有绑定的队列中。与之前创建两种类型的交换机类似,创建fanout交换机时,需要指定交换机的类型为fanout:

channel.exchangeDeclare("fanout-exchange", "fanout", true, false, null);

在创建bind时不需要指定路由键:

channel.queueBind("my-queue", "fanout-exchange", "");

在发布消息时,同样不需要指定路由键,fanout 交换机会把消息发送到所有绑定它上面的队列中:

channel.basicPublish("fanout-exchange", "", ...);

2.4 关于Exchange、Queue和Bind之间的关系

可能刚刚接触RabbitMQ的童鞋,会被这三者的关系绕晕。我最开始学习RabbitMQ时,也是花了很长时间才把这三者之间的关系梳理清楚。笔者这里所说的关系,是指1个Exchange对应1个Queue,或者1个Exchange对应多个Queue等这种数量上的对应关系。针对这种关系,最终我发现了一个事实,总结如下:

(1)三者之间这种数量上的对应关系和RabbitMQ的路由策略以及Exchange的类型无关。只要保证一个bind对应在创建时绑定了一个exchange和一个queue即可。

(2)一个exchange可以和多个queue通过多个bind对象绑定,不管exchange是什么类型。

(3)一个queue可以和多个exchange通过多个bind对象绑定,不管exchange是什么类型。

三、RabbitMQ的应用场景

笔者,根据RabbitMQ的特性和使用目的,将RabbitMQ的应用场景归为了三类:

  • 将消费者和生产者解耦。

这是RabbitMQ被提出来最基本也是最初的目的。通过这种解耦,至少可以实现两种效果:

(1)原本需要轮询获取生产者消息的消费者代码,可以通过监听RabbitMQ队列实现有消息才处理,从而省去了轮询的过程。

(2)通过RabbitMQ主题交互机或者广播交换机,可以轻松实现当有新的消费者加入时,而不需要修改生产者代码。比如在充值时,我们可以发送一个充值事件,日志服务捕获充值事件后写入日志。如果后面有新的需求,比如积分服务,只需要新增积分服务即可,无需修改生产者代码。

  • 实现分布式事务

实现分布式事务。利用RabbitMQ代理可持久化,可做高可用以及消息的ack机制,可以实现分布式事务,比如saga模式,ebay的本地事务表。

  • 实现异步调用,提高性能。

在微服务架构的系统种,要实现某种业务往往需要调用多个其它服务的接口,如果采用同步调用的方式,需要在上一个接口调用完成之后再去调用下一个接口,性能势必不高。如果使用RabbitMQ作为代理进行异步调用,几乎可以实现和只调用一个接口同样的耗时。而且采用这种方式,还有一个好处,就是可以有选择地忽略完成该业务非必要地接口调用。

四、总结

本文主要介绍了RabbitMQ的体系结构、三种路由模式和应用场景,结合上文,现总结如下:

(1)RabbitMQ中通过vhost实现了数据的隔离,每个vhost下都有自己的exchange和queue,可以以vhost为单位对用户进行授权。

(2)RabbitMQ中有三种路由策略:

  • direct策略 —— 需要创建direct exchange,和queue绑定时指定路由键为队列名称,在发布消息时需要以目标队列的名称作为路由键。

  • topic策略 —— 需要创建topic exchange,和queue绑定时需要将明确的topic作为路由键,发布消息时需要将topic作为路由键。

  • fanout策略 —— 需要创建fanout exchange,和queue绑定时无需指定路由键,发布消息时无需指定路由键。

(3)一个exchange可以和多个queue通过多个bind对象绑定,不管exchange是什么类型。

(4)一个queue可以和多个exchange通过多个bind对象绑定,不管exchange是什么类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

02.指针的进阶

1.字符指针 在指针的类型中我们知道有一种指针类型为字符指针 char* ; 一般使用: int main() {char ch w;char *pc &ch;*pc w;return 0; } char * p---const char * p(因为常量字符串不能被修改) #include<stdio.h> int main() {const char * pstr "hel…

从汇编的角度了解C++原理——虚函数

文章目录1、虚函数1.1、虚函数储存结构1.2、子类重写虚函数1.3、在栈上调用虚函数1.4、在堆上调用虚函数(通过指针调用&#xff0c;多态)本文用到的反汇编工具是objconv&#xff0c;使用方法可以看我另一篇文章https://blog.csdn.net/weixin_45001971/article/details/12866064…

编译基于armV8架构的opencv,并在rock3a开发板上运行

近期在基于arm开发板做图像识别任务开发时&#xff0c;需要用到Opencv库 之前在做rknpu开发时&#xff0c;开发sdk里面已经集成了opencv 但是该opencv开发包不能实现imshow/VideoCapture等函数&#xff0c;经过调研&#xff0c;决定对opencv源代码进行编译&#xff0c;生成arm…

安科瑞能耗监测系统在新疆昌吉市政务中心项目的研究与应用

安科瑞 华楠摘要&#xff1a;大型公共建筑总面积不足城镇建筑总面积的4%&#xff0c;但总能耗却占全国城镇总耗电量的22%&#xff0c;大型公共建筑单位面积年耗电量达到70&#xff5e;300KWh&#xff0c;为普通居民住宅的10&#xff5e;20倍。公共建筑是节能大户和节能核心&…

Delphi 11.2 安装 CnWizards 组件包

官方网址&#xff1a;https://www.cnpack.org/showdetail.php?id900&langzh-cn 开源免费的组件包&#xff0c;大大提高了开发效率&#xff0c;再次感谢大佬们的无私奉献 这个组件包主要是为了实现一些delphi没有的便捷设置&#xff0c;以及能给delphi增加了一些好用的辅助…

惊艳的产品背后,是锐利的设计思维

缘起 几年前&#xff0c;我偶然用一个 叫 Zine 的小app 写了两篇文章&#xff0c;感觉非常好。 后来在网上认识 了Zine 团队的创始人 Louis&#xff0c;也喜欢上了他们的另一个 App&#xff1a;Varlens&#xff0c; 最近他们推出了记笔记的 App Lattics&#xff0c;一些功能也…

《 Unity Shader 入门精要》 第3章 Unity Shader 基础

第3章 Unity Shader 基础 3.1 Unity Shader 概述 材质与 Unity Shader 在 Unity 中我们通常需要将材质&#xff08;Material&#xff09; 和 Unity Shader 配合使用&#xff0c;常见流程如下&#xff1a; 创建一个材质创建一个 Unity Shader&#xff0c; 并将它赋给材质将材…

Android View类

布局定义了应用中的界面结构&#xff08;例如 Activity 的界面结构&#xff09;。布局中的所有元素均使用 View 和 ViewGroup 对象的层次结构进行构建。View 通常用于绘制用户可看到并与之交互的内容。ViewGroup 则是不可见的容器&#xff0c;用于定义 View 和其他 ViewGroup 对…

AppScan自定义扫描策略,扫描针对性漏洞

系列文章 AppScan介绍和安装 AppScan 扫描web应用程序 AppScan被动手动探索扫描 AppScan绕过登录验证码深入扫描 第五节-AppScan自定义扫描策略&#xff0c;扫描针对性漏洞 AppScan安全扫描往往速度是很慢的&#xff0c;有些场景下他的扫描项目又不是我们需要的&#xff0c;…

如何实现六轴机械臂的逆解计算?

1. 机械臂运动学介绍 机械臂运动学 机器人运动学就是根据末端执行器与所选参考坐标系之间的几何关系&#xff0c;确定末端执行器的空间位置和姿态与各关节变量之间的数学关系。包括正运动学&#xff08;Forward Kinematics&#xff09;和逆运动学&#xff08;Inverse Kinemati…

渔业养殖远程监控系统解决方案

传统的水产养殖依靠养殖者的经验进行观察&#xff0c;信息不准确&#xff0c;调控不及时&#xff0c;养殖规模扩大难&#xff0c;人工成本高。除此之外传统水产养殖以个户居多&#xff0c;生产管理方式粗放&#xff0c;个体生产能力不足&#xff0c;养殖产品的品质难以保障。 …

AppScan扫描报告

系列文章 AppScan介绍和安装 AppScan 扫描web应用程序 AppScan被动手动探索扫描 AppScan绕过登录验证码深入扫描 AppScan自定义扫描策略&#xff0c;扫描针对性漏洞 第六节-AppScan扫描报告 1.加载扫描结果 1.点击【打开】 2.选择之前保存过的扫描结果 3.等待加载完成 …

RK35XX(3568) Android WSL ubuntu22.04 编译环境配置

前言&#xff1a;装Ubuntu真机操作是很流畅但是没什么软件&#xff0c;装Vmware虚拟机操作卡顿配置也麻烦。那不如试一试wsl吧&#xff0c;命令行操作&#xff0c;流程又快捷wsl简介&#xff1a;适用于 Linux 的 Windows 子系统可让开发人员按原样运行 GNU/Linux 环境 - 包括大…

JAVA面试(如何进行有效面试)

1、什么是面试它是一种面试人与求职者之间相互交流信息的有目的的会谈。它使招聘方和受聘方都能得到充分的信息&#xff0c;以在招聘中作出正确的决定。面试是一个双方彼此考量和认知的过程。2、面试的目标从求职者那里获取与个人行为、工作有关的信息&#xff0c;以确定求职者…

c语言数组复习

1、一维数组 ----------&#xff08;1&#xff09;、键盘输入 10 个数&#xff0c;求最大值和最小值&#xff08;最简单的方法&#xff09; ----------&#xff08;2&#xff09;、数组的逆置 #include<stdio.h> void test01() {int arr[10] { 0 };int n sizeof(arr)…

【IoT】硬件选型:如何正确区分电子线的端子型号?

问题提出 笔者最近负责的一款重力传感器由于没有端子&#xff0c;需要在生产时自己压端子&#xff0c;这个时候就会涉及端子的选择。 端子介绍 一般来说&#xff0c;端子有多种不同的型号&#xff0c;在使用的时候&#xff0c;你必须要注意到每种型号之间的差别。 端子一般有XH…

权限管理---尚硅谷

1.项目基础 2.定义统一返回结果对象 3.Nodejs 4.前端内容编写 5.菜单详情 6.SpringSecurity权限管理 7.添加登录日志 8.操作日志 9.后端打包 10.前端打包 11.动态sql日期的判断 项目基础 定义统一返回结果对象定义全局统一返回结果类 import lombok.Data;/*** 全局统一返回结果…

小程序容器技术助力突破智能汽车瓶颈

作为一种综合系统&#xff0c;智能车辆集环境感知、规划决策、多等级辅助驾驶等功能于一体。近年来&#xff0c;智能车辆已经成为世界车辆工程领域研究的热点和汽车工业增长的新动力&#xff0c;很多发达国家都将其纳入到各自重点发展的智能交通系统当中。在共享经济兴起和汽车…

如何写好JS

本节课从实践维度解读在实际编码过程中何种类型的 JavaScript 代码称之为“好代码”&#xff0c;并从 JS 出发&#xff0c;总结其他语言编码可遵循的共性原则&#xff0c;由浅入深&#xff0c;其三大原则是&#xff1a; 各司其职——html&#xff0c;css&#xff0c;js分离组件…

通达信接口QQ是什么端口?

可以将通达信接口QQ视为使用通达信市场软件作为数据库&#xff0c;然后将信息整合为策略的前提&#xff0c;所有行为都是自动化的。通达信接口的优势在于交易策略是事先制定的。是否基于市场波动&#xff0c;不受个人情绪的影响&#xff0c;可以大大降低个人原因造成的错误。 …