RabbitMQ入门详解

前言

本篇文章将详细介绍rabbitmq的基本概念知识,以及rabbitmq各个工作模式在springboot中如何使用。

文章目录

介绍

简介

RabbitMQ 核心

生产者与消费者

Exchange

Queue

工作模式

简单模式

工作队列模式

发布订阅模式

路由模式

主题模式

SpringBoot中使用RabbitMQ

简单模式

基础配置

生产者

消费者

工作队列模式

发布/订阅模式(广播模式)

路由模式

主题模式


介绍

简介

RabbitMQ 是采用 Erlang 语言实现 AMQP(Advanced Message Queuing Protocol,高级消息队列协议)的消息中间件,它最初起源于金融系统,用于在分布式系统中存储转发消息。

RabbitMQ 发展到今天,被越来越多的人认可,这和它在易用性、扩展性、可靠性和高可用性等方面的卓著表现是分不开的。RabbitMQ 的具体特点可以概括为以下几点:

  • 可靠性: RabbitMQ使用一些机制来保证消息的可靠性,如持久化、传输确认及发布确认等。

  • 灵活的路由: 在消息进入队列之前,通过交换器来路由消息。对于典型的路由功能,RabbitMQ 己经提供了一些内置的交换器来实现。针对更复杂的路由功能,可以将多个交换器绑定在一起,也可以通过插件机制来实现自己的交换器。这个后面会在我们将 RabbitMQ 核心概念的时候详细介绍到。

  • 扩展性: 多个RabbitMQ节点可以组成一个集群,也可以根据实际业务情况动态地扩展集群中节点。

  • 高可用性: 队列可以在集群中的机器上设置镜像,使得在部分节点出现问题的情况下队列仍然可用。

  • 支持多种协议: RabbitMQ 除了原生支持 AMQP 协议,还支持 STOMP、MQTT 等多种消息中间件协议。

  • 多语言客户端: RabbitMQ几乎支持所有常用语言,比如 Java、Python、Ruby、PHP、C#、JavaScript等。

  • 易用的管理界面: RabbitMQ提供了一个易用的用户界面,使得用户可以监控和管理消息、集群中的节点等。在安装 RabbitMQ 的时候会介绍到,安装好 RabbitMQ 就自带管理界面。

  • 插件机制: RabbitMQ 提供了许多插件,以实现从多方面进行扩展,当然也可以编写自己的插件。感觉这个有点类似 Dubbo 的 SPI机制。

RabbitMQ 核心

生产者与消费者

RabbitMQ 整体上是一个生产者与消费者模型,主要负责接收、存储和转发消息。可以把消息传递的过程想象成:当你将一个包裹送到邮局,邮局会暂存并最终将邮件通过邮递员送到收件人的手上,RabbitMQ就好比由邮局、邮箱和邮递员组成的一个系统。

  • Producer(生产者) :生产消息的一方(邮件投递者)

  • Consumer(消费者) :消费消息的一方(邮件收件人)

消息一般由 2 部分组成:消息头(或者说是标签 Label)和 消息体。消息体也可以称为 payLoad ,消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括 routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。生产者把消息交由 RabbitMQ 后,RabbitMQ 会根据消息头把消息发送给感兴趣的 Consumer(消费者)。

Exchange

在 RabbitMQ 中,消息并不是直接被投递到Queue中的,中间还必须经过 Exchange(交换机) 这一层,Exchange 会把我们的消息分配到对应的Queue中。

Exchange用来接收生产者发送的消息并将这些消息路由给服务器中的队列中,如果路由不到,或许会返回给 Producer(生产者) ,或许会被直接丢弃掉 。这里可以将RabbitMQ中的交换器看作一个简单的实体。

RabbitMQ 的 Exchange(交换器) 有4种类型,不同的类型对应着不同的路由策略:direct(默认)fanout, topic, 和 headers,不同类型的Exchange转发消息的策略有所区别。

Queue

Queue(消息队列) 用来保存消息直到发送给消费者。RabbitMQ 中消息只能存储在队列中 ,它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。

多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(Round-Robin,即轮询)给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理,这样避免的消息被重复消费。

工作模式

简单模式

RabbitMQ简单模式,也称为基本模式(Basic Model),是RabbitMQ的最简单的消息传递模式,仅涉及到一个生产者和一个消费者。

在这个模式中,当我们启动一个程序作为生产者并向RabbitMQ发出消息时,我们希望它直接进入队列中,然后消费者会从队列中获取这个消息并进行处理。

简单模式在RabbitMQ中是一个单队列单生产者单消费者的模式,主要适用于单纯的任务处理,消息的生产者和消费者的削峰填谷能力非常高。

工作队列模式

RabbitMQ工作队列模式,也称为Task Queues或Background Tasks,是一种常见的应用场景,它用于处理大量的任务,将任务进行排队,然后分发给多个消费者进行处理。这种模式适用于需要异步处理耗时的、密集型任务并且要求可靠性的情况。

RabbitMQ工作队列模式的基本原理是,将需要处理的任务投递到RabbitMQ中,生成任务队列(Task Queues),多个消费者通过拉取任务队列中的任务进行处理。

在RabbitMQ的工作队列模式中,队列中的每个消息都会分配给一个消费者进行处理。消费者可以是不同的进程、线程或服务,从而实现可扩展性和并行性。

在一个生产者-多个消费者的场景下,生产者只需要将消息发送到一个消息队列中,消费者会自动从队列中获取消息进行处理。如果存在多个消费者,队列中的消息将会被分摊给多个消费者进行处理,即实现了任务并行处理的功能。而且如果一个消费者挂掉,该消费者所占用的任务在一定的时间内不会被重新分配,即实现了任务可靠性处理的功能。

一般情况下,RabbitMQ的工作队列模式可以应用于以下场景:

  • 任务比较繁重,处理较慢
  • 任务多且耗时,无法同步处理
  • 需要执行一些必须的后台任务,如发送邮件、生成报表等

发布订阅模式

RabbitMQ发布/订阅模式,也叫做“广播(Broadcast)模式”,是RabbitMQ的一种高级消息传递模式,主要用于广播消息。

在发布/订阅模式中,消息发送到Exchange(交换机)上,并携带着一个Routing Key(路由键),Exchange将收到的消息转发到绑定在它上面的所有队列。每个绑定键(Binding Key)都与一个队列相关联,而队列和消息的接收者实现了完全解耦,接收者只需要订阅(subscribe)与该队列相关联的绑定键即可。

我们将它作为“广播”模式,因为可以将一条消息同时发送到多个消费者。例如,我们可以让多个消费者接收网站上发布的新闻消息。

发布/订阅模式在RabbitMQ中的架构非常简单,主要可以描述为以下四个步骤:

  • 生产者将消息发送到exchange中,并指定了Routing Key。
  • Exchange将消息分发到所有绑定它的队列上。
  • 消费者从队列中接收消息,并进行处理。
  • 消费者对队列进行确认操作,告诉RabbitMQ该消息已经被接收并处理。

路由模式

RabbitMQ路由模式是一种高级消息传递模式,它可以通过选择路由键(Routing Key)将消息推送到绑定键(Binding Key)与之匹配的队列中,以满足不同的消费者需要。

路由模式主要用于单一应用程序内的消息传递,生产者将消息发送到指定的Exchange(交换机)中,并且Exchange会根据Routing Key将消息放到绑定到Exchange上的队列中。而不同的消费者使用不同的Binding Key来决定与哪个队列建立联系并接收消息。

在RabbitMQ中,路由模式有以下几个步骤:

  • 生产者将消息发送到Exchange中,并指定了Routing Key。
  • Exchange将消息根据Routing Key发送到绑定到Exchange中的队列。
  • 消费者从队列中接收消息,并进行处理。
  • 消费者对队列进行确认操作,告诉RabbitMQ该消息已经被接收并处理。

主题模式

RabbitMQ主题模式(Topic Model)是一种高级消息传递模式,它使你可以订阅一个特定的主题(Topic)并接收所有与该主题相关的消息。主题模式是在发布/订阅模式基础上进一步增强了消息传递的粒度。

在主题模式中,Exchange不仅可以使用Routing Key来将消息传递到队列中,还可以使用一个模式字符串来匹配Routing Key,这个模式字符串被称为主题(Topic)。消费者可以通过订阅不同的主题来接收不同的消息。

一个主题可以包含一个或多个单词(Word),单词之间使用"."(点号)来分割。通配符符号“#”表示跟单词数不限,而“”则表示只匹配一个单词。

主题模式在RabbitMQ中的架构非常简单,主要可以描述为以下四个步骤:

  • 生产者将消息发送到Exchange中,并指定了Routing Key。
  • Exchange将消息根据匹配的主题字符串发送到绑定到Exchange中的队列。
  • 消费者从队列中接收消息,并进行处理。
  • 消费者对队列进行确认操作,告诉RabbitMQ该消息已经被接收并处理。

SpringBoot中使用RabbitMQ

在使用之前先要确保在电脑中已经安装了rabbitmq,并启动服务,启动成功后是可以在本地15672端口中访问到网页的。如图:

简单模式

基础配置

首先创建两个SpringBoot项目,一个作为消费者,一个作为生产者,并导入依赖项。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

 在两个项目的yaml文件中写入rabbitmq的配置信息

spring:rabbitmq:host: localhost # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机username: guest # 用户名password: guest # 密码

在rabbitmq中创建一个队列叫做queue1

生产者

在生产者中编写测试类,发送消息

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class RabbitPublisherApplicationTests {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void SimpleQueue(){//队列名字String name = "queue1";//具体的消息String message = "你好!!!rabbit";//发送消息rabbitTemplate.convertAndSend(name,message);}
}

执行测试类后在rabbitmq的相应队列中就会有消息了。

消费者

随后编写消费者来消费消息。

创建一个监听类,来监听具体的队列

@Component
public class SpringRabbitListener {/*** 从队列queue1中取消息* @param msg*/@RabbitListener(queues = "queue1")public void listenSimpleQueueMessage(String msg) {System.out.println("spring 消费者接收到消息:" + msg);}
}

随后启动消费者项目,就可以从队列中成功获取到消息了。

工作队列模式

编写方法发送20条消息

    @Testpublic void WorkQueue(){String name = "work.queue";for(int i=0;i<20;i++){String message = "第"+i+"消息";rabbitTemplate.convertAndSend(name,message);}}

用两个消费者来接收

    @RabbitListener(queues = "work.queue")public void listenWorkQueueMessage1(String msg) {System.out.println("第一位消费者接收到消息:" + msg);}@RabbitListener(queues = "work.queue")public void listenWorkQueueMessage2(String msg) {System.out.println("第二位消费者接收到消息:" + msg);}

先启动消费者再发送消息:

此时可以发现两个消费者将消息均匀分配,每位各接收10条消息,这里是因为mq有预分配,会先预取,每个消费者和队列中有一个通道,存放预取的消息,所以会平均分消息,然后各自独立消费。

但是假如我们的消费者消费能力不一样呢,rabbitmq也会将其平均分配,这样的机制显然是不合理的,因此面对这种情况时,可以通过控制预取数量来改变这种情况,我们可以在yml文件中编写配置。这样就实现了取一个消费一个,不会先预取很多个,如果消费能力强取得就快,消费能力弱,取得就慢。

spring:rabbitmq:host: localhost # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机username: guest # 用户名password: guest # 密码listener:simple:prefetch: 1

发布/订阅模式(广播模式)

广播模式使用fanout交换机

首先编写一个配置类,配置交换机和队列

@Configuration
public class FanoutConfig {//声明交换机,设置名称@Beanpublic FanoutExchange fanoutExchange() {return new FanoutExchange("exchange1");}//队列1@Beanpublic Queue fanoutQueue1() {return new Queue("fanout1",true);}//绑定队列1和交换机@Beanpublic Binding binding1() {return BindingBuilder.bind(fanoutQueue1()).to(fanoutExchange());}//队列2@Beanpublic Queue fanoutQueue2() {return new Queue("fanout2",true);}//绑定交换机和队列2@Beanpublic Binding bindingQueue2() {return BindingBuilder.bind(fanoutQueue2()).to(fanoutExchange());}
}

发送消息

    @Testpublic void fanout(){String name = "exchange1";String meg = "这里时fanout";rabbitTemplate.convertAndSend(name,"",meg);}

接收消息

    @RabbitListener(queues = "fanout1")public void listenWorkQueueMessage1(String msg) {System.out.println("第一位消费者接收到消息:" + msg);}@RabbitListener(queues = "fanout2")public void listenWorkQueueMessage2(String msg) {System.out.println("第二位消费者接收到消息:" + msg);}

结果我们可以看到两个消费者都接收到了消息。

路由模式

路由模式使用direct交换机,除了使用配置类的方式进行队列和交换机的绑定,还可以在消费者中使用注解的方式,例如

    @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),exchange = @Exchange(name="direct",type = ExchangeTypes.DIRECT),key = {"one","two"}))public void directListener1(String msg){System.out.println("第一位消费者接收到来自direct.queue1的消息:"+ msg);}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),exchange = @Exchange(name="direct",type = ExchangeTypes.DIRECT),key = {"three"}))public void directListener2(String msg){System.out.println("第二位消费者接收到来自direct.queue2的消息:"+ msg);}

发送消息

    @Testpublic void directTest(){// 交换机名称String exchangeName = "direct";// 消息String message = "第 one 消息";// 发送消息rabbitTemplate.convertAndSend(exchangeName, "one", message);// 消息String message2 = "第 two 消息";// 发送消息rabbitTemplate.convertAndSend(exchangeName, "two", message2);// 消息String message3 = "第 three 消息";// 发送消息rabbitTemplate.convertAndSend(exchangeName, "three", message3);}

最后可以看到,根据key路由接收到了消息。

主题模式

主题模式和路由模式类似,使用topic交换机,只是可以在key中使用通配符,

主题模式中RoutingKey一般由一个或多个单词组成,用“.”分割。

通配符规则

# 匹配一个或多个词

* 匹配一个词

修改消费者配置

    @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue1"),exchange = @Exchange(name="topic",type = ExchangeTypes.TOPIC),key = {"a.*"}))public void topicListener1(String msg){System.out.println("第一位消费者接收到来自topic.queue1的消息:"+ msg);}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue2"),exchange = @Exchange(name="topic",type = ExchangeTypes.TOPIC),key = {"a.#"}))public void topocListener2(String msg){System.out.println("第二位消费者接收到来自topic.queue2的消息:"+ msg);}

发送消息

    @Testpublic void topicTest(){// 交换机名称String exchangeName = "topic";String message = "消息:a.b";rabbitTemplate.convertAndSend(exchangeName, "a.b", message);String message2 = "消息:a.b.c";rabbitTemplate.convertAndSend(exchangeName, "a.b.c", message2);String message3 = "消息:a.b.c.d";rabbitTemplate.convertAndSend(exchangeName, "a.b.c.d", message3);}

最后结果可以看到,第二个消费者可以拿到所有消息,第一个消费者只能拿到a.b的消息

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

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

相关文章

扭蛋机潮玩小程序搭建,扭蛋机行业的创新

在当下潮玩市场中&#xff0c;扭蛋机具有盲盒的未知性和惊喜体验感&#xff0c;商品丰富&#xff0c;并且价格相对低廉&#xff0c;获得了极高的人气。年轻人开始对扭蛋机逐渐“上头”&#xff0c;为了扭到喜欢的商品不断地进行复购下单&#xff0c;在这场随机性的扭蛋游戏中&a…

【故障排查】Docker启动Nacos报错:No DataSource set 问题解决

Nacos报错内容 Nacos Server did not start because dumpservice bean construction failure : No DataSource set原因分析 Nacos 配置的是单机模式&#xff0c;使用mysql 进行存储配置文件&#xff0c;Nacos的启动脚本已经配置了MySQL的连接方式&#xff0c;根据错误提示&a…

Window下安装Zookeeper

一、下载 地址&#xff1a;https://archive.apache.org/dist/zookeeper/zookeeper-3.5.6/ 解压&#xff1a;非中文、没有空格目录下 新建data目录&#xff0c;用于存放数据文件 二、配置 进入conf目录&#xff0c;复制zoo_sample.cfg 为zoo.cfg 打开zoo.cfg 修改dataDir&…

江苏科技大学24计算机考研数据速览,有专硕复试线大幅下降67分!

江苏科技大学&#xff08;Jiangsu University of Science and Technology&#xff09;&#xff0c;坐落在江苏省镇江市&#xff0c;是江苏省重点建设高校&#xff0c;江苏省人民政府与中国船舶集团有限公司共建高校&#xff0c;国家国防科技工业局与江苏省人民政府共建高校 &am…

层次分析模型

一、算法简介 决策问题&#xff1a;面临多种方案&#xff0c;需要根据一定的标准选择某一种方案 归一化处理(让指标在同一数量级&#xff0c;且保证在同一指标下其差距不变)&#xff1a; 给指标加上权重&#xff08;加权&#xff09; 科学地设定权重&#xff1f; 二、python…

2. 深度学习的项目流程(批量化打包数据、构建模型、训练模型、波士顿房价预测、激活函数、多层感知机)

深度学习流程 1. 深度学习基本流程1.1 流程图1.2 代码实现1.3 基本概念 2. 深度学习项目流程2.1 批量化打包数据2.2 构建模型2.3 训练模型&#xff08;1&#xff09;筹备训练&#xff08;2&#xff09;开始训练 2.4 模型推理 3. 深度学习实现波士顿房价预测3.1 数据读取、切分、…

数据库之PHP联动

目录 一、软件安装 二、软件讲解 三、搭配环境 四、编辑软件配置 五、成果展示 如果有人问&#xff1a;为什么非要用xampp、VS code编辑软件?不用phpstudy等其他工具。 那么我只想说&#xff1a;因为xampp、VS code编辑软件免费(ಡωಡ)hiahiahia 一、软件安装 下载连…

Java语言程序设计基础篇_编程练习题**15.19 (游戏:手眼协调)

**15.19 (游戏:手眼协调) 请编写一个程序&#xff0c;显示一个半径为10像素的实心圆&#xff0c;该圆放置在面板上的随机位置&#xff0c;并填充随机的顔色&#xff0c;如图15-29b所示。单击这个圆时&#xff0c;它会消失&#xff0c;然后在另一个随机的位置显示新的随机颜色的…

Python task

任务1 实现wordcount&#xff1a; 代码如下&#xff1a; import re def wordcount(text):#全部小写text text.lower()text re.sub(r[^\w\s], , text)#切分words text.split()#计算频率word_count {}for word in words:if word in word_count:word_count[word] 1else:wo…

MPI框架以及PIPE数据流向细节

一、海思MPP内部处理流程图 各模块功能介绍&#xff1a; &#xff08;1&#xff09;VI:捕获视频图像&#xff0c;可对其做剪切、缩放、镜像等处理&#xff0c;并输出多路不同分辨率的图像数据. &#xff08;2&#xff09;AI:捕获⾳频数据&#xff0c;然后AENC 模块⽀持按多种⾳…

华盈生物-小分子靶点筛选服务:助力药物发现的利器

在药物发现的过程中&#xff0c;确定小分子化合物的靶点是至关重要的一步。华盈生物为科学家们提供了两种高效的小分子靶点筛选方案&#xff0c;助力研究人员精准锁定靶点&#xff0c;加速新药研发进程。 方案一&#xff1a;荧光标记与HuProt人类蛋白质组芯片结合 华盈生物的H…

lua 游戏架构 之 游戏 AI (三)ai_attack

这段Lua脚本定义了一个名为 ai_attack 的类&#xff0c;继承自 ai_base 类。 lua 游戏架构 之 游戏 AI &#xff08;一&#xff09;ai_base-CSDN博客文章浏览阅读119次。定义了一套接口和属性&#xff0c;可以基于这个基础类派生出具有特定行为的AI组件。例如&#xff0c;可以…

MongoDB教程(十六):MongoDB高级索引

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、全文索…

开源软件项目:趋势、参与经验与收获

在当今这个全球经济与科技日新月异的时代&#xff0c;开源软件项目&#xff08;Open Source Software, OSS&#xff09;正以前所未有的速度蓬勃发展&#xff0c;成为推动技术创新、促进产业合作、加速知识共享的重要力量。随着云计算、大数据、人工智能等技术的兴起&#xff0c…

matlab 绘制参数方程

matlab 绘制参数方程 绘制参数方程绘制结果 绘制参数方程 clc; clear; close all;axis_length 100;% 定义参数t的范围 t 0:0.01:100;% 计算x和y的值 x t.^2 1; y 4*t - t.^2;% 绘制函数图像 plot(x, y); xlabel(x); ylabel(y); title(Plot of the curve xt^21, y4t-t^2…

机器学习之主成分分析案例-红酒主成分分析

&#x1f377; 机器学习实战&#xff1a;使用PCA与sklearn红酒数据集进行特征降维与模型预测对比 在机器学习中&#xff0c;主成分分析&#xff08;PCA&#xff09;是一种有效的降维技术&#xff0c;它通过寻找数据中的主成分来减少特征数量&#xff0c;同时尽量保留数据的结构…

人工智能全景图2.0 | 一文了解人工智能学科

大家好&#xff0c;这是一节人工智能的科普视频&#xff0c;试图用40多分钟的时间&#xff0c;带你宏观了解人工智能学科&#xff0c;对人工智能有个初步的、全景式的把握&#xff0c;这对你学习具体人工智能细节大有裨益&#xff0c;也是我珍贵的总结。 视频链接&#xff08;建…

灰色关联分析【系统分析+综合评价】

系统分析&#xff1a; 判断哪个因素影响最大 基本思想&#xff1a;根据序列曲线几何形状的相似程度来判断其练习是否紧密 绘制统计图并进行分析 确定子序列和母序列 对变量进行预处理&#xff08;去量纲、缩小变量范围&#xff09; 熟练使用excel与其公式和固定&#xff08…

一套成熟的实验室信息管理系统源码,.Net 检验系统LIS源码,实现从采集、检测、报告、归档的全程跟踪管理

一套成熟的实验室信息管理系统源码。在长期的医疗信息化实践中&#xff0c;我们分析总结了大量客户实例&#xff0c;建立了以病人为中心、以业务处理为基础、以提高检验科室管理水平和工作效率为目标的产品开发思路&#xff0c;将医学检验、科室管理和财务统计等检验科室/实验室…

电脑基础知识 | 电脑的基本组成

电脑作为我们日常工作和娱乐的重要工具&#xff0c;扮演着举足轻重的角色。当我们谈论电脑的基本组成时&#xff0c;其实是在探讨电脑硬件和软件两个核心部分。硬件是电脑看得见、摸得着的物理设备&#xff0c;而软件则是运行在这些硬件之上的程序和指令。两者相辅相成&#xf…