RabbitMQ 入门
目录
一:什么是MQ
二:安装RabbitMQ
三:在Java中如何实现MQ的使用
RabbitMQ的五种消息模型
1.基本消息队列(BasicQueue)
2.工作消息队列(WorkQueue)
3. 发布订阅(Publish、Subscribe)
4.Direct Exchange:路由
5.Topic Exchange:主题
在Java中实现五种模型
1.基本消息队列
2.工作消息队列
3.发布订阅模型--广播
4.发布订阅模型---路由
5.发布订阅模型----主题
一:什么是MQ
MQ,中文是消息队列(MessageQueue),字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。
比较常见的MQ实现:
-
ActiveMQ
-
RabbitMQ
-
RocketMQ
-
Kafka
几种常见MQ的对比:
| RABBITMQ | ACTIVEMQ | ROCKETMQ | KAFKA | |
|---|---|---|---|---|
| 公司/社区 | Rabbit | Apache | 阿里 | Apache |
| 开发语言 | Erlang(并发能力强,性能及其好) | Java | Java | Scala&Java |
| 协议支持 | AMQP,XMPP,SMTP,STOMP | OpenWire,STOMP,REST,XMPP,AMQP | 自定义协议 | 自定义协议 |
| 可用性 | 高 | 一般 | 高 | 高 |
| 单机吞吐量(性能承载能力) | 一般 | 差 | 高 | 非常高 |
| 消息延迟 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒以内 |
| 消息可靠性 | 高 | 一般 | 高 | 一般 |
追求可用性(当需要处理数据时,资源处于可用状态的程度):Kafka、 RocketMQ 、RabbitMQ
追求可靠性:RabbitMQ、RocketMQ
追求吞吐能力(十万级别的):RocketMQ、Kafka
追求消息低延迟:RabbitMQ、Kafka
二:安装RabbitMQ
我们将RabbitMQ安装在linux上使用以下两种方式可以安装(安装过程保证自己的docker容器一直是开着的)
第一种方法使用docker镜像,直接拉取安装即可
命令:docker pull rabbitmq:3.8-management
第二种方法 使用 本地下载
RabbitMQ的镜像包我已上传在我的个人博客资源中,将镜像包拖到tmp目录下
使用命令
//在线解压即可
docker load -i mq.tar
如下:
解压好后,接着输入以下命令
docker run \
# 设置环境变量 用户名是 dlwlrma
-e RABBITMQ_DEFAULT_USER=itcast \
# 设置环境变量 密码是 zhien0516
-e RABBITMQ_DEFAULT_PASS=123321 \
# 挂载数据卷,后面高级会用到下面的插件
-v mq-plugins:/plugins \
# mq的名字
--name mq \
# 主机名 这里不配置也可以,后期如果是集群必须配置
--hostname mq \
# web可视化终端监控端口;mq的ui界面管理平台端口
-p 15672:15672 \
# 程序与mq交互的访问端口;发消息和收消息的端口
-p 5672:5672 \
# 后端运行
-d \
# 镜像名称
rabbitmq:3.8-management
精简命令如下:
docker run \
-e RABBITMQ_DEFAULT_USER=dlwlrma\
-e RABBITMQ_DEFAULT_PASS=zhien0516 \
-v mq-plugins:/plugins \
--name mq \
--hostname mq \
-p 15672:15672 \
-p 5672:5672 \
-d \
rabbitmq:3.8-management
安装好后,可以在浏览器中输入自己的linux的ip地址访问即可出现以下画面,输入自己刚刚设置的用户名和密码即可成功登录

三:在Java中如何实现MQ的使用
RabbitMQ的五种消息模型
1.基本消息队列(BasicQueue)

P(producer/ publisher):生产者,一个发送消息的用户应用程序。我们自己书写代码发送。
C(consumer):消费者,消费和接收有类似的意思,消费者是一个主要用来等待接收消息的用户应用程序。我们自己书写代码接收。
队列(红色区域):存在于rabbitmq内部。许多生产者可以发送消息到一个队列,许多消费者可以尝试从一个队列接收数据。
总之:生产者将消息发送到队列,消费者从队列中获取消息,队列是存储消息的缓冲区。
2.工作消息队列(WorkQueue)

工作消息队列是基本消息队列的增强版,具有多个消费者消费队列的消息。假设消息队列中积压了多个消息,那么此时可以使用多个消费者来消费队列中的消息。效率要比基本消息队列模型高。
3. 发布订阅(Publish、Subscribe)
又根据交换机类型不同分为三种:
但是三种类型都有一个共性:
1、1个生产者,多个消费者
2、每一个消费者都有自己的一个队列
3、生产者没有将消息直接发送到队列,而是发送到了交换机
4、每个队列都要绑定到交换机
5、生产者发送的消息,经过交换机到达队列,实现一个消息被多个消费者获取的目的
X(Exchanges):交换机一方面:接收生产者发送的消息。另一方面:知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失
广播类型:

将消息交给所有绑定到交换机的队列,生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。交换机把消息发送给绑定过的所有队列.队列的消费者都能拿到消息。实现一条消息被多个消费者消费.
4.Direct Exchange:路由

1.在广播模式中,生产者发布消息,所有消费者都可以获取所有消息。
2.在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。在Direct模型下,队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key).消息的发送方在向Exchange发送消息时,也必须指定消息的routing key。
3.P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。
4.X:Exchange(交换机),接收生产者的消息,然后把消息递交给 与routing key完全匹配的队列
5.Topic Exchange:主题

1.Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符!
2.Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert
3.通配符规则:
#:匹配一个或多个词
*:匹配恰好1个词
在Java中实现五种模型
1.基本消息队列
消费者:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;//将当前类放到SpringIOC容器中
@Component
public class SpringRabbitListener {/**** @author dlwlrma* @date 2024/6/17 20:18* @param msg* TODO: @RabbitListener 为定义监听哪一个队列*/@RabbitListener(queues = {"simple.queue"})//Spring自动将接收的消息给方法参数msgpublic void listenSimpleQueueMessage(String msg) throws InterruptedException {System.out.println("spring 消费者接收到消息:【" + msg + "】");}
}
发布者:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;//TODO:是一个测试启动器,可以加载SpringBoot测试注解,让测试方法在Spring容器环境下执行
@RunWith(SpringRunner.class)
//TODO:目的是加载ApplicationContext,启动spring容器
@SpringBootTest
public class SpringAmqpTest {//自动装配RabbitTemplate模板对象@Autowiredprivate RabbitTemplate rabbitTemplate;/**** @author dlwlrma* @date 2024/6/17 20:23* TODO: Basic Queue 简单队列模型*/@Testpublic void testSimpleQueue() {//1.定义变量保存队列的名字String queueName = "simple.queue";//2.定义变量保存要发送的消息String message = "hello啊,我是mq,我发送的是简单队列模型";//3.发送消息rabbitTemplate.convertAndSend(queueName,message);}
}
2.工作消息队列
消费者:
@RabbitListener(queues = {"simple.queue"})public void listenWorkQueue1Message(String msg) throws InterruptedException {System.out.println("用户1已收到了消息:"+msg);//休眠20毫秒Thread.sleep(20);}@RabbitListener(queues = {"simple.queue"})public void listenWorkQueue2Message(String msg) throws InterruptedException {System.out.println("用户2已收到了消息:"+msg);//休眠100毫秒Thread.sleep(100);}
发布者:
/**** @author dlwlrma* @date 2024/6/17 20:24* TODO:workQueue 向队列中不停发送消息,模拟消息堆积。*/@Testpublic void testWorkQueue() throws InterruptedException {//1.定义变量保存队列的名字String queueName = "simple.queue";//2.定义变量保存要发送的消息String message = "我是mq,我发送的是hello_message_";//3.发送消息for (int i = 1; i <=50 ; i++) {rabbitTemplate.convertAndSend(queueName,message+i);//4.模拟每隔20毫秒发送一次Thread.sleep(20);}}
3.发布订阅模型--广播
定义绑定类:将交换机与多个队列绑定起来
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FanoutConfig {//1.定义交换机的名字@Beanpublic FanoutExchange fanoutExchange(){return new FanoutExchange("dlwlrma.fanout");}//2.定义队列1@Beanpublic Queue fanoutQueue1(){return new Queue("fanout.queue1");}//3.将交换机与队列绑定起来@Beanpublic Binding bindingExchangeToFanoutQueue1(FanoutExchange fanoutExchange,Queue fanoutQueue1){//将队列1与交换机绑定起来return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);}//4.定义队列2@Beanpublic Queue fanoutQueue2(){return new Queue("fanout.queue2");}//3.将交换机与队列绑定起来@Beanpublic Binding bindingExchangeToFanoutQueue2(FanoutExchange fanoutExchange,Queue fanoutQueue2){//将队列2与交换机绑定起来return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);}}
消费者:
/**** @author dlwlrma* @date 2024/6/17 22:14* @param msg* TODO:模拟订阅发布:广播类型*/@RabbitListener(queues = {"fanout.queue1"})public void listenFAnoutQueue1Message(String msg) {System.out.println("用户1已收到了消息:"+msg);}@RabbitListener(queues = {"fanout.queue2"})public void listenFAnoutQueue2Message(String msg) {System.out.println("用户2已收到了消息:"+msg);}
发布者:
/**** @author dlwlrma* @date 2024/6/17 20:24* TODO: Fanout Exchange:广播*/@Testpublic void testFanoutExchange() {//1.定义变量保存交换机名字String exchangeName = "dlwlrma.fanout";//2.定义变量保存要发送的信息String message = "hello,我是订阅发布";//3.发送消息//第二个参数为广播类型rabbitTemplate.convertAndSend(exchangeName,"",message);}
4.发布订阅模型---路由
用基于注解的方式定义交换机和队列在consumer的SpringRabbitListener中添加两个消费者
/**** @author dlwlrma* @date 2024/6/18 23:42* @param msg * TODO: 1. value = @Queue(name = "direct.queue1") 表示绑定的第一个队列* 2.exchange = @Exchange(name = "dlwlrma.direct", type = ExchangeTypes.DIRECT) 表示交换机名和类型* 3.key = {"red", "blue"} 表示路由key*/@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),exchange = @Exchange(name = "dlwlrma.direct", type = ExchangeTypes.DIRECT),key = {"red", "blue"}))public void listenDirectQueue1(String msg){System.out.println("消费者接收到direct.queue1的消息:【" + msg + "】");}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),exchange = @Exchange(name = "dlwlrma.direct", type = ExchangeTypes.DIRECT),key = {"red", "yellow"}))public void listenDirectQueue2(String msg){System.out.println("消费者接收到direct.queue2的消息:【" + msg + "】");}
发布者:
/**** @author dlwlrma* @date 2024/6/17 20:24* TODO:Direct Exchange:路由*/@Testpublic void testSendDirectExchange() {// 交换机名称String exchangeName = "dlwlrma.direct";// 消息String message = "红色警报!惊险大怪兽!";// 发送消息rabbitTemplate.convertAndSend(exchangeName, "red", message);}
5.发布订阅模型----主题
消费者:
/**** @author dlwlrma* @date 2024/6/18 23:42* @param msg* TODO: 1.value = @Queue(name = "topic.queue1") 表示绑定的第一个队列* 2.exchange = @Exchange(name = "dlwlrma.topic", type = ExchangeTypes.TOPIC) 表示交换机名和类型* 3. key = "china.#" 表示路由key只要以china开始都会接收*/@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue1"),exchange = @Exchange(name = "dlwlrma.topic", type = ExchangeTypes.TOPIC),key = "china.#"))public void listenTopicQueue1(String msg) {System.out.println("消费者接收到topic.queue1的消息:【" + msg + "】");}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue2"),exchange = @Exchange(name = "dlwlrma.topic", type = ExchangeTypes.TOPIC),key = "#.news"))public void listenTopicQueue2(String msg) {System.out.println("消费者接收到topic.queue2的消息:【" + msg + "】");}
发布者:
/**** @author dlwlrma* @date 2024/6/17 20:25* Topic Exchange:主题*/@Testpublic void testSendTopicExchange() {// 交换机名称String exchangeName = "dlwlrma.topic";// 消息String message = "喜报!孙悟空大战哥斯拉,胜!";// 发送消息rabbitTemplate.convertAndSend(exchangeName, "china.news", message);}相关文章:
RabbitMQ 入门
目录 一:什么是MQ 二:安装RabbitMQ 三:在Java中如何实现MQ的使用 RabbitMQ的五种消息模型 1.基本消息队列(BasicQueue) 2.工作消息队列(WorkQueue) 3. 发布订阅(Publish、S…...
物联网协议应用
目录 前言一、WIFI简介二、NTP协议2.1 NTP简介2.2 NTP实现 三、HTTP协议3.1 HTTP协议简介3.2 HTTP服务器 四、MQTT协议4.1 MQTT协议简介4.1.1 MQTT通信模型4.1.2 MQTT协议实现原理4.1.3 MQTT 控制报文 4.2 移植MQTT协议 前言 本文主要介绍一下物联网协议如NTP协议、HTTP协议和M…...
十分钟学会微调大语言模型
有同学给我留言说想知道怎么训练自己的大语言模型,让它更贴合自己的业务场景。完整的大语言模型训练成本比较高昂,不是我们业余玩家能搞的,如果我们只是想在某个业务场景或者垂直的方面加强大模型的能力,可以进行微调训练。 本文…...
结合简单工厂和工厂方法模式:实现灵活的对象创建
前言 在软件开发过程中,创建对象的方式直接影响代码的灵活性和可维护性。设计模式提供了一种解决复杂问题的方法,其中简单工厂模式和工厂方法模式是两种常用的创建型模式。在这篇文章中,我们将结合这两种模式,通过一个实际案例&a…...
网抑云特殊版,登录即永久
前言 今天分享一款特殊版本的音乐软件,相信大家在听网抑云的时候会有两大烦恼, 一是歌曲需要开通VIP才可以收听,不管怎么说也是国内厂商普遍操作 但是第二种烦恼你万万想不到的是,开通了会员后,惊奇的发现ÿ…...
Kotlin 实战小记:No-Arg 引用解决 No constructor found的问题
一、问题 新的项目试用一下kotlin, 调用数据库查询数据的时候报了这个问题:org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: No constructor found in com.neusoft.collect.entity.cm.CmRoom matc…...
HTML(5)——列表表格
列表 无序列表 作用:布局排列整齐的不需要规定顺序的区域。 标签:ul嵌套il,ul是无序列表,li是列表条目 注:ul标签只能包裹li标签,li标签可以包含任何内容 有序列表 作用:布局排列整齐的需…...
FreeBSD通过CBSD管理低资源容器jail来安装Ubuntu子系统实践
简介 FreeBSD、CBSD、Jail和Ubuntu,四者的组合方案可以说是强强联合,极具性价比和竞争力!同时安装简单方便,整体方案非常先进。 CBSD是为FreeBSD jail子系统、bhyve、QEMU/NVMM和Xen编写的管理层。该项目定位为一个综合解决方案…...
SpringCloud总结(springcloud alibaba)
目录 版本说明(很重要) springcloud alibaba对应组件版本说明 简述 spring cloud albaba 几大模块 周会讨论 - spring cloud alibaba每周都会有周会讨论,社区活跃 spring cloud alibaba官网 注册配置中心 简单介绍 nacos 步骤 示例代码 依赖…...
轻轻松松上手的LangChain学习说明书
本文为笔者学习LangChain时对官方文档以及一系列资料进行一些总结~覆盖对Langchain的核心六大模块的理解与核心使用方法,全文篇幅较长,共计50000字,可先码住辅助用于学习Langchain。 一、Langchain是什么? 如今各类AI…...
全面对比与选择指南:Milvus、PGVector、Zilliz及其他向量数据库
本文全面探讨了Milvus、PGVector、Zilliz等向量数据库的特性、性能、应用场景及选型建议,通过详细的对比分析,帮助开发者和架构师根据具体需求选择最合适的向量数据库解决方案。 文章目录 向量数据库概述向量数据库的关键功能向量数据库的扩展和选择向量…...
svm 超参数
https://www.cnblogs.com/ChevisZhang/p/12932674.html https://wenku.baidu.com/view/b8a2c73cfd4733687e21af45b307e87100f6f861.html?wkts1718332423081&bdQuerysvm%E7%9A%84%E8%B6%85%E5%8F%82%E6%95%B0 用交叉验证找到最好的参数 C 和γ 。使用 RBF 核时,…...
001-基于Sklearn的机器学习入门:Sklearn库基本功能和标准数据集
本节将介绍Sklearn库基本功能,以及其自带的几个标准数据集的调用方法。本节是学习后面内容的基础,如果您已经对本节内容相当熟悉,可跳过本节内容。 1.1 Sklearn库基本功能 的 1.2 Sklearn库标准数据集 Sklearn自带许多标准数据集ÿ…...
充电学习—7、BC1.2 PD协议
BC1.2(battery charging)充电端口识别机制: SDP、CDP、DCP 1、VBUS detect:vbus检测 PD(portable device,便携式设备)中有个检测VBUS是否有效的电路,电路有个参考值,高…...
技术点梳理0618
ann建库,分布式建库,性能优化,precision recall参数优化 hnsw,图索引 1. build a)确定层:类似跳表思路建立多层,对每一个插入的节点,random层号l,从图的起始点search_…...
石英砂酸洗提纯方法和工艺
石英砂酸洗提纯方法和工艺是石英砂加工中至关重要的一个环节,其目的是通过化学手段去除石英砂中的杂质,提升其纯度。以下将详细介绍石英砂酸洗提纯的方法和工艺,以便更好地理解和应用这一技术。 一、概述 石英砂酸洗提纯主要是利用酸液对石英…...
linux安装dgl
1.DGL官网、选择与自己cuda、python版本匹配的dgl的whl文件CUDA11.8、python10并下载 2.用pip install运行 pip install /home/u2023170749/download/dgl-2.2.0cu118-cp310-cp310-manylinux1_x86_64.whl或者直接安装https://blog.csdn.net/weixin_44017989/article/details/13…...
【SAP-ABAP】-权限批导-批量给某个角色导入事务码权限
需求:SAP期初上线的时候,业务顾问经常会遇到批量创建角色和分配角色权限的情况 岗位需求:一般是业务顾问定义权限,BASIS进行后期运维,今天讲两个批导功能,方便期初上线 主要函数:PRGN_READ_ROLE…...
异常处理总结
自定义异常 系统中的异常可以分为我们能预知的异常和未知的系统异常,对于我们能预知的异常如空值判断,用户名错误,密码错误等异常我们需要返回客户端,对于系统内部异常如SQL语法错误,参数格式转换错误等需要统一包…...
大模型日报2024-06-18
大模型日报 2024-06-18 大模型资讯 大模型产品 Olvy 3.0:AI加速客户反馈分析 摘要: Olvy 3.0推出AI自动监听和智能标签功能,通过Google Meet集成轻松提取洞察,贴近客户,激发同理心。 PlantIdentify-免费植物识别应用 摘要: PlantI…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
篇章一 论坛系统——前置知识
目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...
