分布式消息队列:RabbitMQ(1)
目录
一:中间件
二:分布式消息队列
2.1:是消息队列
2.1.1:消息队列的优势
2.1.1.1:异步处理化
2.1.1.2:削峰填谷
2.2:分布式消息队列
2.2.1:分布式消息队列的优势
2.2.1.1:数据的持久化
2.2.1.2:可扩展性
2.2.1.3:应用解耦
2.2.1.4:发送订阅
2.2.2:分布式消息队列的应用场景
三:Rabbitmq
3.1:基本概念
3.2:快速入门
3.2.1:引入消息队列Java客户端
3.2.2:单消费开发生产者和消费者
3.2.3:多消费开发生产者和消费者
3.3.3:交换机
3.3.3.1:交换机的类别
a):fanout
一:中间件
连接多个系统,帮助多个系统紧密协作的技术(组件)
二:分布式消息队列
2.1:是消息队列
概念:存储消息的队列
关键词:存储,消息,队列
存储:存储数据
消息:某种数据结构,比如l字符串,对象,二进制数据,json等
队列:先进先出的数据结构
作用:在不同的系统下,应用之间实现消息的传输,不需要考虑传输应用的编程语言,系统和,框架等等,实现应用解耦的作用。
eg:可以让Java开发的应用发消息,让php开发的应用收消息。
针对生产者来说:不需要关心消费者什么时候接受消息,什么时候消费,我只需要把我的工作完成就好了。生产者和消费者之间实现了解耦。
针对上图,同样我们会发现,当小李要别的书籍的时候,小王也可以将别的书籍放到消息队列中。生产者和消费者从某一种程度上实现了解耦合。
2.1.1:消息队列的优势
2.1.1.1:异步处理化
生产者发送消息之后,可以继续去忙别的,消费者什么时候消费都可以,不产生阻塞。
2.1.1.2:削峰填谷
先把用户的请求放到消息队列种,消费者(实际执行操作的应用)可以按照自己的需求,慢慢去取。
举个栗子:
原本:
12点时来了10万个请求,原本情况下,10万个请求都在系统内部立刻处理,很快系统压力过大宕机。
现在:
把10万个请求放到消息队列中,处理系统以自己的恒定速率(比如每秒1个)慢慢执行,稳定处理。
2.2:分布式消息队列
2.2.1:分布式消息队列的优势
分布式消息队列继承于消息队列的优势,并进行了一部分的拓展。
2.2.1.1:数据的持久化
把消息集中存储在硬盘当中,服务器重启就不会丢失。
2.2.1.2:可扩展性
可以根据需求,随时增加(或减少)节点,继续保持稳定的服务。
2.2.1.3:应用解耦
可以连接不同语言(Java,PHP),框架开发的系统,让这些系统读取数据。
示例:
以前的项目:
加了分布式消息队列之后的项目:
1:一个系统挂了,不影响另一个系统。
2:系统挂了之后并恢复,仍然可以从消息队列中取消息
3:只要发送消息到队列,就可以立即进行返回,不用同步调用所有系统,性能更高
2.2.1.4:发送订阅
假设情景:当QQ进行了一部分改革之后,其他使用QQ的APP也应该处理
这部分改革。
QQ做了一个情景,要让其他系统知道,比如公告消息。如果QQ一次性给这些应用发消息,所引出的问题如下:
1.每次发通知都要调用很多系统,很麻烦,很可能失败
2.不知道哪个系统需要这些QQ的改革。
解决方案:大的核心系统始终往消息队列发消息,其他的系统都去订阅这个消息队列的消息,用的时候进行取就OK。
2.2.2:分布式消息队列的应用场景
1:耗时场景。
2:高并发场景。
3:分布式系统的协作。(跨团队,跨业务合作,应用解耦)
4:强稳定的场景(金融业务,持久化,可靠性,削锋填谷)
三:Rabbitmq
特点:生态好,易学习,易于理解,时效性强,支持不同语言的客户端,扩展性,可用性都很不错。
3.1:基本概念
AMPQ协议:Rabbitmq是遵循AMPQ协议的一种消息中间件。
生产者:发消息到交换机
消费者:收消息的,从某个队列中取消息
交换机(exchange):负责把消息转发到对应的队列
队列(Queue):存储消息的
路由(Rountes):转发,怎么把一个消息从一个地方转发到另一个地方(比如生产者转发到某个队列)
Rabbitmq:端口占用 5672:程序连接的端口 15672:管理界面端口
Rabbitmq的安装:https://blog.csdn.net/qq_25919879/article/details/113055350
管理器页面打不开:http://t.csdnimg.cn/6FqZl
3.2:快速入门
3.2.1:引入消息队列Java客户端
<dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.17.0</version></dependency>
3.2.2:单消费开发生产者和消费者
生产者端代码:
public class SingeProducer {private final static String QUEUE_NAME = "hello";public static void main(String[] argv) throws Exception {//创建连接工厂ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");try (Connection connection = factory.newConnection();//频道相当于客户端(jdbcClient,redisClient),提供了和消队列server建立通信,程序通过channel进行发送消息Channel channel = connection.createChannel()) {//创建消息队列,第二个参数(durable):是否开启持久化,第三个参数exclusiove:是否允许当前这个创建消息队列的//连接操作消息队列 第四个参数:没有人使用队列,是否需要删除channel.queueDeclare(QUEUE_NAME, false, false, false, null);//发送消息String message = "Hello World!";channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));System.out.println(" [x] Sent '" + message + "'");}}
}
消费者代码:
public class SingeConsumer {private final static String QUEUE_NAME = "hello";public static void main(String[] argv) throws Exception {//创建连接工厂ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");//创建频道,提供通信Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.queueDeclare(QUEUE_NAME, false, false, false, null);System.out.println(" [*] Waiting for messages. To exit press CTRL+C");//如何处理消息DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [x] Received '" + message + "'");};channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });}
}
3.2.3:多消费开发生产者和消费者
场景:一个生产者给队列里面发了一条消息,多个消费者进行消费。适用于多个机器同时去接收并处理任务(每个机器处理任务有限)
队列持久化:
durable:
参数设置为true,服务器队列不丢失
channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
消息持久化:
指定MessageProperties.PERSISTENY_TEXT_PLAIN参数
channel.basicPublish("", TASK_QUEUE_NAME,MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes("UTF-8"));
生产者端代码:
public class MultiProducer {private static final String TASK_QUEUE_NAME = "multi_queue";public static void main(String[] argv) throws Exception {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");try (Connection connection = factory.newConnection();Channel channel = connection.createChannel()) {channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);Scanner scanner=new Scanner(System.in);while(scanner.hasNext()){String message = scanner.nextLine();channel.basicPublish("", TASK_QUEUE_NAME,MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes("UTF-8"));System.out.println(" [x] Sent '" + message + "'");}}}
}
消费者代码:
在消费者代码中,如何测验一个消费者只能取一个任务,我们利用for循环来进行解决。
指定确认某条消息:
第一个参数:获取消息的信息
第二个参数:如果是true,把所有的历史消息全都确认了。如果为false,取出当前的消息。
//第二个参数:是否一次性取所有的消息。如果为true,则要取所有的挤压在消息队列中的消息//如果为false,则为一次性取一个消息channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
指定拒绝某条消息
第一个参数:获取消息的信息
第二个参数:如果是true,则代表是否要拒绝所有的历史消息。
第三个参数:如果是false, 则代表失败的任务是否要重新入队。
channel.basicNack(delivery.getEnvelope().getDeliveryTag(),false,false);
public class MultiConsumer {private static final String TASK_QUEUE_NAME = "multi_queue";public static void main(String[] argv) throws Exception {//建立连接ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");final Connection connection = factory.newConnection();for (int i = 0; i <= 2; i++) {final Channel channel = connection.createChannel();int finalI=i;//声明队列channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);System.out.println(" [*] Waiting for messages. To exit press CTRL+C");//控制单个消费者的任务积压数:每个消费者最多处理一个任务,每个消费者智能处理一个任务channel.basicQos(1);//处理从队列中取的的消息DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");try {//处理工作System.out.println(" [x] Received '" +"编号:"+finalI+ message + "'");//停20秒模拟一个机器处理工作能力有限Thread.sleep(20000);//第二个参数:是否一次性取所有的消息。如果为true,则要取所有的挤压在消息队列中的消息//如果为false,则为一次性取一个消息channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {System.out.println(" [x] Done");channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);}};//开启消费监听channel.basicConsume(TASK_QUEUE_NAME, false, deliverCallback, consumerTag -> { });}}}
3.3.3:交换机
一个生产者给多个队列发消息,一个生产者对多个队列。交换机:转发功能,怎么把消息转发到不同的队列上。
3.3.3.1:交换机的类别
a):fanout
场景:很适用于发布订阅的场景。
特点:消息会被转发到所有绑定到交换机的队列。
生产者代码:当生产者发送消息后,由交换机放到消息队列中,消费者从消息队列中取。
public class FonoutProducer {private static final String EXCHANGE_NAME = "1";public static void main(String[] argv) throws Exception {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");try (Connection connection = factory.newConnection();Channel channel = connection.createChannel()) {//创建交换机channel.exchangeDeclare(EXCHANGE_NAME, "fanout");Scanner scanner=new Scanner(System.in);while(scanner.hasNext()){String message = scanner.nextLine();channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));System.out.println(" [x] Sent '" + message + "'");}}}}
消费者代码:
public class FonoutConsumer {private static final String EXCHANGE_NAME = "1";public static void main(String[] argv) throws Exception {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");Connection connection = factory.newConnection();Channel channel = connection.createChannel();Channel channel2= connection.createChannel();//声明交换机//创建队列,随机分配一个队列名称channel.exchangeDeclare(EXCHANGE_NAME, "fanout");String queueName="xiaowang";channel.queueDeclare(queueName,true,false,false,null);channel.queueBind(queueName, EXCHANGE_NAME, "");channel2.exchangeDeclare(EXCHANGE_NAME, "fanout");String queueName2="xiaoli";channel2.queueDeclare(queueName2,true,false,false,null);channel2.queueBind(queueName2,EXCHANGE_NAME,"");System.out.println(" [*] Waiting for messages. To exit press CTRL+C");DeliverCallback deliverCallback1 = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [小王] Received '" + message + "'");};DeliverCallback deliverCallback2 = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println(" [小李] Received '" + message + "'");};channel.basicConsume(queueName, true, deliverCallback1, consumerTag -> { });channel.basicConsume(queueName2, true, deliverCallback2, consumerTag -> { });}}
运行结果:
相关文章:

分布式消息队列:RabbitMQ(1)
目录 一:中间件 二:分布式消息队列 2.1:是消息队列 2.1.1:消息队列的优势 2.1.1.1:异步处理化 2.1.1.2:削峰填谷 2.2:分布式消息队列 2.2.1:分布式消息队列的优势 2.2.1.1:数据的持久化 2.2.1.2:可扩展性 2.2.1.3:应用解耦 2.2.1.4:发送订阅 2.2.2:分布式消息队列…...
Redis集群脑裂
1. 概述 Redis 集群脑裂(Cluster Split Brain)是指在 Redis 集群中,由于网络分区或通信问题,导致集群中的节点无法相互通信,最终导致集群内部发生分裂,出现多个子集群,每个子集群认为自己是有效…...
GEE教程——随机样本点添加经纬度信息
简介: 有没有办法在绘制散点图后将样本的坐标信息(纬度/经度)添加到.CSV表格数据中? 这里我们很多时候我们需要加载样本点的基本信息作为属性,本教程主要的目的就是我们选取一个研究区,然后产生随机样本点,然后利用坐标函数,进行样本点的获取经纬度,然后通过循环注意…...
PyTorch入门学习(十):神经网络-非线性激活
目录 一、简介 二、常见的非线性激活函数 三、实现非线性激活函数 四、示例:应用非线性激活函数 一、简介 在神经网络中,激活函数的主要目的是引入非线性特性,从而使网络能够对非线性数据建模。如果只使用线性变换,那么整个神…...
《golang设计模式》第三部分·行为型模式-03-解释器模式(Interpreter)
文章目录 1. 概述1.1 角色1.2 类图1.3 优缺点 2. 代码示例2.1 设计2.2 代码2.3 类图 1. 概述 解释器模式(Interpreter)是用于表达语言语法树和封装语句解释(或运算)行为的对象。 1.1 角色 AbstractExpression(抽象表…...

Windows个性化颜色睡眠后经常改变
问题再现 我把系统颜色换成了一种红色,结果每次再打开电脑又变回去了(绿色); 原因是因为wallpaper engine在捣蛋 需要禁用修改windows配色这一块选项; 完事!原来是wallpaper engine的问题;...
calico ipam使用
calico ipam使用 前面的文章pod获取ip地址的过程中提到过calico使用的IP地址的管理模块是其自己开发的模块calico-ipam,本篇文章来讲述下其具体用法。 一、环境信息 版本信息 本环境使用版本是k8s 1.25.3 [rootnode1 ~]# kubectl get node NAME STATUS ROLES …...
Redis系统学习(高级篇)-Redis持久化-AOF方式
目录 一、是什么AOF? 二、AOF如何开启 以及触发策略有哪些 三、AOF文件重写 四、AOF与RDB对比 一、是什么AOF? 就是通过每次记录写操作,最终通过来依次这些命令来达到恢复数据的目的 二、AOF如何开启 以及触发策略有哪些 save "&q…...

云安全-云原生基于容器漏洞的逃逸自动化手法(CDK check)
0x00 docker逃逸的方法种类 1、不安全的配置: 容器危险挂载(挂载procfs,Scoket) 特权模式启动的提权(privileged) 2、docker容器自身的漏洞 3、linux系统内核漏洞 这里参考Twiki的云安全博客,下…...

精选10款Python可视化工具,请查收
今天我们会介绍一下10个适用于多个学科的Python数据可视化库,其中有名气很大的也有鲜为人知的。 1、matplotlib matplotlib 是Python可视化程序库的泰斗。经过十几年它仍然是Python使用者最常用的画图库。它的设计和在1980年代被设计的商业化程序语言MATLAB非常接近…...
大数据(21)-skew-GroupBy
&&大数据学习&& 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博主哦ᾑ…...
window压缩包安装mongodb并注册系统服务
下载解压包 https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-5.0.22.zip启动mongod 解压压缩包 至 d:\mongodb目录中,创建目录data、logs。并创建配置文件mongod.conf输入以下配置 dbpath d:\mongodb\data logpath d:\mongodb\logs\mongo.log loga…...
【Java每日一题】——第四十五题:综合案例:模拟物流快递系统。(2023.11.1)
🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL:…...

二十二、Arcpy批量波段组合——结合Landat数据城市建成区提取
一、前言 其实波段组合和GIS中栅格计算有点类似,实质上就是对每个像素点对应的DN值进行数学计算,也就是可以进行运算表达式是三个或多个变量相加、相减……每一个变量对应于一个图像数据,对这三个或多个图像数据求值并输出结果图像。 二、具体操作 1、实验具体目标 将202…...

电脑上数据恢复的详细操作
在日常使用电脑过程中,我们可能会遇到数据丢失的情况。无论是因为误删除、格式化、病毒攻击还是硬件故障,数据恢复都是我们迫切需要解决的问题。本文将介绍电脑数据恢复的详细操作步骤,帮助读者在面临数据丢失时能够迅速地恢复重要文件。 一…...
3.1 linux控制内核打印printk demsg DEBUG
本文主要内容: 1 列出内核打印级别 2 修改内核打印级别 方法1 编译时 方法2 uboot时 方法3 启动后 3 DEBUG宏控制妙用 4 内存中各种打印函数封装 5 测试示例代码 1 打印级别 #define KERN_EMERG "<0>" /* system is unusable */ #define KERN_ALERT …...
关于爬虫API常见的技术问题和解答
随着互联网的快速发展,数据获取变得越来越重要。爬虫API作为一种高效的数据获取手段,被广泛应用于各种场景。然而,在实际使用过程中,我们经常会遇到一些技术问题。本文将详细介绍爬虫API的常见技术问题及相应的解决方案。 一、爬…...

在CentOS上用yum方式安装MySQL8过程记录
此文参考官方文档一步一步记录安装到正常运行全过程 安装环境:centos7 mysql版本:8.0.35 安装过程主要参考下面两边文章: 1.官方文档 https://dev.mysql.com/doc/refman/8.0/en/linux-installation-yum-repo.html 2.linux yum安装mysql8 安…...

CEYEE希亦新品洗地机Pro系列发布, 领跑行业的「水汽混动」技术的旗舰新杰作
CEYEE希亦全新一代洗地机T800 PRO正式上市,采用双滚刷,双倍活水洗拖洗方式,达到拖一遍抵两遍,相对于10倍洁净效果! 这款希亦Pro系列产品不仅刷新了洗地机行业技术水准,满足了用户愈发极致的清洁效能追求&a…...

为什么要安装防静电门禁闸机
安装防静电门禁闸机可以带来以下几个方面的好处: 防止静电干扰:静电是一种非常危险的物理现象,它可以对电子元器件、电路板和其他敏感设备造成损害,甚至导致设备故障和生产中断。防静电门禁闸机可以有效地防止静电的产生和传导&am…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...