RabbitMQ 2025/3/5

高性能异步通信组件。

同步调用

以支付为例:

可见容易发生雪崩。

异步调用

以支付为例:

支付服务当甩手掌柜了,不管后面的几个服务的结果。只管库库发,后面那几个服务想取的时候就取,因为消息代理里可以一直装,缓存消息。

消息代理(英文Broker)

消息代理相关的技术MQ技术

Erlang面向并发的语言

 

RabbitMQ安装部署

可直接采用Docker,方便。

RabbitMQ消息流转的过程(整体架构)

消费者监听队列,发送者不直接发给队列,而是发给exchange交换机,交换机会根据规则把消息路由给不同队列。

因为RabbitMQ的性能很强,每秒钟可以达到数万的并发,所以企业有多个项目的话,往往部署一套RabbitMQ就够了,多个项目可以共享RabbitMQ服务。但是大家一起的话,很可能交换机出现冲突,所以引出RabbitMQ的新概念virtual-host(虚拟主机),类似与MySQL里的database(众所周知,MySQL里可以创建多个database,每个database的表和其他database的表直接是相互隔离的),每个项目都创一个自己的virtual-host,就可以相互隔离开了。

例子:MQ入门-06.RabbitMQ-快速入门_哔哩哔哩_bilibili

交换机不存只负责转发。交换机和队列必须有一个关系,才能给队列发消息。binding绑定关系。

数据隔离

虚拟主机是实现了数据隔离。

不同的项目创建不同的用户。为新建用户建一个虚拟主机。

视频举例:MQ入门-07.RabbitMQ-数据隔离_哔哩哔哩_bilibili

RabbitMQ的java客户端

这里我们不采用Rabbit官方提供的java客户端,而是Spring AMQP,它是基于AMQP协议(消息收发与语言和平台无关),官方提供的java客户端使用起来繁琐,所以使用Spring AMQP。

4:00  MQ入门-08.Java客户端-快速入门_哔哩哔哩_bilibili

因为是简单入门案例,可以省去交换机这个步骤。

控制台创建队列->pom里引入spring-amqp依赖->yaml里配置RabbitMQ服务端信息(如地址主机名、端口、虚拟主机名、用户、密码),这样微服务才能连接到RabbitMQ->发送消息(SpringAMQP提供了RabbitTemplate工具类,方便我们发送消息)->接受消息

接收者接受消息的代码:加一个@Comonent把它注册成Spring的一个Bean,这个类的内部要有一个方法,这个方法要加上@RabbitListener(也就是消费者的监听者)的注解后面再带上队列名,现在只要队列有消息,方法就可以拿到了。方法参数自己设。

WorkQueues

任务模型,让多个消费者绑定到一个队列,共同消费队列中的消息。

那么队列中的消息会被哪个消费者收到呢?

模拟WorkQueue(实现一个队列绑定多个消费者)

MQ入门-09.Java客户端-WorkQueue_哔哩哔哩_bilibili

在RabbitMQ控制台建立一个队列->一个发消息的->2个消费者

下图两个消费者,一个发送者。

 

队列同一个消息只能被一个消费者处理,很多条消息的话均匀分配(默认轮询,1人1条)。(上图2个消费者结果有奇偶规律)

把很多消息平均分给消费者,可以加快消息处理速度。

每个消费者能力不一样(通过sleep(ms)修改),均匀分配消息(默认)肯定是不合理的,只需要修改application.yml,设置preFetch值为1,实现能者多劳。

Fanout交换机(广播交换机)

再看一下以前学的这个发消息的过程。带有交换机的完整模型。

交换机的作用是接受发送者发送的消息,并将消息路由到与其绑定的队列。

那么什么是Fanout交换器?

特征:把接收到的消息路由到每一个和他绑定的队列。(队列中的消息只能被一个消费者处理,有了Fanout交换机,发的消息就可以被多个消费者处理了。我们完全可以给每个微服务创建一个队列,然后队列绑到交换机上,fanout交换机想广播一样,给每个队列群发/复制消息。)

案例步骤:声明2个队列,一个交换机exhanges,然后banding绑定,第一种方法可以直接用控制台发消息然后查看,还有一种方法java代码,2段接受代码,1段发送代码(这回调3个参数的api,exchange,null,message,之前写的例子用到的都是两个参数,队列名和消息)。

Direct交换机(定向)

MQ入门-11.Java客户端-Direct交换机_哔哩哔哩_bilibili

和原来差不多,这回交换机选direct,队列设置bindingkey,发送时发送者的参数分别设好exchange,routingkey值,message。其余的步骤和原来一样。

所以两个key值一样,direct交换机也能实现Fanout交换机的功能。一个queue可以设多个bindingkey。

Topic交换机(话题)

 队列bindingkey可以通过通配符简易设置。

topic和direct比除了多了一个统配符,功能差不多。

声明队列交换机

之前队列和交换机的创建都是依靠控制台,这次学习用代码声明队列交换机,这样项目一启动就会自己创建队列和交换机了。

可以用new的方式。(更简单)

也可以用builder方式。

发送者只管发,什么也不关心,所以通常我们在消费者这一端,声明队列交换机及绑定关系。

步骤(以Fanout交换机为例):创建FanoutConfiguration类,声明交换机,队列,绑定关系。可以new(比较简单),也可以builder构建(比较专业)。

上述基于JavaBean绑定太麻烦了,这回学习注解@RatbbitListener。

基于JavaBean还是基于注解,完全个人喜好了。(但是如果基于javabean,声明direct交换机好像没法写很多bindingKey)

消息转换器

以前我们发消息一直用到rabbitTemplate的convertAndSend方法。我们发消息是可以传任何java对象作为消息,网络传输其实是以字节传的,直接对象不行,因此传的时候要把java对象转换成字节。这个转换就是由消息转换器转的。

java里有一种JDK自带的序列化的一个工具(能把任一java对象序列化成字节的形式),所以这个消息转换的过程就是采用JDK自带的序列化方式。

ObjectOutputStream:对象流,jdk自带的序列化工具,能把任意java对象序列化成字节。

但是推荐使用JSON的消息转换器。

发送方和接收方一定要用相同的消息转换器。

pom配置好之后到MAVEN里刷新一下。

给发送方和接收方都配置一个消息转换类。

对比图(下边的JSON的消息转换器)

业务改造

把业务从OpenFeign的同步调用改成基于MQ的异步调用。

OpenFeign:02-基本概念_哔哩哔哩_bilibili

nacos可以抽取共享配置,不用重复进行同样的配置。

共同代码可以写到common里

消息可靠性

发送者的可靠性

发送者重连

yml

发送者确认

路由失败的两种原因:

exchange2交换机没连队列,路由失败。返回ACK(因为消息确实发出去了)

routingkey和bandingkey没有匹配上的。

如果返回NACK要重发消息。

none是关闭(默认)

simple是同步阻塞

correlated异步的

至此,ConfirmCallback和ReturnCallback全部写完了。

唯一,uuid,最简单的随机算法

MQ的可靠性

消息传到MQ也不一样可靠,因为MQ本身也可能把消息弄丢。

MQ内存储存的方式,可能弄丢消息,还有可能导致MQ性能下降和阻塞。

为此,产生两个方案:数据持久化(把数据提前持久化存到磁盘,提前的意思:不是等到满了再存到磁盘,提前就开始往磁盘存了)、LazyQueue

数据持久化

持久化的一种方法:写出到磁盘,这样就永久保存了。

交换机的持久化(默认都是持久的交换机、durable属性)(Spring的AMQP代码生成的交换机默认也是持久化的)

队列持久化(默认持久化durable属性)(Spring的AMQP代码生成的默认也是持久化的)

消息持久化(手动设置为Persistent)

LazyQueue

上节课写了数据持久化,当我们把交换机、队列、消息持久化了以后,就不用再担心MQ宕机而导致消息丢失了,不仅如此,RabbitMQ也不会再因为消息堆积配置out而出现阻塞了。但是数据持久化后,不仅要在内存里写,还要再磁盘里写一份,这样每条消息处理的耗时就增加了,这也就导致它的整体并发能力有点下降。为了解决这个问题,引入了一种新的队列模式,lazy Queue(消息直接写磁盘里)。它不仅仅具有数据持久化的优势,同时还解决了并发能力下降的问题。

那么怎样去设置一个队列变成Lazy Queue模式呢

第一种方法,控制台添加

第二种方法,代码添加(声明bean的方式或者注解都可以)

消费者的可靠性

消费者确认机制

三种状态(ack,nack,reject):不管哪种状态,都不能在刚收到消息的时候就返回,我们应该根据处理结果去做判断,也就是consumer处理完的时候。

注意:这回配置的是消费者下的application文件。

有个缺点:消息异常了就会像踢球一样反复被踢来踢去,下面学的失败重试机制就可以解决这个问题(设置最大尝试次数)

失败重试机制

第一种:重试次数耗尽后直接reject,不要了

第二种:重试次数耗尽后,返回nack,消息回到队列,再重试

第三种:重试次数耗尽后,消费者将失败消息扔进另一个交换机,这个交换机连着另一个队列

下面以第三种方式为例(相比于前两种更复杂,多了一个交换机和一个新队列)

业务幂等性

解决重复消费问题(比如事务发到消费者那了,本来消费者要给MQ返回一个ACK,因为断电没发送出去,MQ以为消费者宕机了,于是恢复电的时候,MQ又会重新给消费者发送一次,可消费者已经处理完这个事务了,如果这个事务涉及到支付,那消费者就会白白消费两次。)这时就用到业务幂等性了。

下面以消息重复提交导致业务被重复执行的这个场景为例的几个方案:

1.唯一id(我们可以给消息带上唯一的id)

这种方案存在业务侵入的问题:本来是没有id这个属性的,现在的消息都带了id属性,并且还放在了数据库里!!!!!

2.业务判断

加了一个业务判断,当订单来了后,不急着标记订单为已支付,而是每次都在标记前查询一下订单状态。

延迟消息

在上面三个可靠性都失败下的兜底方案——延迟消息

死信交换机

一旦我们通过dead-letter-exchange属性指定了一个交换机,那么死信就都会被投到这个交换机里,不会被丢弃了。

我们已经有了一组交换机和队列,再准备一组特殊的交换机和队列,给上面的队列通过dead-letter-exchange属性指定下面的交换机,现在下面的交换机就变成上面的队列的死信交换机了。我们不会给上面的队列绑定消费者,通常是给死信交换机的队列绑定消费者。发送者向上面的交换机发消息,发消息时给消息设置过期时间TTL=30s,然后消息就发到上面的队列,因为上面的队列没有消费者,就在这里停下来了开始等待,有个计时器开始等待数30秒,30秒后消息变成死信进入死信交换机。这样就通过死信交换机的形式实现了延迟效果。

延迟消息插件

用了这个插件,只要简单的把delay属性配置成true就好了,然后就可以实现延迟消息。

步骤:首先下载配置好插件->声明交换机并设置其delay属性为true(可用注解或bean方式)->发消息的时候要设置一个过期时间

利用延迟消息解决用户订单超时未支付问题

可以分成几步:下单之后发消息,完成延迟消息的发送。编写消息监听,它要干的事是去修改订单状态。利用延迟消息实现延时任务的效果。

MQ高级-13.延迟消息-取消超时订单_哔哩哔哩_bilibili

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

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

相关文章

Win10 访问 Ubuntu 18 硬盘

目录 方案一:使用Samba共享服务Ubuntu 18 端配置Windows 10 端访问 方案二:使用 SSHFS(需在 Windows 上安装 SSH 客户端)Ubuntu 18 端配置Windows 10 端配置 方案三:使用 FTP 服务Ubuntu 18 端配置Windows 10 端访问 方…

Android15使用FFmpeg解码并播放MP4视频完整示例

效果: 1.编译FFmpeg库: 下载FFmpeg-kit的源码并编译生成安装平台库 2.复制生成的FFmpeg库so文件与包含目录到自己的Android下 如果没有prebuiltLibs目录,创建一个,然后复制 包含目录只复制arm64-v8a下

Hadoop、Hive、Spark的关系

Part1:Hadoop、Hive、Spark关系概览 1、MapReduce on Hadoop 和spark都是数据计算框架,一般认为spark的速度比MR快2-3倍。 2、mapreduce是数据计算的过程,map将一个任务分成多个小任务,reduce的部分将结果汇总之后返回。 3、HIv…

计算机网络篇:基础知识总结与基于长期主义的内容更新

基础知识总结 和 MySQL 类似,我同样花了一周左右的时间根据 csview 对计算机网络部分的八股文进行了整理,主要的内容包括:概述、TCP 与 UDP、IP、HTTP,其中我个人认为最重要的是 TCP 这部分的内容。 在此做一篇目录索引&#xf…

[密码学实战]Java实现国密TLSv1.3单向认证

一、代码运行结果 1.1 运行环境 1.2 运行结果 1.3 项目架构 二、TLS 协议基础与国密背景 2.1 TLS 协议的核心作用 TLS(Transport Layer Security) 是保障网络通信安全的加密协议,位于 TCP/IP 协议栈的应用层和传输层之间,提供: • 数据机密性:通过对称加密算法(如 AE…

09 HarmonyOS NEXT 仿uv-ui Tag组件开发教程系列(三)

温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! 文章目录 Tag组件实战应用与最佳实践1. 复杂场景应用1.1 标签筛选系统 2. 性能优化实践2.1 状态管理优化2.2 渲染性能优化 3. 实用功能扩展3.1 拖拽…

clickhouse查询效率低

《关于ClickHouse查询效率低的探讨》 在数据处理的世界里,数据库扮演着至关重要的角色。ClickHouse是一款专为在线分析处理(OLAP)设计的列式存储数据库管理系统。它因其快速的数据写入和查询速度而闻名,尤其适合处理海量数据。如…

Linux系统基于ARM平台的LVGL移植

软硬件介绍:Ubuntu 20.04 ARM 和(Cortex-A53架构)开发板 基本原理 LVGL图形库是支持使用Linux系统的Framebuffer帧缓冲设备实现的,如果想要实现在ARM开发板上运行LVGL图形库,那么就需要把LVGL图形库提供的关于帧缓冲设…

【GPT入门】第14课 openai调用高德地图案例实现多轮会话与多轮接口调用

【GPT入门】第14课 openai调用高德地图案例实现多轮会话与多轮接口调用 1.使用openai调用高德地图API概述2. 高德接口调用申请3.实现代码(多个function调用,多轮对话)4.执行结果1.使用openai调用高德地图API概述 任务描述:使用openai调用高德地图API,实现用户问地理有关的…

每日一题-----面试

一、什么是孤儿进程?什么是僵尸进程? 1.孤儿进程是指父进程在子进程结束之前就已经退出,导致子进程失去了父进程的管理和控制,成为了 “孤儿”。此时,这些子进程会被系统的 init 进程(在 Linux 系统中&…

Python深度学习算法介绍

一、引言 深度学习是机器学习的一个重要分支,它通过构建多层神经网络结构,自动从数据中学习特征表示,从而实现对复杂模式的识别和预测。Python作为一门强大的编程语言,凭借其简洁易读的语法和丰富的库支持,成为深度学…

【Python】Django 中的算法应用与实现

Django 中的算法应用与实现 在 Django 开发中,算法的应用可以极大地扩展 Web 应用的功能和性能。从简单的数据处理到复杂的机器学习模型,Django 都可以作为一个强大的后端框架来支持这些算法的实现。本文将介绍几种常见的算法及其在 Django 中的使用方法…

旋转编码器原理与应用详解:从结构到实战 | 零基础入门STM32第四十七步

主题内容教学目的/扩展视频旋转编码器电路原理,跳线设置,结构分析。驱动程序与调用。熟悉电路和驱动程序。 师从洋桃电子,杜洋老师 📑文章目录 一、旋转编码器是什么?二、内部结构揭秘2.1 机械组件解剖2.2 核心部件说明…

如何禁止电脑中某个应用联网

一、通过防火墙基础设置(快速操作) 打开控制面板 在任务栏搜索框输入“控制面板”并打开,将右上角“查看方式”切换为“大图标”。 进入防火墙设置 点击 Windows Defender防火墙 → 左侧选择 允许应用或功能通过Windows Defender防火墙。…

aws(学习笔记第三十二课) 深入使用cdk(API Gateway + event bridge)

文章目录 aws(学习笔记第三十二课) 深入使用cdk学习内容:1. 使用aws API Gatewaylambda1.1. 以前的练习1.2. 使用cdk创建API Gateway lambda1.3. 确认cdk创建API Gateway lambda 2. 使用event bridge练习producer和consumer2.1. 代码链接2.2. 开始练习2.3. 代码部…

城市霓虹灯夜景拍照后期Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色教程 在城市霓虹灯夜景拍摄中,由于现场光线复杂等因素,照片可能无法完全呈现出当时的视觉感受。通过 Lr 调色,可以弥补拍摄时的不足。例如,运用基本调整面板中的曝光、对比度、阴影等工具,可以处理出画面的整体明暗…

自然语言处理:文本分类

介绍 大家好,我这个热衷于分享知识的博主又来啦!之前我们一起深入探讨了自然语言处理领域中非常重要的两个方法:朴素贝叶斯和逻辑斯谛回归。在探索的过程中,我们剖析了朴素贝叶斯如何基于概率原理和特征条件独立假设,…

PDFMathTranslate安装使用

PDF全文翻译!!!! PDFMathTranslate安装使用 它是个啥 PDFMathTranslate 可能是一个用于 PDF 文件的数学公式翻译 工具。它可能包含以下功能: 提取 PDF 内的数学公式 将数学公式转换成 LaTeX 代码 翻译数学公式的内…

【由技及道】量子构建交响曲:Jenkinsfile流水线的十一维编程艺术【人工智障AI2077的开发日志008】

摘要:当代码提交触发时空涟漪,当构建流水线穿越量子维度——欢迎来到自动化构建的终极形态。本文将揭示如何用Jenkinsfile编写量子构建乐章,让每次代码提交都成为跨维度交响乐的音符。 动机:构建系统的量子哲学 “主人啊&#xff…

K8S高可用集群-小白学习之二进制部署(ansible+shell)

一.K8S高可用集群配置概述 序言:本文从一个小白的视角进行K8S的研究和部署,采用二进制的方式是为了更清楚了分解部署流程及了解这个集群是怎么运作的,加上ansible+shell是方便在这个过程中,遇到了问题,我们可以不断的快速重复部署来测试和研究问题的所在点,本文的架构图…