MQ,RabbitMQ,SpringAMQP的原理与实操
MQ
同步通信



异步通信

事件驱动优势:
-
服务解耦

-
性能提升,吞吐量提高

-
服务没有强依赖,不担心级联失败问题

-
流量消峰

小结: 大多情况对时效性要求较高,所有大多数时间用同步。而如果不需要对方的结果,且吞吐量,并发量较高则需要使用异步通信

MQ常见框架
MQ(MessageQueue),消息队列,字面来看就是存放消息的队列,也就是事件驱动架构中的Broker
消息:就是事件,比如支付成功了这个事件,在MQ中就是一个消息

RabbitMQ,RocketMQ 适合处理业务(若需要优化定制则选Rocket,因为用Java写的)
Kafka 适合处理日志(海量数据且对数据安全性要求不高的场景),ActiveMQ用的较少
RabbitMQ
RabbitMQ概述与安装
RabbitMQ是基于Erlang语言(面向并发的语言,天生为分布式系统而设计的)开发的开源消息通信中间件,官网地址:https://www.rabbitmq.com/
参考课前资料(链接:https://pan.baidu.com/s/1JuVKKFpUXg8TFxa_FoV3Gg
提取码:1468) 来安装RabbitMQ

之后在浏览器输入:http://192.168.83.130:15672/ 进入RabbitMQ管理页面,按docker run中设置的账号密码进行登录
结果如下

mq整体架构

小结

常见消息模型

HelloWorld 案例

动手实践
案例: 完成官方Demo中的hello world案例(链接:https://pan.baidu.com/s/1JuVKKFpUXg8TFxa_FoV3Gg
提取码:1468)

打开项目,将ip调成自己的rabbitmq使用虚拟机(或电脑)的ip,再运行一次PublisherTest中的 testSendMessage() 方法
发送一条消息。再运行ConsumerTest 中main方法来接收消息。

小结

SpringAMQP
AMOP(Advanced Message Queuing Protocol)高级消息队列协议,大大简化消息发送和接收的代码量,且与语言无关
SpringAmqp的官方地址:https://spring.io/projects/spring-amqp


AMQP依赖
<!--AMQP依赖,包含RabbitMQ-->
<dependency> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
在配置文件中添加mq连接信息
spring:rabbitmq:host: 192.168.83.130 # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机 username: itcast # 用户名password: 123321 # 密码
Basic Queue 简单队列模型
案例:利用SpringAMQP实现HelloWorld中的基础消息队列功能
流程如下:
1.在父工程中引入spring-amqp的依赖,以及在publisher服务中编写配置
2.在publisher服务中利用RabbitTemplate的convertAndSend方法,发送消息到simple.queue这个队列

SpringAMQP发送消息步骤:引入依赖和设置配置---->利用RabbitTemplate的convertAndSend方法
3.在consumer中编写代码,接收消息

SpringAMQP接收消息步骤:引入依赖和设置配置—》定义类,添加Component注解,类中声明方法添加@RabbitListener注解
Work Queue 工作队列模型
Work queue,工作队列,可以提高消息处理速度,避免队列消息堆积
比如队列 一秒来50条消息 一个消费者一秒处理40条消息,那么需要两个消费者才能使得队列中消息被处理不丢失

案例:实现一个队列绑定多个消费者

问题:rabbitMQ消息预取,会将50条消息平均分给消费者1和消费者2,但消费者2处理速度慢,因此在1s内处理不完publisher发过来的50条消息
解决方案:让能者多劳,设置preFetch,控制预取消息的上限

小结
发布、订阅模型-Fanout

注意:exchange负责消息路由,而不是存储(queue负责存储),路由失败则消息丢失
Fanout Exchange 会将接收到的消息路由到每一个跟其绑定的queue(广播)
案例:利用SpringAMQP演示FanoutExchange的使用

step1 在consumer服务中声明Exchange、Queue、Binding(绑定关系)


step2 在consumer服务声明两个消费者
在consumer服务的SpringRabbitListener类中,添加两个方法,分别监听fanout.queue1和fanout.queue2:
@RabbitListener(queues = "fanout.queue1")
public void listenFanoutQueue1(String msg) {System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
}@RabbitListener(queues = "fanout.queue2")
public void listenFanoutQueue2(String msg) {System.out.println("消费者2接收到Fanout消息:【" + msg + "】");
}
step3 在publisher服务发送消息到FanoutExchange
在publisher服务的SpringAmqpTest类中添加测试方法:
@Test
public void testFanoutExchange() {// 队列名称 String exchangeName = "itcast.fanout"; // 消息String message = "hello, everyone!";// 发送消息,参数分别是:交互机名称、RoutingKey(暂时为空)、消息 rabbitTemplate.convertAndSend(exchangeName, "", message);
}
小结

发布、订阅模型-Direct

案例:利用SpringAMQP演示DirectExchange的使用

步骤一 在consumer服务声明Exchange、Queue
1.在consumer服务中,编写两个消费者方法,分别监听direct.queue1和direct.queue2,
2.并利用@RabbitListener声明Exchange、Queue、RoutingKey
@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),key = {"red","blue"}
))
public void listenDirectQueue1(String msg){System.out.println("消费者1........接收到路由消息:【" + msg + "】" + LocalTime.now());
}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),key = {"red","yellow"}
))
public void listenDirectQueue2(String msg){System.out.println("消费者2........接收到消路由息:【" + msg + "】" + LocalTime.now());
}
步骤二 在publisher服务发送消息到DirectExchange
在publisher服务的SpringAmqpTest类中添加测试方法:
@Test
public void testDirectExchange() {//交换机名字String exchangeName = "itcast.direct";//消息String message = "红色警报!日本乱排核废水,导致海洋生物变异,惊现哥斯拉!";//发送消息,参数依次为:交换机名称,RoutingKey,消息rabbitTemplate.convertAndSend(exchangeName, "blue", message);
}
从blue->yellow->red 运行三次,得到结果如下

小结

发布、订阅模型-Topic

案例 利用SpringAMQP演示TopicExchange的使用

步骤一:在consumer服务声明Exchange、Queue
1.在consumer服务中,编写两个消费者方法,分别监听topic.queue1和topic.queue2,
2.并利用@RabbitListener声明Exchange、Queue、RoutingKey
@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue1"),exchange = @Exchange(name = "itcast.topic", type = ExchangeTypes.TOPIC),key = "china.#"
))
public void listenTopicQueue1(String msg){System.out.println("消费者1........接收到路由消息:【" + msg + "】" + LocalTime.now());
}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue2"),exchange = @Exchange(name = "itcast.topic", type = ExchangeTypes.TOPIC),key = "#.news"
))
public void listenTopicQueue2(String msg){System.out.println("消费者2........接收到消路由息:【" + msg + "】" + LocalTime.now());
}
步骤二:在publisher服务发送消息到TopicExchange
在publisher服务的SpringAmqpTest类中添加测试方法:
@Test
public void testTopicExchange() {//交换机名字String exchangeName = "itcast.topic";//消息String message = "喜报!孙悟空大战哥斯拉,胜!";//发送消息,参数依次为:交换机名称,RoutingKey,消息rabbitTemplate.convertAndSend(exchangeName, "china.news", message);
}
小结

消息转化器
Spring的对消息对象的处理是由org.springframework.amqp.support.converter.MessageConverter来处理的。而默认实现是SimpleMessageConverter,基于JDK的ObjectOutputStream完成序列化。如果要修改只需要定义一个MessageConverter 类型的Bean即可。推荐用JSON方式序列化,步骤如下:
在publisher服务引入依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId>
</dependency>
在publisher服务声明MessageConverter。(原本应该放到配置类中,但启动类也是配置类,所以可以放启动类中)
@Bean
public MessageConverter jsonMessageConverter(){return new Jackson2JsonMessageConverter();
}

案例 测试发送Object类型消息

结果如下(没有更改JDK序列化方式)

使用json序列化器之后

consumer接收消息过程
step1:加jackson依赖,依赖上面已经放父工程中,就不用做了
step2: 将pulisher中相同的MessageConverter放入consumer 启动类中(发送方与接收方必须相同)
@Bean
public MessageConverter jsonMessageConverter(){return new Jackson2JsonMessageConverter();
}
step3: 定义一个消费者,监听object.queue队列并消费消息
@RabbitListener(queues = "object.queue")
public void listenObjectQueue(Map<String,Object> msg){System.out.println("消费者........接收到对象消息:【" + msg + "】" + LocalTime.now());
}

相关文章:
MQ,RabbitMQ,SpringAMQP的原理与实操
MQ 同步通信 异步通信 事件驱动优势: 服务解耦 性能提升,吞吐量提高 服务没有强依赖,不担心级联失败问题 流量消峰 小结: 大多情况对时效性要求较高,所有大多数时间用同步。而如果不需要对方的结果,且吞吐…...
Vue 3 + Koa2 + MySQL 开发和上线部署个人网站
Vue 3 Koa2 MySQL 开发和上线部署个人网站 记录个人的一个操作步骤, 顺序不分先后, 嫌啰嗦请出门右转! 环境说明: 服务器: 阿里云轻量应用服务器 服务器系统: CentOS8.2 本地环境: macOS 12.7.2 Node: 20.10.0 MySQL: 8.0.26 Vue: 3.3.11 Koa: 2.7.0 pm2: 5.3.1 Nginx: 1.1…...
uniapp踩坑之项目:简易版不同角色显示不一样的tabbar和页面
1. pages下创建三个不同用户身份的“我的”页面。 显示第几个tabbar,0是管理员 1是财务 2是司机 2. 在uni_modules文件夹创建底部导航cc-myTabbar文件夹,在cc-myTabbar文件夹创建components文件夹,在components文件夹创建cc-myTabbar.vue组件…...
源支付V7开心1.9修复版,非网络上泛滥不能那种
源支付V7开心1.9修复版,非网络上泛滥不能那种 修复版源码,非网络泛滥版,防止源码泛滥,会员专属源码, 本站会员免费下载所有资源 注:开发不易,仅限交流学习使用,如商业使用,请支持正…...
Gitlab和Jenkins集成 实现CI (二)
Gitlab和Jenkins集成 实现CI (一) Gitlab和Jenkins集成 实现CI (二) Gitlab和Jenkins集成 实现CI (三) 配置Gitlab api token 配置 Gitlab 进入gitlab #mermaid-svg-t84fR8wrT4sB4raQ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:…...
Java:内部类、枚举、泛型以及常用API --黑马笔记
内部类 内部类是类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。 当一个类的内部,包含一个完整的事物,且这个事物没有必要单独设计时&a…...
【持续更新】2024牛客寒假算法基础集训营3 题解 | JorbanS
A - 智乃与瞩目狸猫、幸运水母、月宫龙虾 string solve() {string a, b; cin >> a >> b;if (isupper(a[0])) a[0] a - A;if (isupper(b[0])) b[0] a - A;return a[0] b[0] ? yes : no; }B - 智乃的数字手串 string solve() {cin >> n;int cnt 0;for (…...
Java基于微信小程序的驾校报名小程序,附源码
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...
Android中AGP与Gradle、AS、JDK的版本关系
文章目录 AGP版本所要求的Gradle、JDK、SDK Build Tools最小版本Android Studio所要求的AGP最小版本 本文介绍了 在Android开发中由于AGP与gradle、JDK、AS等版本不匹配导致的编译失败问题屡见不鲜,尤其是对于新手而言更是叫苦不迭。新手经常遇到拿到别人的工程代码…...
web 前端实现一个根据域名的判断 来显示不同的logo 和不同的标题
1.需求 有可能我做一个后台 web端 我想实现一套代码的逻辑 显示不同的公司主题logo以及内容,但是实际上 业务逻辑一样 2.实现 建一个store oem.ts 这个名为是 oem系统 oem.ts import { defineStore } from pinia;import { store } from /store;const oemDataLis…...
复制和粘贴文本时剥离格式的5种方法(MacWindows)
您可能每天复制和粘贴多次。虽然它是一个非常方便的功能,但最大的烦恼之一就是带来了特殊的格式。从网络上获取一些文本,您经常会发现粘贴到文档中时,它保持原始样式。 我们将展示如何使用一些简单的技巧在不格式化的情况下复制和粘贴。 1.…...
SpringBoot实现即时通讯
SpringBoot实现即时通讯 功能简述 好友管理群组管理聊天模式:私聊、群聊消息类型:系统消息、文本、语音、图片、视频会话列表、发送消息、接收消息 核心代码 package com.qiangesoft.im.core;import com.alibaba.fastjson2.JSONObject; import com.q…...
【每日一题】LeetCode——反转链表
📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏小杨水平有…...
精通Python爬虫:掌握日志配置
源码分享 https://docs.qq.com/sheet/DUHNQdlRUVUp5Vll2?tabBB08J2 在开发Python爬虫时,日志记录是一个不可或缺的特性,它帮助我们捕捉运行时信息、调试代码和监控爬虫的健康状况。合理地配置日志系统是提高爬虫可维护性的关键。本篇技术博客将详细介绍…...
Python_百度贴吧评论情感分析
一、评论爬取 以百度贴吧中“美团骑手吧”为例,对页面中的帖子评论进行爬取,并将结果以json的格式保存到本地中。 from lxml import etree import requests import json# 根据网页url获取评论 def GetComments(url):# 使用requests库发送GET请求&#…...
如何运行心理学知识(心流)来指导工作和生活
如何运用心流来指导工作和生活 如何联系我 作者:鲁伟林 邮箱:thinking_fioa163.com或vlinyes163.com GitHub:https://github.com/thinkingfioa/ReadingSummary 版权声明:文章和记录为个人所有,如果转载或个人学习…...
精简还是全能?如何在 Full 和 Lite 之间做出最佳选择!关于Configuration注解的Full模式与Lite模式(SpringBoot2)
🏃♂️ 微信公众号: 朕在debugger© 版权: 本文由【朕在debugger】原创、需要转载请联系博主📕 如果文章对您有所帮助,欢迎关注、点赞、转发和订阅专栏! 前言 关于 Configuration 注解,相信在座的各位 Javaer 都…...
springboot微信小程序uniapp学习计划与日程管理系统
基于springboot学习计划与日程管理系统,确定学习计划小程序的目标,明确用户需求,学习计划小程序的主要功能是帮助用户制定学习计划,并跟踪学习进度。页面设计主要包括主页、计划学习页、个人中心页等,然后用户可以利用…...
236.二叉树的最近公共祖先
题目来源: leetcode题目,网址:236. 二叉树的最近公共祖先 - 力扣(LeetCode) 解题思路: 分别获得从根节点到两个目标节点的链路,寻找到最后一个相同节点即可。 解题代码: /***…...
ETL是什么,有哪些ETL工具?就业前景如何?
ETL是什么 ETL(Extract-Transform-Load),用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目标端的过程。ETL一词较常用在数据仓库,但其对象并不限于数据仓库。它可以自动化数据处理过程,减少…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
TJCTF 2025
还以为是天津的。这个比较容易,虽然绕了点弯,可还是把CP AK了,不过我会的别人也会,还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...
LangChain【6】之输出解析器:结构化LLM响应的关键工具
文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...
【学习记录】使用 Kali Linux 与 Hashcat 进行 WiFi 安全分析:合法的安全测试指南
文章目录 📌 前言🧰 一、前期准备✅ 安装 Kali Linux✅ 获取支持监听模式的无线网卡 🛠 二、使用 Kali Linux 进行 WiFi 安全测试步骤 1:插入无线网卡并确认识别步骤 2:开启监听模式步骤 3:扫描附近的 WiFi…...
【Elasticsearch基础】Elasticsearch批量操作(Bulk API)深度解析与实践指南
目录 1 Bulk API概述 1.1 什么是批量操作 1.2 Bulk API的优势 2 Bulk API的工作原理 2.1 请求处理流程 2.2 底层机制 3 Bulk API的使用方法 3.1 基本请求格式 3.2 操作类型示例 3.3 响应格式 4 Bulk API的最佳实践 4.1 批量大小优化 4.2 错误处理策略 4.3 性能调…...
迁移科技3D视觉系统:重塑纸箱拆垛场景的智能革命
一、传统拆垛场景的困局与破局之道 在汽车零部件仓库中,每天有超过2万只异形纸箱需要拆垛分拣。传统人工拆垛面临三大挑战: 效率瓶颈:工人每小时仅能处理200-300件,且存在间歇性疲劳安全隐患:20kg以上重箱搬运导致年…...
