从 0 到 1 ,手把手教你编写《消息队列》项目(Java实现) —— 介绍项目/ 需求分析

news2024/12/22 22:12:19

文章目录

  • 一、消息队列是什么?
  • 二、需求分析
    • 结构解析
    • 功能解析
    • 规则解析
      • 绑定关系
      • 交换机类型
      • 消息应答
  • 三、持久化存储
  • 四、网络通信
    • 提供的API
    • 复用TCP连接
  • 五、消息队列概念图


一、消息队列是什么?


消息队列 (Message Queue, MQ)就是将阻塞队列这一数据结构提取成了一个独立程序,故消息队列也是一个生产者消费者模型.

生产者消费者模型的作用:

1️⃣解耦合:
如果是客户端A直接调用服务器B,那么客户端A与服务器B的代码耦合度就比较高,更改任意一方的代码,可能另一方的代码都会随之受到牵连而也需要改写.

而如果是客户端A将请求发送至生产者消费者模型,服务器B再从中取出,此时A和B的代码耦合度就低,就不会出现牵一发而动全身这样麻烦的情况了.

2️⃣削峰填谷:
服务器C,业务逻辑比较复杂,无法同时处理很多的请求,如果此时有多个客户端向服务器C发送请求,那么服务器C就有挂掉的风险.
引入消息队列后,让所有的客户端都将请求发送到消息队列中,服务器从消息队列中取,
在客户端请求较多时,仍让服务器收到的请求保持在安全数量,即达到削峰效果.
在服务器较为空闲时,仍可以让其从消息队列中获取请求,达到填谷效果.
以此来降低因请求过多而让服务器挂掉的风险.

使用场景:

双十一的时候,淘宝客户端会产生大量订单,客户端将订单提交到服务器,此时服务器就会面临大量订单,那么服务器面对远超自己承受能力的庞大数据量,可能就会挂掉.

此时就可以引入 生产者消费者模型 >>> 消息队列,让淘宝客户端的订单,发送到消息队列,再让服务器根据自己的承受能力自行取订单.


二、需求分析

此处咱们编写的消息队列,主要参考市面上比较知名的消息队列 RabbitMQ.
消息队列的核心功能主要有两个:
1️⃣让生产者将需要转发的数据(称之为消息)存储到消息队列中.
2️⃣让消费者将需要取出的消息,从消息队列中取出
在这里插入图片描述

此处的消息队列会有N多个生产者,N多个消费者,其中Borker Server 最为重要,是用来存储和转发消息的.


根据上述要实现的两个核心功能就提取出了六个核心概念:
1️⃣生产者(Producer):生产消息的一方

2️⃣消费者(Consumer):消费消息的一方

3️⃣中间人(Broker):存放消息的一方

4️⃣发布消息(Publish):生产者将生产出的消息,存放到中间人处的功能.

5️⃣订阅消息(Subscribe):消费者订阅中间人此处的某些消息的功能.

6️⃣消费消息(Consume):服务器将消息推送给订阅的消费者的功能.


结构解析

前三个概念是比较好理解的,那我们就来剖析一下后三个功能.

让我们先来看看RabbitMQ的内部结构

在这里插入图片描述

上述结构遵循了AMPQ协议.

Broker Server内部的结构有多个<虚拟机>.

虚拟机:类似于MySQL中的 batabase,是一组数据的逻辑集合.

交换机:生产者投递消息到 Broker Server 实际上,是把消息投递到某个交换机,再由交换机把自身的规则把消息转发给对应的队列.

消息队列:真正用来存储消息的实体.

Binding绑定关系:记录交换机与队列之间的绑定关系.


功能解析

发布消息功能:其实就是生产者将消息发送给对应的交换机,交换机再根据不同的转发规则,转发给与之相绑定且符合规则的消息队列.

订阅消息功能:其实就是消费者去某个消息队列处注册,表明自己要从这个消息队列中取消息,这个注册称之为订阅.(此处的订阅消息就好像是在抖音上给一个博主点了关注,)

消费消息功能:其实就是当消息队列中有消息时,自动向在这个消息队列注册过的消费者推送信息.(当你关注的博主发布新视频时,便会自动将视频推送给你)


规则解析

上述三个功能中有两个核心规则:
1️⃣让生产者的消息正确存储到对应队列的规则(姑且称为正确存储规则).

2️⃣保证将消息转发到对应的消费者手中的规则,而没有在网络上丢失(姑且称为正确转发规则).

正确存储规则要如何实现呢?
发布消息的本质是将消息到交换机,再由对应的交换机存储到与之绑定且符合转发规则的队列中.
故正确存储规则的实现主要依靠
绑定关系 与 交换机的类型.

绑定关系

绑定关系本质上是给 交换机 与 消息队列 通过 一个绑定钥匙进行绑定.
所以绑定关系本质上只有三个字段,
exchangeName(交换机名称),queueName(消息队列名称),bindingKey(绑定钥匙).
在这里插入图片描述

在不同的交换机类型中bindingKey也起到不同的作用.


交换机类型

发送消息到交换机时,一共会提交三个参数,
1.消息,2.交换机名称,3.routingKey
交换机共有四种类型:

Direct类型
Fanout类型
Topic类型

Header类型(其中 Header 这种方式比较复杂, 比较少见. 常用的是前三种交换机类型. 咱们此处也主要实现这三种)

Direct类型(直接交换机): 生产者向该类型交换机发送消息时, 直接指定队列名称,无视绑定关系.(即指定的队列与该交换机有没有绑定都可以)

在这里插入图片描述

Fanout类型(扇出交换机):生产者发送的消息会被发送到所有与该交换机存在绑定关系的队列中.
在这里插入图片描述

Topic类型(主题交换机): 发送消息指定⼀个字符串为 routingKey. 然后去绑定关系表中去查找与该交换机绑定的队列,并且与绑定关系中的 bindingKey匹配成功才发送到这个队列中.(匹配算法后续讲解)

在这里插入图片描述


正确转发规则要如何实现呢?
其实很简单,让消费者拿到消息后,告诉服务器一声就ok了,也就是消息应答.


消息应答

应答模式分成两种.
自动应答 : 消费者只要消费了消息, 就算应答完毕了. Broker 直接删除这个消息.(等于没应答)
手动应答 : 消费者手动调用应答接口, Broker Server 收到应答请求之后, 才真正删除这个消息.

手动应答的目的, 是为了保证消息确实被消费者处理成功了. 在⼀些对于数据可靠性要求高的场景, 比较常见.


三、持久化存储

Exchange交换机, Queue消息队列, Binding绑定关系, Message消息 都有持久化的需求.
以保证当程序重启 / 主机重启, 上述内容不丢失.

这就需要我们将这些数据存储到硬盘中,这样当程序重启/主机重启时,才不会丢失数据.

但是为了保证 咱们这个《消息队列》程序能够高效的转发处理数据,所以这些数据也要在内存中存储一份,
并且每次重启后,都要将硬盘的数据读取恢复到内存中.


四、网络通信

⽣产者和消费者都是客户端程序, broker Server 则是作为服务器. 通过网络进⾏通信.
在⽹络通信的过程中, 客户端部分要提供对应的 api, 来实现对服务器的操作.

以生产者创建交换机举例:
在这里插入图片描述

提供的API

创建交换机 (exchangeDeclare)
销毁交换机 (exchangeDelete)
创建队列 (queueDeclare)
销毁队列 (queueDelete)
创建绑定 (queueBind)
解除绑定 (queueUnbind)
发布消息 (basicPublish)
订阅消息 (basicConsume)
确认消息 (basicAck)

上述这9个API是服务器和客户端都有的,

客户端的这些API让客户使用 RPC 远程调用服务器上的方法.
服务器的这些API则是实现各种操作的.


复用TCP连接

还有4个API是提供网络连接支持的
创建 Connection (创建TCP连接)
关闭 Connection (销毁TCP连接)
创建 Channel (创建逻辑连接)
关闭 Channel (销毁逻辑链接)

一个Connection对象代表一个TCP连接.

Channel 则是 Connection 中的逻辑通道.
⼀个 Connection 中可以包含多个 Channel.
Channel 和 Channel 之间的数据是独立的. 不会相互干扰.

这样的设定主要是为了 客户端在短时间多次远程调用 Broker Server 的 API时,减少频繁创建销毁TCP连接的资源开销,更好的复用 TCP 连接, 达到长连接的效果

此时就可以将 Connection 理解成教学楼,Channel理解为教室,一栋教学楼里可以有多个教室,且每个教室互不干扰.


五、消息队列概念图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1054511.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

国庆作业2

select实现服务器并发 代码&#xff1a; #include <myhead.h>#define ERR_MSG(msg) do{\printf("%d\n",__LINE__);\perror(msg);\ }while(0)#define PORT 8888#define IP "192.168.1.5"int main(int argc, const char *argv[]) {//创建流式套接字…

格拉姆角场GAF将时序数据转换为图像并应用于东南大学轴承故障诊断(Python代码,CNN模型)

1.运行效果&#xff1a;格拉姆角场GAF将时序数据转换为图像并应用于东南大学轴承故障诊断&#xff08;Python代码&#xff0c;CNN模型&#xff09;_哔哩哔哩_bilibili 环境库 只要tensorflow版本大于等于2.4.0即可运行 2.GAF的内容 GAF是一种用于时间序列数据可视化和特征提…

崇州街子古镇中秋国庆热闹非凡

今天&#xff08;国庆节日&#xff09;下午约4点钟&#xff0c;笔者实在耐不住寂寞&#xff0c;走出寄居养老的成都市崇州街子古镇青城神韵小区&#xff0c;去到国家AAAA级旅游景区那古色古香的街子古镇街道&#xff0c;旨在要亲身感受一下今年这里过双节&#xff0c;气氛究竟会…

28294-2012 钢渣复合料 课堂随笔

声明 本文是学习GB-T 28294-2012 钢渣复合料. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了混凝土用钢渣复合料的术语和定义、原材料组成及要求、强度等级、技术要求、试验方 法、检验规则、包装、标识、运输与贮存。 本标准…

WinHex数据恢复方法(误删后没覆盖)

winhex永远滴神&#xff01;winhex永远滴神&#xff01;winhex永远滴神&#xff01; md&#xff0c;安卓手机插u盘&#xff0c;改个文件夹名竟然把整个文件夹搞没了&#xff01;于是我赶紧查怎么恢复&#xff0c;然后依次找到并试用了diskgenus&#xff08;410RMB&#xff09;、…

信息安全:使用程序编写基于密钥的加密方式

目录 前言RSA算法代码实现设计思路结果示意 Diffie-Hellman算法代码实现设计思路结果示意 前言 信息安全是计算机科学的一个重要分支&#xff0c;它涉及到保护信息的机密性、完整性和可用性。信息加密是信息安全的一种常用手段&#xff0c;它通过使用一些数学算法和密钥&#…

P1525 [NOIP2010 提高组] 关押罪犯(并查集)

[NOIP2010 提高组] 关押罪犯 题目描述 S 城现有两座监狱&#xff0c;一共关押着 N N N 名罪犯&#xff0c;编号分别为 1 − N 1-N 1−N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久&#xff0c;如果客观条件具备则随时可能爆发冲突。我们用“怨气值”&#x…

编程每日一练(多语言实现)基础篇:满足abcd=(ab+cd)^2的数 (增加Go语言实现)

文章目录 一、实例描述二、技术要点三、代码实现3.1 C 语言实现3.2 Python 语言实现3.3 Java 语言实现3.4 JavaScript 语言实现3.5 Go 语言实现 一、实例描述 假设 abcd 是一个四位整数&#xff0c;将它分成两段&#xff0c;即 ab 和 cd&#xff0c;使之相加求和后再平方。求满…

linux入门---信号量

什么是信号量 信号量的本质是一个计数器&#xff0c;通常用来表示公共资源中资源数量多少&#xff0c;公共资源是指可以被多个进程同时访问的资源&#xff0c;访问没有被保护的公共资源时可能出现数据不一致的问题&#xff0c;比如说一个进程对公共资源执行一些写操作&#xf…

Python 数据分析与挖掘(一)

Python 数据分析与挖掘&#xff08;数据探索&#xff09; 数据探索 1.1 需要掌握的工具&#xff08;库&#xff09; 1.1.1 Nump库 Numpy 提供多维数组对象和各种派生对象&#xff08;类矩阵&#xff09;&#xff0c;利用应用程序接口可以实现大量且繁琐的数据运算。可以构建…

一文搞懂如何求MOS管的等效阻抗

首先先明确方法论&#xff0c;求等效电阻有多种方法&#xff0c;这里使用加压求流法&#xff0c;即我们要求从MOS的哪端看进去等效阻抗&#xff0c;就在哪个端口加一个电压源&#xff0c;并将原电路所有独立源置零&#xff08;电压源短路&#xff0c;电流源断路&#xff09;&am…

【MySQL】MySQL 官方安装包形式

MySQL 官方提供3种包&#xff1a; 1. 源码包 mysql-5.7.42.tar.gz mysql-5.7.42-aarch64.tar.gz http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.34.tar.gz http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.42.tar.gz需要用户根据自己的CPU架构选择对应的…

文心一言 VS 讯飞星火 VS chatgpt (103)-- 算法导论10.1 1题

一、用go语言&#xff0c;仿照图 10-1&#xff0c;画图表示依次执行操作 PUSH(S&#xff0c;4)、PUSH(S&#xff0c;1)、PUSH(S&#xff0c;3)、POP(S)、PUSH(S&#xff0c;8)和 POP(S)每一步的结果&#xff0c;栈 S初始为空&#xff0c;存储于数组 S[1…6]中。 文心一言&…

国庆10.01

TCPselect 代码 服务器 #include<myhead.h> #include<sqlite3.h> #define PORT 6666 //端口号 #define IP "192.168.0.104" //IP地址//键盘事件 int jp(fd_set tempfds,int maxfd) {char buf[128] ""; //用来接收数据char buf1[128] …

RHEL8.0安装+基础命令练习+discuz(lamp)论坛搭建

上课练习环境&#xff1a; RHEL8.0系统镜像下载&#xff1a; 链接1&#xff1a;https://pan.baidu.com/s/1wX2j-aTO1VRcHQYpCDYnEg 提取码&#xff1a;6buv 链接2&#xff1a;https://ws28.cn/f/32i4oq8p5r1 &#xff08;下载完2个文件后只需要解压001&#xff0c;推荐压缩…

树莓派4B串口通信配置方式

目录 1树莓派4B的安装&#xff1a; 1.1安装Serial与使用 1.1.1安装serial 1.1.2打开串口 1.2设置硬件串口为GPIO串口&#xff08;修改串口映射关系&#xff09; 1.2.1修改配置文件 2.1minicom串口 2.1.1安装minicom 这篇博客源于&#xff1a;工创赛。需要让树莓派与STM…

Java集合处理Stream流使用解析

Stream Stream是Java 8引入的一个新的API&#xff0c;用于处理集合数据的流式操作。它提供了一种更简洁、更灵活的方式来处理集合数据&#xff0c;可以实现更高效的数据处理和转换。 使用Stream&#xff0c;可以通过一系列的操作来对集合数据进行筛选、映射、排序、聚合等操作…

SpringBoot终极讲义第一章笔记

01.Spring Boot简介 1.Spring的本质和作用 spring的本质就是一个"容器",它负责创建并管理容器中的对象(组件,也称为Bean),并管理组件之间的依赖关系(何为依赖关系:A组件需要调用B组件方法,称为A依赖于B) 因此学习Spring最常用的两个注解: Component:将被修饰的类…

使用VSCODE 调试ros2具体设置

vscode 调试 ROS2 张得帅&#xff01; 于 2023-09-09 15:39:39 发布 456 收藏 1 文章标签&#xff1a; vscode ros2 版权 1、在下列目录同层级找到.vscode文件夹 . ├── build ├── install ├── log └── src 2、 安装ros插件 3、创建tasks.json文件&#xff0c;添…

真正理解浏览器渲染更新流程

浏览器渲染更新过程 文章目录 浏览器渲染更新过程帧维度解释帧渲染过程一些名词解释Renderer进程GPU进程rendering(渲染) vs painting(绘制)⭐位图纹理Rasterize(光栅化) 1. 浏览器的某一帧开始&#xff1a;vsync2. Input event handlers3. requestAnimationFrame4. 强制重排(可…