消息队列(一):需求分析
为什么要做这样一个项目?
首先,我们在之前学习的时候,就认识了一下 生产者消费者模式,这样一个模式有两大好处:
- 解耦合
- 本来有个分布式系统,A服务器 调⽤ B服务器(A给B发请求,B给A返回响应)===》 A 和 B 的耦合是⽐较⼤的!
- 引⼊消息队列后,A把请求发送到消息队列,B再从消息队列获取到请求;此时就算 A 或者 B 崩溃了,都不会影响到对方
-
- 削峰填谷
- ⽐如A是⼊⼝服务器,A 调⽤ B 完成⼀些具体业务,如果是 A 和 B 直接通信,如果突然A 收到 ⼀组⽤户的请求的峰值,此时 B 也会随着受到峰值
- 引⼊消息队列后,A把请求发送到消息队列,B再从消息队列获取到请求。 (虽然A收到很多请 求,队列也收到了很多请求,但是B仍旧可以按照原来的节奏处理请求。不⾄于说⼀下就收到太 多的并发量。)
- 举个例⼦:⾼铁⽕⻋站,进站⼝。 乘客好⽐A ,进站⼝好⽐B,是有限的,就需要⼀个队列来 排队,这样不管⼈多少,就不会影响到乘客进站以后的坐⻋。
-
什么是消息队列?
队列可以说是一个数据结构,可以存储数据,如下图,我们从右侧(队尾)插入元素(入队),从队头获取元素(出队)。
了解了队列之后,我们来看一下什么是消息队列,消息队列就是我们常说的MQ,英文叫Message Queue,是作为一个单独的中间件产品存在的,独立部署。
这个消息队列有啥好处呢?
我们先前已经提过了 解耦合 、 削峰填谷 ;除此之外还有一个好处 : 异步,关于这个异步,等到正式介绍的相关代码我再来细说,这里就不多介绍了。
市⾯上⼀些知名的消息队列
- RabbitMQ
- Kafka
- RocketMQ
- ActiveMQ
本项目是 基于 RabbitMQ 实现的较为简易的(所谓建议的意思就是还可以继续完善) MQ;RabbitMQ 是一款比较 “ 年长 ” 的消息队列,比较经典,所以选择了这一款消息队列。
需求分析
核心概念1
- ⽣产者(Producer)
- 消费者(Consumer)
- 中间⼈(Broker)
- 发布(Push) ⽣产者向中间⼈这⾥投递消息的过程
- 订阅(Subscribe) 哪些消费者要从中间⼈取数据,这个注册的过程,称为 "订阅"
- 消费 (Consume) 消费者从中间⼈这⾥取数据的动作
一个生产者,一个消费者
多个生产者,多个消费者
核心概念2
- 虚拟主机(Virtual Host),类似于 MySQL 中的 database,算是⼀个 "逻辑" 上的数据集合
- ⼀个Broker server 上可以组织多种不同类别数据,可以使⽤ Virtual Host 做出逻辑上的区分
- 实际开发中,⼀个 Broker server也可能同时⽤来管理多个 业务线上的数据,就可以使⽤ Virtual Host 做出逻辑上的区分。
- 交换机(Exchange)
- ⽣产者把消息投递给 Broker Server,实际上是把消息先交给了 (公司某⼀层楼)Broker Server 上的交换机,再由交换机把消息交给对应的队列。 (交换机类似于“前台⼩姐姐”)
- 队列(Queue)
- 真正⽤来存储处理消息的实体,后续消费者也是从对应的队列中取数据
- ⼀个⼤的消息队列中,可以有很多具体的⼩队列
- 绑定(Binding)
- 把交换机和队列之间,建⽴关系。
- 可以把 交换机 和 队列 视为,数据库中 多对多的关系。可以想象,在 MQ 中,也是有⼀个这 样的中间表,所谓的 “绑定’其实就是中间表中的⼀项
- 消息(Message)
- 具体来说,是 服务器A 发给 B 的请求(通过MQ转发), 服务器B 给 服务器A返回的响应(通过MQ转发)
- ⼀个消息,可以视为⼀个字符串(⼆进制数据),具体由程序员⾃定义
持久化
关于持久化,上述 虚拟机、交换机、队列、绑定、消息,需要存储起来,光是存内存显然是不够的(为啥不够呢?万一服务器宕机了,我们消息还没有处理,所以还需要将消息恢复一下),所以我们还需要存硬盘,这里以内存为主、硬盘为辅。
关于存硬盘,我们这里要进行一个区分 :
- 存数据库:交换机、队列、绑定
- 存文件:主要是与消息相关的
在内存中存储的原因:
对于 MQ 来说,能够⾼效的转发处理数据,是⾮常关键的指标! 因此对于使⽤内存来组织数据,得 到的效率,就⽐放硬盘要⾼很多
在硬盘中存储的原因:
为了防⽌内存中数据随着进程重启/主机重启⽽丢失
核心 API
- 创建队列(queueDeclare)
- 此处不⽤ Create这样的术语,原因是Create仅仅是创建;⽽ Declare 起到的效果是,不存在则创建,存在就啥也不做
- 销毁队列(queueDelete)
- 创建交换机(exchangeDeclare)
- 销毁交换机(exchageDelete)
- 创建绑定(queueBind)
- 解除绑定(queueUnbind)
- 发布消息(basicPublish)
- 订阅消息(basicConsume)
- 确认消息(basicAck)
- 这个API起到的效果,是可以让消费者显式的告诉 broker server,这个消息我处理完毕了,提⾼ 整个系统的可靠性~保证消息处理没有遗漏
- RabbitMQ 提供了 肯定 和 否定的 确认,此处我们项⽬就只有 肯定确认
交换机类型
交换机在转发消息的时候,有一套转发规则的
消息队列提供了几种不同的 交换机类型(ExchangeType) 来描述这里不同的转发规则
RabbitMQ主要实现了如下四种交换机(也是由 AMQP协议定义的)
- Direct 直接交换机
- Fanout 扇出交换机
- Topic 主题交换机
- Header 消息头交换机
而在我们手写的交换机只实现了前三种:
a. ⽣产者发送消息时,会指定⼀个"⽬标队列"的名字(此时的 routingKey就是 队列的名字)b. 交换机收到后,就看看绑定的队列⾥⾯,有没有匹配的队列c. 如果有,就转发过去(把消息塞进对应的队列中)d. 如果没有,消息直接丢弃
a. 会把消息放到交换机绑定的每个队列b. 只要和这个交换机绑定任何队列都会转发消息
a. bindingKey:把队列和交换机绑定的时候,指定⼀个单词(像是⼀个暗号⼀样)b. routingKey:⽣产者发送消息的时候,也指定⼀个单词c. 如果当前 bindingKey 和 routingKey 对上了,就可以把消息转发到对应的队列
- 专属红包 ======== 直接交换机
- 发个10块钱红包,⼤家都能领 10块钱红包 ======== 扇出交换机
- 我发个⼝令红包,只有输⼊对应⼝令才能领导红包 ======== 主题交换机
至于为啥没有实现 header主题头 交换机 ,那是因为 header 的实现规则复杂,并且实用场景少。
网络通信
其他的服务器(生产者/消费者)通过网络,和咱们的 BrokerServer 进行交互的。
此处设定,使用 TCP + 自定义应用层协议 实现 生产者/消费者 和 BrokerServer 之间进行交互。
应用层协议主要工作:就是让客户端可以通过网络,调用 BrokerServer 提供的编程接口(从而达到看似是生产者远程调用服务器的API)
消息队列服务器(BrokerServer),要提供的核心 API
- 创建队列(queueDeclare)
- 此处不⽤ Create这样的术语,原因是Create仅仅是创建;⽽ Declare 起到的效果是,不存在则创建,存在就啥也不做
- 销毁队列(queueDelete)
- 创建交换机(exchangeDeclare)
- 销毁交换机(exchageDelete)
- 创建绑定(queueBind)
- 解除绑定(queueUnbind)
- 发布消息(basicPublish)
- 订阅消息(basicConsume)
- 确认消息(basicAck)
- 这个API起到的效果,是可以让消费者显式的告诉 broker server,这个消息我处理完毕了,提⾼ 整个系统的可靠性~保证消息处理没有遗漏
- RabbitMQ 提供了 肯定 和 否定的 确认,此处我们项⽬就只有 肯定确认
因此,客户端这边也需要提供上述 API,只有服务器是真正干实事的;客户端只是发送请求、接收响应:
客户端除了提供了上述 9 个方法之外,还需要提供 4个 额外的方法,支撑其他工作
- 创建 Connection
- 关闭 Connection
- 此处⽤的 TCP 连接,⼀个 Connection 对象,就代表⼀个 TCP连接
-
- 创建 Channel
- ⼀个Connection ⾥⾯包含多个 Channel,每个 Channel 上传输的数据都是互不相⼲的
- TCP中,建⽴/断开⼀个连接,成本挺⾼的,因此很多时候不希望频繁建⽴断开 TCP 连接
- 所以定义⼀个 Channel ,不⽤的时候,销毁 Channel,此处 Channel 是逻辑概念,⽐ TCP 轻量很多
-
- 关闭 Channel
消息应答模式
- 自动应答,消费者把这个消息取走了(调用了回调函数),就算应答了
- 手动应答,调用 basicAck 这个方法属于手动应答(消费者需要主动调用这个 API 来进行应答)
总结
- 需要实现 ⽣产者,消费者,brokerserver 三个部分
- 针对⽣产者消费者来说,主要编写的是 客户端和服务器的通信部分,给客户端提供⼀组 api,让客 户端的业务代码来调⽤,从⽽通过⽹络通信的⽅式远程调⽤ brokerserver 上的⽅法
- ⽐如创建交换机,客户端这边只需要提供相关参数即可,然后通过 socket 将 request 传⼊到 ⽹卡中,然后服务器从 ⽹卡中读取 request 解析。然后计算请求得到 response,再通过 socket 写回去⽹卡。
- 实现 brokerserver 【重点】
- 持久化
- 上述这些关键数据,在硬盘中怎么存储,啥格式存储,存储在哪?
- 后续服务器宕机或是重启了,如何读取这些数据?
如果还是不太理解的话,可以结合下列思维导图一起理解:
思维导图
相关文章:
消息队列(一):需求分析
为什么要做这样一个项目? 首先,我们在之前学习的时候,就认识了一下 生产者消费者模式,这样一个模式有两大好处: 解耦合 本来有个分布式系统,A服务器 调⽤ B服务器(A给B发请求,B给A…...
ImageViewer技术实现细节
第1章 ImageViewer工具使用方法 1.1. 图像加载 1.1.1. 单图像加载 左上角菜单,“File”->“单图像”,或者Ctrl-S,弹出文件对话框,选择图像文件,当前支持bmp,png,jpg格式。 结果如下图所示: 1.1.2. 多图像加载 左上角菜单,“File”->“多图像”,或者Ctrl-M…...
MFC多文档程序,从菜单关闭一个文档和直接点击右上角的x效果不同
MFC多文档程序,从菜单关闭一个文档和直接点击右上角的x效果不同 若文档内容有修改,则前者会询问用户,是否保存修改;后者不保存修改直接关闭。 原因在于,从菜单关闭时,调用OnClose,一定会调用Sa…...
【数据结构】C++实现AVL平衡树
文章目录 1.AVL树的概念2.AVL树的实现AVL树结点的定义AVL树的插入AVL树的旋转左单旋右单旋左右双旋右左双旋插入代码 AVL树的验证AVL树的查找AVL树的修改AVL树的删除AVL树的性能 AVL树的代码测试 1.AVL树的概念 二叉搜索树虽然可以提高我们查找数据的效率,但如果插…...
图神经网络系列之序章
文章目录 一、为什么需要图神经网络?二、图的定义1.图的定义和种类2.一些关于图的重要概念2.1 子图2.2 连通图2.3 顶点的度、入度和出度2.4 边的权和网2.5 稠密图、稀疏图 3.图的存储结构3.1 邻接矩阵3.2 邻接表3.3 边集数组3.4 邻接多重表3.5 十字链表3.6 链式前向…...
Unity中 UI Shader的基本功能
文章目录 前言一、实现思路1、暴露一个 2D 类型的属性来接受UI的纹理2、设置shader的层级为TransParent半透明渲染层级,一般UI都是在这个渲染层级3、更改混合模式,是 UI 使用的纹理,该透明的地方透明 二、代码实现 前言 Unity中 UI Shader的…...
【自学开发之旅】Flask-标准化返回-连接数据库-分表-orm-migrate-增删改查(三)
业务逻辑不能用http状态码判断,应该有自己的逻辑判断。想要前端需要判断(好多if…else),所以需要标准化,标准化返回。 json标准化返回: 最外面:data,message,code三个字段。 data:返回的数据 co…...
numpy增删改查
NumPy是一个用于科学计算的Python库,它提供了一个多维数组对象以及许多用于操作这些数组的函数。下面是关于如何在NumPy中进行增删改查操作的一些基本示例: 创建NumPy数组: import numpy as np # 创建一个一维数组 arr np.array([1, 2, 3, …...
【kafka】kafka重要的集群参数配置
如何规划Kafka 对于实际应用的生产环境中,需要尽量先规划设计好集群,避免后期业务上线后费力调整。在考量部署方案时需要通盘考虑,不能仅从单个维度上进行评估,下面是几个重要的维度的考量和建议: 这里重点说说操作系…...
cs224w_colab3_2023 And cs224w_colab4_2023学习笔记
class GNNStack(torch.nn.Module):def __init__(self, input_dim, hidden_dim, output_dim, args, embFalse):super(GNNStack, self).__init__() #这里的继承表示参见 https://blog.csdn.net/wanzew/article/details/106993425 # 继承时运行继承类别的函数 总之 __mro__的目的…...
Cannot find module ‘prop-types‘
把这个import删了。...
LeetCode-63-不同路径Ⅱ-动态规划
题目描述: 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。 现在考虑网格中有障碍物。那…...
unity 使用Photon进行网络同步
Pun使用教程 第一步:请确保使用的 Unity 版本等于或高于 2017.4(不建议使用测试版)创建一个新项目。 第二步:打开资源商店并找到 PUN 2 资源并下载/安装它。 导入所有资源后,让 Unity 重新编译。 第三步…...
大数据课程M1——ELK的概述
文章作者邮箱:yugongshiyesina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解ELK的定义; ⚪ 掌握ELK的使用; 一、什么是ELK 1. 简介 ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案,是三个…...
C# byte[] 如何转换成byte*
目标:将byte[]转成byte*以方便使用memcpy [DllImport("kernel32.dll", EntryPoint "RtlCopyMemory", CharSet CharSet.Ansi)] public extern static long CopyMemory(IntPtr dest, IntPtr source, int size); private void butTemp_Click(object…...
MySQL与Oracle的分页
MySQL与Oracle的分页 当我们通过SQL去查询一个结果集的时候,并不需要查看所有行,可能只是查看前几行,或者中间的几行。则需要像MySQL的limit或Oracle的ROWNUM与FETCH NEXT来实现。 MySQL 语法 SELECT * FROM table_name LIMIT [offset,] ro…...
git基本手册
Git and GitHub for Beginners Tutorial - YouTube Kevin Stratvert git config --global user.name “xxx” git config --global user.email xxxxx.com 设置默认分支 git config --global init.default branch main git config -h查看帮助 详细帮助 git help config 清除 cl…...
每日一题(两数相加)
每日一题(两数相加) 2. 两数相加 - 力扣(LeetCode) 思路 思路: 由于链表从头开始向后存储的是低权值位的数据,所以只需要两个指针p1和p2,分别从链表的头节点开始遍历。同时创建一个新的指针new…...
恒运资本:沪指震荡涨0.28%,医药板块强势拉升,金融等板块上扬
15日早盘,沪指盘中震荡上扬,科创50指数表现强势;北向资金小幅净流入。 到午间收盘,沪指涨0.28%报3135.31点,深成指、创业板指涨均0.11%,科创50指数涨1.04%;两市合计成交4357亿元,北…...
【计算机网络】Tcp详解
文章目录 前言Tcp协议段格式TCP的可靠性面向字节流应答机制超时重传流量控制滑动窗口(重要)拥塞控制延迟应答捎带应答标志位具体标志位三次握手四次挥手粘包问题TCP异常情况listen的第二个参数 前言 前面我们学习了传输层协议Udp,今天我们一…...
最简单的laravel不使用任何扩展导出csv
php导出csv是非常常用的操作,网上也有灰常多的扩展。如果只是单纯的导出csv数据,完全没有必要去用扩展。现在做项目,都是代码能少就少,扩展能不用就不用。好了,不废话了,开干! 直接搞一个方法&…...
Android studio 断点调试、日志断点
目录 参考文章参考文章1、运行调试2、调试操作3、断点类型行断点的使用场景属性断点的使用场景异常断点的使用场景方法断点的使用场景条件断点日志断点 4、断点管理区 参考文章 参考文章 1、运行调试 开启 Debug 调试模式有两种方式: Debug Run:直接…...
服务器数据恢复-热备盘同步过程中硬盘离线的RAID5数据恢复案例
服务器数据恢复环境: 华为OceanStor某型号存储,11块硬盘组建了一组RAID5阵列,另外1块硬盘作为热备盘使用。基于RAID5阵列的LUN分配给linux系统使用,存放Oracle数据库。 服务器故障: RAID5阵列1块硬盘由于未知原因离线…...
Python 使用input获取用户输入
视频版教程 Python3零基础7天入门实战视频教程 input()函数用于向用户生成一条提示,然后获取用户输入的内容。由于input()函数总会将用户输入的内容放入字符串中,因此用户可以输入任何内容,input()函数总是返回一个字符串。我们可以通过int(…...
Python 可迭代对象、迭代器、生成器
可迭代对象 定义 在Python的任意对象中,只要它定义了可以返回一个迭代器的 __iter__ 魔法方法,或者定义了可以支持下标索引的 __getitem__ 方法,那么它就是一个可迭代对象,通俗的说就是可以通过 for 循环遍历了。Python 原生的列…...
HTML的有序列表、无序列表、自定义列表
目录 背景: 过程: 有序列表: 简介: 代码展示: 效果展示: 无序列表: 简介: 代码展示: 效果展示: 自定义列表: 简介: 代码展示: 效果展示: 总结: 背景: 1.有序列表(Ordered List): 有序列表是最早的…...
银河麒麟安装Docker-国产化-九五小庞
银河麒麟高级服务器操作系统 V10 是针对企业级关键业务,适应虚拟化、 云计算、大数据、工业互联网时代对主机系统可靠性、安全性、性能、扩展性和 实时性的需求,依据 CMMI 5 级标准研制的提供内生安全、云原生支持、国产 平台深入优化、高性能、易管理的…...
数据库与身份认证
1. 数据库的基本概念 1.1 什么是数据库 数据库(database)是用来组织、存储和管理数据的仓库。 当今世界是一个充满着数据的互联网世界,充斥着大量的数据。数据的来源有很多,比如出行记录、消费记录、浏览的网页、发送的消息…...
LabVIEW开发锅炉汽包水位的监督控制和模拟
LabVIEW开发锅炉汽包水位的监督控制和模拟 控制锅炉汽包液位对于机械的安全和设备的保护至关重要。滚筒液位控制器的工作是将滚筒液位提高到指定的设定点,并保持在那里,同时保持一致的蒸汽负荷。锅炉管可能会因该水平急剧下降而暴露,这会导致…...
2023-简单点-树莓派安装ncnn框架
not python 按照下面的步骤进行就可以了: 参考 tips: 其中有一步要用下面方法: 如果你的git clone不得行,可以按照以下操作方法: git clone --depth1 https://ghproxy.com/ https://github.com/Tencent/ncnn.git python 直接 pip install …...
做音乐网站需要版权么/百度识图在线识别
今天总结了一下spring中作用域scope的用法。在spring中作用域通过配置文件形式的用法如下。 1<bean id"role" class"spring.chapter2.maryGame.Role" scope"singleton"/>一. 在spring 中常用的作用域有单例模式(singleton&…...
网站备案注销 万网/网站建设费用明细表
JCommander可以帮我们解析Java的命令行工具,主要利用Parameter配置自己所需要的参数; JCommander 案例 在一般应用场景,我们可能只需要设置Parameter以下几个属性值: * names 设置命令行参数,如-old * required 设置…...
凡科建设网站步骤/全网营销策划公司
原文:Sql Server内置函数实现MD5加密实例 MD5加密“123456”: HashBytes(MD5,123456) 结果:0xE10ADC3949BA59ABBE56E057F20F883E (提示:看完最后,结果要进行转换。) 函数 函数描述返回值 HashBytes HashB…...
北辰手机网站建设/给你一个网站怎么优化
一转眼,吾家有女初长成。露露不再是出生时那个手指细如火柴、脑袋只有盈盈一捧的拇指姑娘,不再是那个因吃惯了奶瓶、使足了吃奶的劲也吸不出母乳的小可怜;也不再是那个抱起来就笑,一放下就哭的洋娃娃。虽然只有两岁多一点…...
临朐网站建设定制/搜索数据
第五十三天打卡 1143. 最长公共子序列 提示 中等 1.3K company 字节跳动 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 一个字符串的 子序列 是指这样一个新的字符串:它是…...
知名企业核心价值观/网站优化关键词公司
Java集合学习总结 ----------------------------------------------------------------------------- 1:集合Collection(单列集合的根接口)List接口(有序,元素可重复)ArrayList底层数据结构是数组,查询快,增删慢。线程不安全,效率…...