RabbitMQ怎么保证可靠性

RabbitMQ怎么保证可靠性

  • 前言
  • 生产端问题
    • 解决方案
    • 代码
    • 验证
  • RabbitMQ问题
  • 消费端问题
    • 解决方案
    • 代码
    • 验证
  • 总结

前言

RabbitMQ相信大家都非常熟悉了,今天咱们来聊聊怎么保证RabbitMQ的可靠性。

那什么时候会出现问题呢?

第一种是生产端出现的问题。我们向队列中发送消息的时候,消息不一定可以发送到MQ中,这个时候如果我们不做任何处理,这样消息丢失了。

第二种则是RabbitMQ出现的问题。也就是说现在生产端的成功将消息发送到了RabbitMQ,但由于MQ并没有做持久化,这样宕机重启之后消息可能就丢失了。

第三种则是消费端的问题。消费端处理消息时如果出现异常,默认的解决方式是在重复消费多次,当次数超过阈值时直接删除消息,这也导致消息丢失。

接下来咱们就看看怎么应对以上三种问题。

生产端问题

解决方案

这里我们需要清楚发送的一个大体流程。

生产端发送消息到MQ之后,会收到一个结果,这个结果有acknack两种。

其中ack代表消息成功到达了交换机,但并不意味者消息到达了队列。不过ack的情况下消息未送达队列,会有相应的错误信息提醒。

nack就代表消息并未送达交换机

那么,怎么才能知道消息发送情况呢?

可以设置callback来获取消息发送结果。

代码

局部callback设置如下

    @GetMapping("testmq")
    public Result testmq(){
        String orderId = String.valueOf(UUID.randomUUID());
        String messageData = "下订单!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String,Object> map=new HashMap<>();
        map.put("orderId",orderId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);

//        设置发送的callback
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        correlationData.getFuture().addCallback(result -> {
            // 判断结果
            if (result.isAck()) {
                log.info("发送成功");
            } else {
                log.error("消息未达到交换机,发送失败");
            }
        }, ex -> {
            log.error("出现异常,发送失败");
        });

        rabbitTemplate.convertAndSend(RabbitMQConfig.NORMALEXCHANGE, RabbitMQConfig.TESTROUTING, map, message -> {
            message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
            return message;
        }, correlationData);
        return Result.succ("ok");
    }

验证

消息发送成功
在这里插入图片描述
交换机名称有误
在这里插入图片描述
队列路由出错
虽然没有错误,但给了我们warning。
在这里插入图片描述

RabbitMQ问题

这里就比较简单了,那就是做下持久化就可以了

首先是交换机,队列和消息的持久化
交换机

@Bean
    DirectExchange normalExchange() {
        /**
         * durable 是否持久化
         * autoDelete 没有queue绑定时是否自动删除
         */
        return new DirectExchange(NORMALEXCHANGE, true, false);
    }

队列

@Bean
    public Queue cleanDQueue() {
        return QueueBuilder.durable(CLEANQUEUE)
                .build();
    }

消息的持久化

rabbitTemplate.convertAndSend(RabbitMQConfig.NORMALEXCHANGE, RabbitMQConfig.TESTROUTING, map, message -> {
			// 设置消息持久化
           message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
            return message;
        }, correlationData);

消费端问题

解决方案

消费端出现错误时,会进行重试,当重试次数超过阈值之后有三种解决方案,如下

  • RejectAndDontRequeueRecoverer:超过阈值,直接丢失消息。
  • ImmediateRequeueMessageRecoverer:超过阈值,返回nack,然后消息重新入队。
  • RepublishMessageRecoverer:超过阈值直接将消费失败的消息投递到指定交换机。

这里我们以RepublishMessageRecoverer为例做下演示。

代码

首先需要声明消费消息失败后传递的交换机和队列

   @Bean
    DirectExchange normalExchange() {
        /**
         * durable 是否持久化
         * autoDelete 没有queue绑定时是否自动删除
         */
        return new DirectExchange(NORMALEXCHANGE, true, false);
    }
//  用于处理消费失败消息的队列
    @Bean
    public Queue republishQueue() {
        return QueueBuilder.durable(REPULISHQUEUE)
                .build();
    }
//  绑定失败消费消息队列
    @Bean
    Binding bindingRepublish() {
        return BindingBuilder.bind(republishQueue()).to(normalExchange()).with(REPULISHROUTING);
    }


然后配置下RepublishMessageRecoverer策略,随便找个config注入下bean就可以。

 //  设置RepublishMessageRecoverer,消费失败的消息转移到另一队列中,交给管理员手动处理
    @Bean
    public MessageRecoverer republishMessageRecoverer(RabbitTemplate rabbitTemplate) {
        /**
         * NORMALEXCHANGE   接收消费失败消息的交换机
         * REPULISHROUTING  接收消费失败消息的路由key
         */
        return new RepublishMessageRecoverer(rabbitTemplate, NORMALEXCHANGE, REPULISHROUTING);
    }

验证

咱们看看如果消费出错会咋样

我们可以看到被消费的队列中信息被删除了。
在这里插入图片描述
然后我们设置的转入队列中的消息数加一,这时候我们可以接收下该队列中的信息,存储到数据库中,方便维护人员手动进行处理。
在这里插入图片描述

总结

从生产端、RabbitMQ以及消费端三方面介绍了一下怎么保证RabbitMQ的可靠性,另外还有关于死信队列和延迟队列的内容在这篇博客中,大家有兴趣可以看一下。

RabbitMQ的死信队列和延迟队列

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[数据集][目标检测]手枪检测数据集VOC+YOLO格式3000张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;3000 标注数量(xml文件个数)&#xff1a;3000 标注数量(txt文件个数)&#xff1a;3000 标注…

IP代理池是什么?

从事跨境行业的朋友们总会有一个疑问&#xff0c;为什么自己所合作的IP代理商的IP在使用的过程中账号会有莫名封禁的问题&#xff0c;会不会是自己在使用的过程中错误的操作违反了平台的规则&#xff0c;其实不然有可能会是IP代理池纯净度不高的问题&#xff0c;有可能自己在使…

[个人总结]-java常用方法

1.获取项目根路径 user.dir是一个系统属性&#xff0c;表示用户当前的工作目录&#xff0c;大多数情况下&#xff0c;用户的当前工作目录就是java项目的根目录&#xff08;src文件的同级路径&#xff09; System.getProperty("user.dir") 结果&#xff1a;D:\code…

智能报警器——物联网应用创新

一、项目的目的、意义 我国自2020年至11月起共接报火灾23.3万起&#xff0c;亡1335人&#xff0c;伤837人&#xff0c;直接财产损失36.12亿元&#xff0c;其中&#xff0c;因电线短路、过负荷及电气设备故障等电气原因引起的火灾共40481起&#xff0c;占火灾总数的30.7%&#…

【面试经典150题】合并两个有序数组

目录 一.利用库函数sort二.逆双指针 一.利用库函数sort 首先我们先来看下题目的描述&#xff1a; 两个非递减的数组重新排列成非递减顺序到第一个数组中&#xff0c;并且第一个数组已经提前开好了空间。我们完全可以将nums2数组先放进nums1数组后面&#xff0c;然后整体对num…

ChatGPT制作一个简单的客服机器人

包含功能&#xff1a; MVP&#xff08;最简可行产品&#xff09;版本的客服机器人应该聚焦于核心功能&#xff0c;以快速上线和测试用户反馈为目标。以下是一个简化的版本&#xff1a; 自动问答&#xff08;FAQ&#xff09;功能&#xff1a; 支持回答常见问题&#xff0c;例如…

[数据集][目标检测]数据集VOC格式岸边垂钓钓鱼fishing目标检测数据集-4330张

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;4330 标注数量(xml文件个数)&#xff1a;4330 标注类别数&#xff1a;1 标注类别名称:["fishing"] 每…

禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》Chapter 6插图

禹晶、肖创柏、廖庆敏《数字图像处理&#xff08;面向新工科的电工电子信息基础课程系列教材&#xff09;》 Chapter 6插图

Spring:数据校验(Validation)

1. 概述 在开发中&#xff0c;我们经常遇到参数校验的需求&#xff0c;比如用户注册的时候&#xff0c;要校验用户名不能为空、用户名长度不超过20个字符、手机号是合法的手机号格式等等。如果使用普通方式&#xff0c;我们会把校验的代码和真正的业务处理逻辑耦合在一起&#…

如何使用Dora SDK完成Fragment流式切换和非流式切换

我想大家对Fragment都不陌生&#xff0c;它作为界面碎片被使用在Activity中&#xff0c;如果只是更换Activity中的一小部分界面&#xff0c;是没有必要再重新打开一个新的Activity的。有时&#xff0c;即使要更换完整的UI布局&#xff0c;也可以使用Fragment来切换界面。 何…

ISCC2024之Misc方向WP

目录 FunZip Magic_Keyboard Number_is_the_key RSA_KU 成语学习 钢铁侠在解密 工业互联网模拟仿真数据分析 精装四合一 时间刺客 有人让我给你带个话 FunZip 题目给了一个txt&#xff0c;内容如下 一眼丁真&#xff0c;base隐写&#xff0c;使用工具即可得到flag Fl…

functional函数对象库学习

类模板 std::function 是一种通用多态函数包装器。std::function 的实例能存储、复制及调用任何可复制构造 (CopyConstructible) 的可调用 (Callable) 目标——函数&#xff08;通过其指针&#xff09;、lambda 表达式、bind 表达式或其他函数对象&#xff0c;以及成员函数指针…

Java进阶学习笔记31——日期时间

Date&#xff1a; 代表的是日期和时间。 分配Date对象并初始化它以表示自标准基准时间&#xff08;称为纪元&#xff09;以来的指定毫秒数&#xff0c;即1970年1月1日00:00:00。 有参构造器。 package cn.ensource.d3_time;import java.util.Date;public class Test1Date {pu…

Tomcat安装和配置(图文详解)_tomcat安装及配置教程

Tomcat是一个开源的Web应用服务器&#xff0c;它是Apache软件基金会的一个项目。Tomcat被广泛用作Java Servlet和JavaServer Pages&#xff08;JSP&#xff09;技术构建的Web应用程序的运行环境。 它是轻量级的&#xff0c;适合中小型系统和并发访问用户不是很多的场合&#x…

FPGA基于DE2-115开发板驱动HC_SR04超声波测距模块|集成蜂鸣器,led和vga提示功能

文章目录 前言一、实验原理二、Verilog文件2.1 时钟分频2.2 超声波测距2.3 超声波驱动 三、实现过程3.1 模块说明3.2 引脚分配 三、演示视频总结参考 前言 环境 硬件 DE2-115 HC-SR04超声波传感器 软件 Quartus 18.1 目标结果 使用DE2-115开发板驱动HC-SR04模块&#xff0…

力扣刷题--2085. 统计出现过一次的公共字符串【简单】

题目描述 给你两个字符串数组 words1 和 words2 &#xff0c;请你返回在两个字符串数组中 都恰好出现一次 的字符串的数目。 示例 1&#xff1a; 输入&#xff1a;words1 [“leetcode”,“is”,“amazing”,“as”,“is”], words2 [“amazing”,“leetcode”,“is”] 输出…

万字详解 MySQL MGR 高可用集群搭建

文章目录 1、MGR 前置介绍1.1、什么是 MGR1.2、MGR 优点1.3、MGR 缺点1.4、MGR 适用场景 2、MySQL MGR 搭建流程2.1、环境准备2.2、搭建流程2.2.1、配置系统环境2.2.2、安装 MySQL2.2.3、配置启动 MySQL2.2.4、修改密码、设置主从同步2.2.5、安装 MGR 插件 3、MySQL MGR 故障转…

QT之动态加载树节点(QTreeWidget)

之前写过一篇动态加载ComboBox&#xff0c;可参见下面这篇文章 QT之动态加载下拉框&#xff08;QComboBox&#xff09; 同理QTreeWidget也可以实现动态加载&#xff0c;在一些异步加载数据&#xff0c;并且数据加载比较耗时&#xff0c;非常实用。 效果 原理分析 要实现此类效…

[数据集][图像分类]骨关节炎严重程度分类数据集14038张4分类

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;14038 分类类别数&#xff1a;4 类别名称:[“grade0”,“grade2”,“grade3…

如何使用KolorPanotourPro制作全景图像网页

目录 前言 KolorPanotourPro是什么 如何制作全景网页 1.拥有全景图 2.导入图片 3.在多张全景图中跳转 4.查看制作的全景网页 结束语 前言 今天是坚持写博客的第十五天&#xff0c;继续为努力和坚持的大家点赞和鼓掌。 书接上文&#xff0c;我们讲了如何使用如何使用A…