RabbitMQ-从基础到实战(2)— 防止消息丢失

简介: 转载请注明出处0.目录RabbitMQ-从基础到实战(1)— Hello RabbitMQRabbitMQ-从基础到实战(3)— 消息的交换(上)RabbitMQ-从基础到实战(4)— 消息的交换(中)RabbitMQ-从基础到实战(5)— 消息的交换(下)RabbitMQ-从基础到实战(6)— 与Spring集成1.简介RabbitMQ中,消息丢失可以简单的分为两种:客户端丢失和服务端丢失。

转载请注明出处

0.目录

RabbitMQ-从基础到实战(1)— Hello RabbitMQ

RabbitMQ-从基础到实战(3)— 消息的交换(上)

RabbitMQ-从基础到实战(4)— 消息的交换(中)

RabbitMQ-从基础到实战(5)— 消息的交换(下)

RabbitMQ-从基础到实战(6)— 与Spring集成

1.简介

RabbitMQ中,消息丢失可以简单的分为两种:客户端丢失和服务端丢失。针对这两种消息丢失,RabbitMQ都给出了相应的解决方案。

2.防止客户端丢失消息

image

如图,生产者P向队列中生产消息,C1和C2消费队列中的消息,默认情况下,RabbitMQ会平均的分发消费给C1C2(Round-robin dispatching),假设一个任务的执行时间非常长,在执行过程中,客户端挂了(连接断开),那么,该客户端正在处理且未完成的消息,以及分配给它还没来得及执行的消息,都将丢失。因为默认情况下,RabbitMQ分发完消息后,就会从内存中把消息删除掉。

3.消息确认(Message acknowledgment)

为了解决上述问题,RabbitMQ引入了消息确认机制,当消息处理完成后,给Server端发送一个确认消息,来告诉服务端可以删除该消息了,如果连接断开的时候,Server端没有收到消费者发出的确认信息,则会把消息转发给其他保持在线的消费者。

验证上述问题

首先,我们验证上述问题(客户端丢失消息)是否真的存在,对Consumer进行如下改造。

image

先生产两条消息

image

启动消费者,在消费者接收到消息,还没处理完成的时候,强制关掉

image

这时,观察控制台,发现两条消息都没有了,1条是在执行中丢失的,还有1条,已经分配给这个Consumer,还没来得及处理,也丢失了

image

这证明了上述问题是真的存在的,如果发生在生产环境,将产生难以预料的后果

引入消息确认机制

为了方便观察,我们用CMD来运行Consumer,要通过maven打成可执行的JAR包,需要在pom.xml中增加如下配置

复制代码
<build>
        <finalName>Consumer</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>com.liyang.ticktock.rabbitmq.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>assembly</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

        </plugins>
    </build>
复制代码

上述配置描述了最终打包名字、入口类路径、带上依赖包、使用1.8版本的JDK进行打包,配置完后,就可以通过maven的install方法,在target目录生成可执行的jar包,如果包大小很小,应检查配置,是不是没有带上依赖包

image

再次改造Consummer类

image

install成可执行jar包,通过cmd开启两个consumer

image

通过Sender发送一条消息,然后用Ctrl+C结束先收到消息的Consumer,发现另外一个Consumer接收到了未处理完的消息

image

问题得到了解决,现在消费者在执行过程中死掉也不会丢失消息了

看一下发送确认的方法

复制代码
 1 /**
 2      * Acknowledge one or several received
 3      * messages. Supply the deliveryTag from the {@link com.rabbitmq.client.AMQP.Basic.GetOk}
 4      * or {@link com.rabbitmq.client.AMQP.Basic.Deliver} method
 5      * containing the received message being acknowledged.
 6      * @see com.rabbitmq.client.AMQP.Basic.Ack
 7      * @param deliveryTag the tag from the received 这个是RabbitMQ用来区分消息的,文档在这 8      * @param multiple true to acknowledge all messages up to and 为true的话,确认所有消息,为false只确认当前消息
 9      * including the supplied delivery tag; false to acknowledge just
10      * the supplied delivery tag.
11      * @throws java.io.IOException if an error is encountered
12      */
13     void basicAck(long deliveryTag, boolean multiple) throws IOException;
复制代码

在官方文档中,这样描述deliveryTag

image

简单来说,就是RabbitMQ内部用来区分消息的一个标签,从envelope中获取就行了

忘记确认将引起内存泄漏

RabbitMQ只有在收到消费者确认后,才会从内存中删除消息,如果消费者忘了确认(更多情况是因为代码问题没有执行到确认的代码),将会导致内存泄漏

验证一下

注释掉Consumer中的确认代码

image

image

运行Sender和Consumer,不停的生产消费消息,发现消费者在正常的消费消息

image

查看控制台,发现已经被吃掉了43KB的内存,所以,在试用过程中,一定要保证消息确认在任何情况下都可以发出,否则即使消费者处理完成,RabbitMQ也不会把消息在内存中清除,在该消费者断开连接之后,还会把消息转发给其他消费者重新处理,将引发难以预计的问题

image

image

4.消息的持久化

现在,消费者宕机已经无法影响到我们的消息了,但如果RabbitMQ重启了,消息依然会丢失。所幸的是,RabbitMQ提供了持久化的机制,将内存中的消息持久化到硬盘上,即使重启RabbitMQ,消息也不会丢失。但是,仍然有一个非常短暂的时间窗口(RabbitMQ收到消息还没来得及存到硬盘上)会导致消息丢失,如果需要严格的控制,可以参考官方文档

要使用RabbitMQ的消息持久化,在声明队列时设置一个参数即可

image

注意,RabbitMQ不允许对一个已经存在的队列用不同的参数重新声明,对于试图这么做的程序,会报错,所以,改动之前代码之前,要在控制台中把原来的队列删除

image

重新声明队列后,发现Durable为true

image

重启RabbitMQ

image

队列的消息没有丢失

image

5.结束语

这一章介绍了RabbitMQ消息的确认和持久化,后面将会继续深入介绍RabbitMQ的其他特性

 

http://www.cnblogs.com/4----/p/6526033.html

相关实践学习
快速体验阿里云云消息队列RocketMQ版
本实验将带您快速体验使用云消息队列RocketMQ版Serverless系列实例进行获取接入点、创建Topic、创建订阅组、收发消息、查看消息轨迹和仪表盘。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
前端开发 JavaScript Java
基于SSM的鲜花线上销售系统设计与实现
基于SSM的鲜花线上销售系统设计与实现
531 1
|
存储 Java 数据库连接
MyBatis-Plus 基础操作指南:实现高效的增删改查
MyBatis-Plus 基础操作指南:实现高效的增删改查
794 0
|
5月前
|
传感器 人工智能 边缘计算
AI赋能油田巡检——无人机视频监控系统的技术解析
无人机油田巡检系统融合无人机硬件与AI视频监控技术,实现全域覆盖、智能分析和高效管理。通过多旋翼/固定翼无人机搭载高分辨率摄像头及传感器,采集多维数据;结合YOLOv9等算法进行异常检测,准确率高达98%。系统支持5G实时传输、边缘计算及集中化管理平台,提供可视化监控与预测性维护。基于开源框架设计,灵活扩展且成本低,大幅提升油田巡检效率与安全性。
559 0
|
8月前
|
缓存 Java 开发者
Java字面量详解:概念、分类与使用实例
本文介绍了Java字面量的概念、分类及应用。
253 11
|
机器学习/深度学习 算法 Ubuntu
解读深大的视觉开源源码
这篇文章详细解读了深圳大学步兵视觉开源代码RP_Infantry_Plus,包括功能介绍、效果展示、依赖环境、整体框架、实现方案、通讯协议、配置与调试以及总结展望,提供了RoboMaster2019赛场上装甲板和小符文的识别方案,并通过自定义通讯协议将视觉处理信息发送给下位机。
解读深大的视觉开源源码
|
图形学 开发者
U3D小游戏开发秘籍:实战代码优化与性能提升技巧
【7月更文第13天】Unity 3D(U3D)作为游戏开发界的瑞士军刀,以其强大的灵活性和跨平台能力,让无数创意化为指尖上的精彩。但对于初涉U3D的小游戏开发者而言,如何高效构建项目,确保流畅体验,是一门必修课。本文将深入浅出,结合实战代码示例,分享一系列优化与提升U3D小游戏性能的宝贵技巧。
260 1
|
传感器 Python
门禁管理系统工程是一个涉及硬件和软件集成的复杂系统,旨在控制人员的出入,并记录和管理相关数据。
门禁管理系统工程是一个涉及硬件和软件集成的复杂系统,旨在控制人员的出入,并记录和管理相关数据。
|
编解码
FFT_频谱分析(数字信号处理)
用FFT对信号作频谱分析是学习数字信号处理的重要内容。经常需要进行谱分析的信号是模拟信号和时域离散信号。对信号进行谱分析的重点在于频谱分辨率及分析误差。频谱分辨率D和频谱分析的点数N直接相关,其分辨率为2π/N 。因此2π/N≤D,可以据这个公式确定频率的分辨率。 FFT分析频谱的误差在于得到的是离散谱,而信号(非周期信号)是连续谱,只有当N较大时,离散谱的包络才能逼近于连续谱。因此N要适当选择大一些。 周期信号的频谱是离散谱,只有用整数倍周期的长度作FFT,得到的离散谱才能代表周期信号的频谱。如果不知道信号周期,可以尽量选择信号的观察时间长一些。 对模拟信号进行谱分析时,首先要按照
923 1
FFT_频谱分析(数字信号处理)
|
云安全 人工智能 Cloud Native
阿里云的认证有什么方向?几个等级?
通过阿里云认证就可获得入职阿里云的机会,还有可能被阿里云的合作企业录取。