从零手搓一个【消息队列】项目设计、需求分析、模块划分、目录结构
文章目录
- 一、需求分析
- 1, 项目简介
- 2, BrokerServer 核心概念
- 3, BrokerServer 提供的核心 API
- 4, 交换机类型
- 5, 持久化存储
- 6, 网络通信
- 7, TCP 连接的复用
- 8, 需求分析小结
- 二、模块划分
- 三、目录结构
提示:是正在努力进步的小菜鸟一只,如有大佬发现文章欠佳之处欢迎批评指点~ 废话不多说,直接上干货!
一、需求分析
1, 项目简介
之前我的 这篇文章 中介绍过 JUC 中的阻塞队列 BlockingQueue , 介绍过"生产者消费者模型", 在实际开发中, 尤其是分布式系统⾥, 跨主机之间使⽤⽣产者消费者模型, 也是⾮常普遍的需求
因此, 我们通常会把阻塞队列, 封装成⼀个独⽴的服务器程序, 并且赋予其更丰富的功能, 这样的程序我们就称为 消息队列 (Message Queue, MQ)
目前市场上比较成熟的消息队列有: kafka, RabbitMQ, RocketMQ…, 本项目中部分参考 RabbitMQ 和 “AMQP 协议” 进行设计
项目描述 : 可跨主机的生产者消费者服务器程序,用于服务器之间的解耦,流量削峰;使用RPC模式,由客户端发送网络请求,远程调用服务器以操作交换机、队列、发布消息、订阅消息等;由服务器实现相关逻辑、持久化存储、异步转发消息等
所以这个项目中有一些比较核心的概念和模块 :
- 生产者(Producer) 负责往消息队列中投入消息
- 消费者(Consumer) 负责从消息队列中消费消息
- 中间人(Broker) 负责消息的存储和转发
- 发布(Publish) 投入消息的过程
- 订阅(Subscribe) 消费者注册一个队列的过程(我想要这个队列里的消息)
消费者消费数据由两种模式 :
1, 消费者从队列里取, 这种模式称为"拉"
2, 队列里有消息时, Broker (中间人服务器) 给消费者推送消息, 这种模式称为"推"
我们的项目中实现 “推” 这种模式
Producer, Consumer, Broker 都是服务器程序, 需要编写代码支持这三者之间的业务逻辑
但 Producer, Consumer 又是广义上的消费者, Producer, Consumer 是发起请求的一方, 所以是客户端, Broker 是返回响应的一方, 所以是服务器
2, BrokerServer 核心概念
- 虚拟机 (VirtualHost): 是⼀个逻辑上的集合, ⼀个 BrokerServer 上可以存在多个 VirtualHost , 如果一个 BrokerServer 有多个业务线, 就可以用不同的 VirtualHost 在分别组织不同类别的数据
(我们的项目中暂时只设定一个VirtualHost)
- 交换机 (Exchange): ⽣产者把消息先发送到 Broker 的 Exchange 上. 再根据不同的规则, 把消息转发给不同的 Queue
- 队列 (Queue): 真正⽤来存储消息的部分. 每个消费者决定⾃⼰从哪个 Queue 上取消息
- 绑定 (Binding): Exchange 和 Queue 之间的关联关系.
- 消息 (Message): 传递的内容.
用数据库做对比:
VirtualHost 相当于 database, Exchange 和 Queue 都是 table, Exchange 和 Queue 可理解成 “多对多” 关系. 所以 Binding 就是一个中间表, 可以把这两张表联系起来
AMQP 协议就是按照上述格式组织
3, BrokerServer 提供的核心 API
Producer, Consumer 是发起请求的一方, 所以是客户端, Broker 是返回响应的一方, 所以是服务器
因此 BrokerServer 需要给 Producer, Consumer 提供一些核心 API (对外暴露的), 这些 API 用来实现整个消息队列支持的基本功能
- 1, 创建队列 queueDeclare (Declare 表示不存在则创建, 存在则不创建)
- 2, 销毁队列 queueDelete
- 3, 创建交换机 exchangeDeclare
- 4, 销毁交换机 exchageDelete
- 5, 创建绑定 queueBind
- 6, 解除绑定 queueUnbind
- 7, 发布消息 basicPublish
- 8, 订阅消息 basicSubscribe (只是告知服务器有个消费者需要这个队列的数据)
- 9, 确认消息 basicAck (让消费者显式的告诉服务器, 收到并处理了消息
我们的项目给消费者在订阅消息时, 提供 “自动应答” 和 “确认应答” 两种方式
还有 “拒绝应答” 这种方式, 本项目暂未实现
没有 “消费消息” 这个 API , 上文已经说明, 我们的项目中不支持消费者主动从队列中取消息, 而是由服务器推送给消费者**(这个过程有些复杂, 后续会详细介绍)**
4, 交换机类型
- 直接交换机 Direct
- 扇出交换机 Fanout
- 主题交换机 Topic
- 消息头交换机 Header
咱们的项目不实现第四种, 实现方式复杂且比较少见
生产者在发布消息时, 有三个参数: 1, 消息 2, 交换机 3, routingKey (下面介绍), 不同的交换机有不同的转发规则
主题交换机: 不需要和队列建立绑定, 生产者发布消息时, routingKey 作为队列名(唯一标识)
, 如果队列存在, 交换机直接把消息投入到该队列中
扇出交换机: 需要和队列建立绑定, 生产者发布消息时什么都不用做 routingKey 为 null
, 交换机会把消息给已绑定的队列都投送一份
主题交换机: 需要和队列建立绑定, 并且绑定的时候
指定一个交换机和队列之间
的 “暗号” bindingKey
, 生产者发布消息的时候
指定一个 “暗号” routingKey
, 交换机会把消息投送给已绑定的队列中, 暗号能够对上(规则匹配)
的那个队列
Binding 表中就记录了 交换机和队列的绑定关系, 以及 bindingKey
目前不需要全部看懂 Binding 表, 大概熟悉这三种绑定规则即可
5, 持久化存储
上述提到的交换机, 队列, 绑定, 消息 需要在硬盘和内存上各存储一份, 内存为主, 硬盘为辅
因为内存的访问速度快, 而这对消息队列这个项目, 效率更重要, 而硬盘存储是为了服务器重启之后数据不丢失
硬盘存储使用 数据库 + 文件的方式, 数据库中存储 交换机, 队列, 绑定, 文件中存储消息
因为数据库提供的 增, 删, 查 比较方便, 交换机, 队列, 绑定正需要这些操作, 而消息不需要大量, 复杂的增删查, 基本只涉及到存储, 所以使用数据库略显"多余", 而且一旦消息很多之后, 数据库的性能也有限
6, 网络通信
生产者消费者作为客户端程序, 和 BrokerServer 通过网络进行通信和交互
后续会自定义应用层协议, 传输层使用 TCP 的 Socket API
上述介绍过 BrokerServer 提供的一些核心 API , 在生产者消费者程序上也需要提供的相应的 API
以创建队列这个操作为例: 客户端调用 queueDeclare(), 客户端的这个方法只是实现了向服务器发送请求, 让服务器调用服务器的 queueDeclare() , 服务器的这个方法实现了真正创建交换机, 并持久化存储, 然后返回给客户端一个响应, 告知客户端执行成功了没有
由于客户端也有 queueDeclare() , 客户端看起来是在调用自己的 queueDeclare() 从而创建出来了队列, 实际上是通过网络请求, 调用了服务器的 queueDeclare() , 而服务器是怎么做的, 客户端并不知道细节
这种方式称作: 远程过程调用(RPC)
7, TCP 连接的复用
上面说到要在生产者消费者客户端提供 BrokerServer 的核心 API :
- 1, 创建队列 queueDeclare (Declare 表示不存在则创建, 存在则不创建)
- 2, 销毁队列 queueDelete
- 3, 创建交换机 exchangeDeclare
- 4, 销毁交换机 exchageDelete
- 5, 创建绑定 queueBind
- 6, 解除绑定 queueUnbind
- 7, 发布消息 basicPublish
- 8, 订阅消息 basicSubscribe (只是告知服务器有个消费者需要这个队列的数据)
- 9, 确认消息 basicAck (让消费者显式的告诉服务器, 收到并处理了消息
由于一次 TCP 连接与断开 需要经过三次握手四次挥手, 一个客户端有可能短时间内持续使用 RPC 模式远程调用 BrokerServer 的 API, 这就需要多次 TCP 的连接和断开
所以引入 Channel (信道) 的概念, 建立 TCP 连接之后, 可以使用一个 Channel表示一次逻辑上的连接(一次请求和响应), 一个 Connection 中包含多个 Channel , 各个 Channel 中的数据互不相干, 实现一次 TCP 连接的复用
所以生产者客消费者(客户端)还需要提供四个 API
- 10, 创建 Connection (建立 TCP 连接)
- 11, 关闭 Connection (关闭 TCP 连接)
- 12, 创建 Channel (建立逻辑上的连接)
- 13, 关闭 Channel (关闭逻辑上的连接)
8, 需求分析小结
- 1, 生产者客户端, 消费者客户端, BrokerServer 服务器这三个板块, 这三者都是服务器程序
- 2, 生产者消费者 的代码主要围绕 “网络通信” 展开
- 3, BrokerServer 的代码主要围绕 “核心概念” , "核心 API " , “数据管理” 展开
二、模块划分
三、目录结构
这里各位大概率是一眼看不懂的, 只需要结合注释大致了解各个包和类是用来做什么的即可
由于项目略微复杂, 先对整体结构有个大致认知, 从下篇开始会详细介绍代码编写
相关文章:
从零手搓一个【消息队列】项目设计、需求分析、模块划分、目录结构
文章目录 一、需求分析1, 项目简介2, BrokerServer 核心概念3, BrokerServer 提供的核心 API4, 交换机类型5, 持久化存储6, 网络通信7, TCP 连接的复用8, 需求分析小结 二、模块划分三、目录结构 提示:是正在努力进步的小菜鸟一只,如有大佬发现文章欠佳之…...
【Spring Cloud】深入探索 Nacos 注册中心的原理,服务的注册与发现,服务分层模型,负载均衡策略,微服务的权重设置,环境隔离
文章目录 前言一、初识 Nacos 注册中心1.1 什么是 Nacos1.2 Nacos 的安装,配置,启动 二、服务的注册与发现三、Nacos 服务分层模型3.1 Nacos 的服务分级存储模型3.2 服务跨集群调用问题3.3 服务集群属性设置3.4 修改负载均衡策略为集群策略 四、根据服务…...
No156.精选前端面试题,享受每天的挑战和学习
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…...
如何在PIL图像和PyTorch Tensor之间进行相互转换,使用pytorch进行PIL和tensor之间的数据转换
目录 引言PIL简介PyTorch和Torchvision简介PIL转换为TensorTensor转换为PIL实例代码和解释结论参考文献 📝 引言 在计算机视觉领域,使用图像处理库对图像进行预处理是非常常见的。其中,Python Imaging Library(PIL)以…...
STM32F4X UCOSIII任务消息队列
STM32F4X UCOSIII任务消息队列 任务消息队列和内核消息队列对比内核消息队列内核消息队列 UCOSIII任务消息队列API任务消息队列发送函数任务消息队列接收函数 UCOSIII任务消息队列例程 之前的章节中讲解过消息队列这个机制,UCOSIII除了有内核消息队列之外࿰…...
8个居家兼职,帮助自己在家搞副业
越来越多的人开始追求居家工作的机会,无论是为了获得更多收入以改善生活质量,还是为了更好地平衡工作和家庭的关系,居家兼职已成为一种趋势。而在家中从事副业不仅能够为我们带来额外的收入,更重要的是,它可以让我们在…...
管理与系统思维
技术管理者不仅仅需要做事情,还需要以系统思维的方式推动组织变革,从而帮助团队和个人做到更好。原文: Management and Systems Thinking 图片来源: Dall-E "除非管理者考虑到组织的系统性,否则大多数提高绩效的努力都将注定失败。"…...
电死人的是电流还是电压?
先说答案,是电流。 这个有两个派别,一个是电流派,一个是电压派。 举个例子,拿我们的头发或者指甲之类的高电阻物质去接触高压,你会发现基本没有什么作用;还有就是冬天我们脱毛衣的时候,噼里啪啦…...
mac 编译问题记录
1、mac 编译提示 Unsupported option ‘--no-pie‘ Linux 上用 --no-pie mac 上用 -no-pie 2、mac 找不到 malloc.h 使用 #include <sys/malloc.h> Mac上使用malloc函数报错_mac malloc.h-CSDN博客...
centos 7.9同时安装JDK1.8和openjdk11两个版本
1.使用的原因 在服务器上,有些情况因为有一些系统比较老,所以需要使用JDK8版本,但随着时间的发展,新的软件出来,一般都会使用比较新的JDK版本。所以就出现了我们标题的需求,一个系统内同时安装两个不同的版…...
【JavaEE】HTML
JavaWeb HTML 超文本标记语言 超文本:文本、声音、图片、视频、表格、连接标记:有许许多多的标签组成 vscode开发工具搭建 因为我使用的IDEA是社区版,代码高亮补全缩进都有些问题,使用vscode是最好的选择~ 安装 Visual Stu…...
【数据结构--八大排序】之堆排序
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …...
c# 中的类
反射 Activator.CreateInstance class Program {static void Main(string[] args){//反射Type t typeof(Student);object o Activator.CreateInstance(t, 1, "FJ");Student stu o as Student;Console.WriteLine(stu.Name);//动态编程dynamic stu2 Activator.Cre…...
基于单片机的煤气泄漏检测报警装置设计
一、项目介绍 煤气泄漏是一种常见的危险情况,可能导致火灾、爆炸和人员伤亡。为了及时发现煤气泄漏并采取相应的安全措施,设计了一种基于单片机的煤气泄漏检测报警装置。 主控芯片采用STM32F103C8T6作为主控芯片,具有强大的计算和控制能力。…...
[导弹打飞机H5动画制作] 导弹每次飞行的随机路线制作
技术核心提示: 第一步:检测引导层插件是否具备,如果没有手工添加: createjs.MotionGuidePlugin.install(); 第二步:增加全局变量: var fValue=0; var iOddEven =0; var missileObj=null; 第三步:填写 第一帧 代码: if (missileObj)stage.removeChild(missileObj);missile…...
OpenCV实现FAST算法角点检测 、ORB算法特征点检测
目录 1 Fast算法 1.1 Fast算法原理 1.2 实现办法 1.2.1 机器学习的角点检测器 1.2.2 非极大值抑制 1.3 代码实现 1.4 结果展示 2 ,ORB算法 2.1代码实现 2.2 结果展示 1 Fast算法 1.1 Fast算法原理 1.2 实现办法 1.2.1 机器学习的角点检测器 1.2.2 …...
【Unity的 Built-in 渲染管线下实现好用的GUI模糊效果_Blur_案例分享(内附源码)】
CGPROGRAM实现好用的GUI模糊效果 实现Blur模糊方式1C#代码如下方式1_Shader代码如下实现Blur模糊方式2方式2_Shader如下实现Blur模糊方式1 其他的模糊效果,在这一篇。 效果如图: 新建一个C#文件,命名为"CommandBlur",打开C#,删除内容,复制粘贴下面的代码:…...
AR智能眼镜:提升现场服务技能、效率与盈利能力的利器(一)
随着技术的不断进步,现场服务组织正朝着远程支持转变,用以解决技能差距和生产力问题,提高员工培训和操作效率,同时为企业提高利润率,创造竞争优势。 本文将探讨增强现实(AR)、辅助现实…...
ChatGPT 在机器学习中的应用
办公室里一个机器人坐在人类旁边,Artstation 上的流行趋势,美丽的色彩,4k,充满活力,蓝色和黄色, DreamStudio出品 一、介绍 大家都知道ChatGPT。它在解释机器学习和深度学习概念方面也非常高效,…...
【JavaEE】锁策略
文章目录 前言1. 乐观锁和悲观锁2. 重量级锁和轻量级锁3. 自旋锁和挂起等待锁4. 公平锁和非公平锁5. 可重入锁和非可重入锁6. 读写锁Java synchronized 分别对应哪些锁策略1. 乐观锁和悲观锁2. 重量级锁和轻量级锁3. 自旋锁和挂起等待锁4. 公平锁和非公平锁5. 可重入锁和非可重…...
在 SDXL 上用 T2I-Adapter 实现高效可控的文生图
T2I-Adapter 是一种高效的即插即用模型,其能对冻结的预训练大型文生图模型提供额外引导。T2I-Adapter 将 T2I 模型中的内部知识与外部控制信号结合起来。我们可以根据不同的情况训练各种适配器,实现丰富的控制和编辑效果。 同期的 ControlNet 也有类似的…...
Python分支结构和循环结构
嗨喽~大家好呀,这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 一.分支结构 分支结构是根据判断条件结果而选择不同向前路径的运行方式,分支结构分为:单分支,二分支和多分支。 1࿰…...
Unity调用API函数对系统桌面和窗口截图
Unity3D调用WINAPI函数对系统窗口截图 引入WINAPI函数调用WINAPI函数进行截图使用例子 引入WINAPI函数 using System; using System.Collections; using System.Runtime.InteropServices; using System.Drawing;[DllImport("user32.dll")]private static extern Int…...
【问题思考总结】CPU怎么访问磁盘?CPU只有32位,最多只能访问4GB的空间吗?
问题 在学习操作系统的时候发现了这样一个问题,32位的CPU寻址空间只有4GB,难道只有4GB的空间可以使用吗?以此为始,我开始了一些思考。 思考 Q1:首先,我似乎混淆了一个概念,内存和外存&#x…...
UG NX二次开发(C++)-CAM-根据刀具对程序组进行重新分组
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、在UG NX中创建一个三维模型3、在UG NX/CAM中创建多个加工程序4、采用UG NX二次开发(NXOpen)实现按照刀具分组程序组4.2 创建UI Styler4.1 实现逻辑4.2 生成的代码如下:4.3 测试效果4.…...
Unity如何实现TreeView
前言 最近有一个需求,需要实现一个TreeView的试图显示,开始我一直觉得这么通用的结构,肯定有现成的UI组件或者插件可以使用,结果,找了好久,都没有找到合适的插件,有两个效果差强人意。 最后在回家的路上突然灵光一闪,想到了一种简单的实现方式,什么插件都不用,仅使用…...
Android widget 小部件使用指南强化版
Android widget 小部件使用指南强化版 一、简单UI的小部件二、含集合的小部件三、可配置的小部件四、可控制的小部件五、Android 12 Widget 更新 小部件是主屏幕定制的一个重要方面。您可以将它们视为应用程序最重要的数据和功能的“概览”视图,这些数据和功能可以直…...
Linux下C语言操作网卡的几个代码实例?特别实用
前面写了一篇关于网络相关的文章:如何获取当前可用网口。 《简简单单教你如何用C语言列举当前所有网口!》 那么如何使用C语言直接操作网口? 比如读写IP地址、读写MAC地址等。 一、原理 主要通过系统用socket()、ioctl()、实现 int sock…...
noip2011选择旅馆
1.审题:第一个人与第二个人入住的旅馆要求是同色的; 两个人去消费的旅馆并没有要求与入住的旅馆是同色的(这点要小心) 2.要求记录以下数据: 1)a[color]表示当前同为颜色color的旅馆数 2)b[co…...
vue造轮子完整指南--npm组件包开发步骤
一、项目包文件的创建和初始化。 1. 新建项目包。 vue create <Project Name> //用于发布npm包的项目文件名 ps:一般选择自定义,然后不需要Vuex和Router,其他选项按自己实际情况选择安装即可。 2.修改原始src文件名、新增组件项目存放文件和修改…...
crm系统有哪些/长沙网站优化推广方案
客户端工具:mysql,mysqladmin,mysqldump,mysqlcheck 非客户端类的管理工具:myisamchk,myisampack mysql命令提示符 mysql> 等待输入命令 > 前面提供的‘未提供结束’ ”> > —> 续航符 /*> 注释信息 mysql的命令行编辑快捷键 ctrlw&am…...
空间站 参考消息/免费发布信息不收费的网站
“安全第一、预防为主、综合治理”是关系到国家经济发展与社会稳定的安全方针。安全生产是涉及职工生命安全的大事,同时关系到企业的生存发展和稳定。 2021年6月,第十三次全国人民代表大会常务委员会第二十九次会议,通过《全国人民代表大会常…...
网站制作:网推宝|百度/互联网营销推广
使用plugin生成groovy脚本,或者参考已有的groovy脚本。 文章来自:http://www.ciandcd.com文中的代码来自可以从github下载: https://github.com/ciandcd 1. 使用插件来写groovy脚本 常用的功能,可以安装对应的插件,然后…...
求生之路2怎么做非官方网站/广州网站优化公司排名
题意:中文题,就不解释了。 题解:代码就像女生的裙子,越短看着越性感~~当我们选定树根,那么与他相邻为1的边最后一定会翻转奇数次才能变为0,与他相邻为偶数的边,最后一定翻转偶数次,所…...
wordpress4.x版本/广点通广告平台
Ubuntu操作基本快捷键* 打开主菜单 Alt F1* 运行 Alt F2* 显示桌面 Ctrl Alt d* 最小化当前窗口 Alt F9* 最大化当前窗口 Alt F10* 关闭当前窗口 Alt F4* 截取全屏 Print Screen* 截取窗口 Alt Print Screen默认特殊快捷键* 展示所有窗口程序 F10* 展示当前窗…...
莆田seo快速排名/seo分析报告
前言 很多人都知道读取配置文件,这是初级做法,上升一点难度是使用java bean的方式读取自定义配置文件,但是大家很少有知道读取pom文件信息,接下来我都会讲到。 正文 笔者还是基于Spring Boot :: (v1.5.8.RELEASE)&#…...