rabbitmq的发布确认

生产者将信道设置成 confirm 模式,一旦信道进入 confirm 模式, 所有在该信道上面发布的
消息都将会被指派一个唯一的 ID (从 1 开始),一旦消息被投递到所有匹配的队列之后,broker
就会发送一个确认给生产者(包含消息的唯一 ID),这就使得生产者知道消息已经正确到达目的队
列了,如果消息和队列是可持久化的,那么确认消息会在将消息写入磁盘之后发出,broker 回传
给生产者的确认消息中 delivery-tag 域包含了确认消息的序列号,此外 broker 也可以设置
basic.ack 的 multiple 域,表示到这个序列号之前的所有消息都已经得到了处理。

单个确认发布  

这是一种简单的确认方式,它是一种 同步确认发布 的方式,也就是发布一个消息之后只有它
被确认发布,后续的消息才能继续发布,waitForConfirmsOrDie(long)这个方法只有在消息被确认
的时候才返回,如果在指定时间范围内这个消息没有被确认那么它将抛出异常。
这种确认方式有一个最大的缺点就是: 发布速度特别的慢, 因为如果没有确认发布的消息就会
阻塞所有后续消息的发布,这种方式最多提供每秒不超过数百条发布消息的吞吐量。当然对于某
些应用程序来说这可能已经足够了。
import cn.hutool.core.lang.UUID;
import com.rabbitmq.client.Channel;public class publishMessageIndividually {private static final int MESSAGE_COUNT = 5;public static void publishMessageIndividually() throws Exception {try (Channel channel = RabbitMqUtils.getChannel()) {String queueName = UUID.randomUUID().toString();channel.queueDeclare(queueName, false, false, false, null);//开启发布确认channel.confirmSelect();long begin = System.currentTimeMillis();for (int i = 0; i < MESSAGE_COUNT; i++) {String message = i + "";channel.basicPublish("", queueName, null, message.getBytes());//服务端返回 false 或超时时间内未返回,生产者可以消息重发boolean flag = channel.waitForConfirms();if (flag) {System.out.println("消息发送成功");}}long end = System.currentTimeMillis();System.out.println("发布" + MESSAGE_COUNT + "个单独确认消息,耗时" + (end - begin) +"ms");}}
}

耗时

 批量确认发布

上面那种方式非常慢,与单个等待确认消息相比,先发布一批消息然后一起确认可以极大地
提高吞吐量,当然这种方式的缺点就是:当发生故障导致发布出现问题时,不知道是哪个消息出现
问题了,我们必须将整个批处理保存在内存中,以记录重要的信息而后重新发布消息。当然这种
方案仍然是同步的,也一样阻塞消息的发布。
import cn.hutool.core.lang.UUID;
import com.rabbitmq.client.Channel;public class publishMessageBatch {private static final int MESSAGE_COUNT = 5;public static void publishMessageBatch() throws Exception {try (Channel channel = RabbitMqUtils.getChannel()) {String queueName = UUID.randomUUID().toString();channel.queueDeclare(queueName, false, false, false, null);//开启发布确认channel.confirmSelect();//批量确认消息大小int batchSize = 100;//未确认消息个数int outstandingMessageCount = 0;long begin = System.currentTimeMillis();for (int i = 0; i < MESSAGE_COUNT; i++) {String message = i + "";channel.basicPublish("", queueName, null, message.getBytes());outstandingMessageCount++;if (outstandingMessageCount == batchSize) {channel.waitForConfirms();outstandingMessageCount = 0;}}//为了确保还有剩余没有确认消息 再次确认if (outstandingMessageCount > 0) {channel.waitForConfirms();}long end = System.currentTimeMillis();System.out.println("发布" + MESSAGE_COUNT + "个批量确认消息,耗时" + (end - begin) +"ms");}}public static void main(String[] args) throws Exception {publishMessageBatch.publishMessageBatch();}
}

 耗时

 异步确认发布

异步确认虽然编程逻辑比上两个要复杂,但是性价比最高,无论是可靠性还是效率都没得说,
他是利用回调函数来达到消息可靠性传递的,这个中间件也是通过函数回调来保证是否投递成功,
下面就让我们来详细讲解异步确认是怎么实现的。
import cn.hutool.core.lang.UUID;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmCallback;import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;public class publishMessageAsync {private static final int MESSAGE_COUNT = 5;public static void publishMessageAsync() throws Exception {try (Channel channel = RabbitMqUtils.getChannel()) {String queueName = UUID.randomUUID().toString();channel.queueDeclare(queueName, false, false, false, null);//开启发布确认channel.confirmSelect();/*** 线程安全有序的一个哈希表,适用于高并发的情况* 1.轻松的将序号与消息进行关联* 2.轻松批量删除条目 只要给到序列号* 3.支持并发访问*/ConcurrentSkipListMap<Long, String> outstandingConfirms = newConcurrentSkipListMap<>();/*** 确认收到消息的一个回调* 1.消息序列号* 2.true 可以确认小于等于当前序列号的消息* false 确认当前序列号消息*/ConfirmCallback ackCallback = (sequenceNumber, multiple) -> {if (multiple) {//返回的是小于等于当前序列号的未确认消息集合 是一个 mapConcurrentNavigableMap<Long, String> confirmed =outstandingConfirms.headMap(sequenceNumber, true);//清除该部分未确认消息集合confirmed.clear();}else{//只清除当前序列号的消息outstandingConfirms.remove(sequenceNumber);}};ConfirmCallback nackCallback = (sequenceNumber, multiple) -> {String message = outstandingConfirms.get(sequenceNumber);System.out.println("发布的消息"+message+"未被确认,序列号"+sequenceNumber);};/*** 添加一个异步确认的监听器* 1.确认收到消息的回调* 2.未收到消息的回调*/channel.addConfirmListener(ackCallback, nackCallback);long begin = System.currentTimeMillis();for (int i = 0; i < MESSAGE_COUNT; i++) {String message = "消息" + i;/*** channel.getNextPublishSeqNo()获取下一个消息的序列号* 通过序列号与消息体进行一个关联* 全部都是未确认的消息体*/outstandingConfirms.put(channel.getNextPublishSeqNo(), message);channel.basicPublish("", queueName, null, message.getBytes());}long end = System.currentTimeMillis();System.out.println("发布" + MESSAGE_COUNT + "个异步确认消息,耗时" + (end - begin) +"ms");}}public static void main(String[] args) throws Exception {publishMessageAsync.publishMessageAsync();}
}

耗时

 以上 3 种发布确认速度对比

单独发布消息

同步等待确认,简单,但吞吐量非常有限。

批量发布消息

批量同步等待确认,简单,合理的吞吐量,一旦出现问题但很难推断出是那条

消息出现了问题。

异步处理: 最佳性能和资源使用,在出现错误的情况下可以很好地控制,但是实现起来稍微难些

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

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

相关文章

AI巨浪下,数据技术如何驱动智能未来?

引言 数据技术是大数据时代的核心驱动力&#xff0c;也是推动各行各业数字化转型和智能化升级的关键因素。随着云计算、人工智能、区块链等新兴技术的不断发展和融合&#xff0c;数据技术也呈现出多模态、混合处理、自动化管理等新的趋势和特点。 8 月 19 日&#xff08;周六&…

【宝藏系列】嵌入式 C 语言代码优化技巧【超详细版】

【宝藏系列】嵌入式 C 语言代码优化技巧【超详细版】 文章目录 【宝藏系列】嵌入式 C 语言代码优化技巧【超详细版】前言整形数除法和取余数合并除法和取余数通过2的幂次进行除法和取余数取模的一种替代方法使用数组下标全局变量使用别名变量的生命周期分割变量类型局部变量指针…

STM32 F103C8T6学习笔记3:串口配置—串口收发—自定义Printf函数

今日学习使用STM32 C8T6的串口&#xff0c;我们在经过学习笔记2的总结归纳可知&#xff0c;STM32 C8T6最小系统板上有三路串口&#xff0c;如下图&#xff1a; 今日我们就着手学习如何配置开通这些串口进行收发&#xff0c;这里不讲串口通信概念与基础&#xff0c;可以自行网上…

一文读懂HTML

文章目录 HTML的历史HTML的作用HTML的基本语言 HTML的历史 HTML&#xff08;HyperText Markup Language&#xff09;的历史可以追溯到20世纪90年代早期&#xff0c;它是互联网发展的重要里程碑之一。以下是HTML的历史概述&#xff1a; 早期阶段&#xff08;1980年代末 - 1990年…

FLatten Transformer 简化版Transformer

今天在找论文时&#xff0c;看到一篇比较新奇的论文&#xff0c;在这里跟大家分享一下&#xff0c;希望可以给一些人提供一些思路。虽然现在Transformer 比较火&#xff0c;在分割上面也应用的比较多&#xff0c;但是我一直不喜欢用&#xff0c;其中一个原因是结构太复杂了&…

C++:模拟实现list及迭代器类模板优化方法

文章目录 迭代器模拟实现 本篇模拟实现简单的list和一些其他注意的点 迭代器 如下所示是利用拷贝构造将一个链表中的数据挪动到另外一个链表中&#xff0c;构造两个相同的链表 list(const list<T>& lt) {emptyinit();for (auto e : lt){push_back(e);} }void test_…

运动路径规划,ROS发布期望运动轨迹

目录 一、Python实现&#xff08;推荐方法&#xff09; 1.1代码cubic_spline_path.py 1.2使用方法 二、C实现 参考博客 想让机器人/智能车无人驾驶&#xff0c;要有期望路径&#xff0c;最简单的是一条直线&#xff0c;或者是一条光滑曲线。 生成路径的方法有两种&#xf…

【网络编程(二)】NIO快速入门

NIO Java NIO 三大核心组件 Buffer&#xff08;缓冲区&#xff09;&#xff1a;每个客户端连接都会对应一个Buffer&#xff0c;读写数据通过缓冲区读写。Channel&#xff08;通道&#xff09;&#xff1a;每个channel用于连接Buffer和Selector&#xff0c;通道可以进行双向读…

Redis数据库的可视化工具AnotherRedisDesktopManager使用+抖音直播小玩法实践

一、它是什么 Another Redis DeskTop Manager 是一个开源项目&#xff0c;提供了以可视化的方式管理 Redis 的功能&#xff0c;可供免费下载安装&#xff0c;也可以在此基础上进行二次开发&#xff0c;主要特点有&#xff1a; 支持 Windows 平台和 MacOS 平台 支持查询 Key、…

QT中的按钮控件Buttons介绍

目录 Buttons 按钮控件 1、常用属性介绍 2、按钮介绍 2.1QPushButton 普通按钮 2.2QtoolButton 工具按钮 2.3Radio Button单选按钮 2.4CheckButton复选按钮 2.5Commam Link Button命令链接按钮 2.6Dialog Button Box命令链接按钮 Buttons 按钮控件 在Qt里&#xff0c;…

Viobot开机指南

0.前言 本篇旨在让每个拿到Viobot设备的用户都能够第一时间测试它的效果&#xff0c;以及将设备配置到自己的环境下面。 1.上电 首先&#xff0c;我们先要把设备接上电源线和网线&#xff0c;最简单的方式就是网线直连电脑。 电源选用12V1.5A设备自带的电源即可。 2.配置网…

深入学习前端开发,掌握HTML、CSS、JavaScript等技术

课程链接&#xff1a; 链接: https://pan.baidu.com/s/1WECwJ4T8UQfs2FyjUMbxig?pwdi654 提取码: i654 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 --来自百度网盘超级会员v4的分享 课程介绍&#xff1a; 第1周&#xff1a;HTML5基础语法与标签 &#x1f…

web集群学习:搭建 LNMP应用环境

目录 LNMP的介绍&#xff1a; LNMP组合工作流程&#xff1a; FastCGI介绍&#xff1a; 1、什么是 CGI 2、什么是 FastCGI 配置LNMP 1、部署LNMP环境 2、配置LNMP环境 LNMP的介绍&#xff1a; 随着 Nginx Web 服务的逐渐流行&#xff0c;又岀现了新的 Web 服务环境组合—…

【Spring Cloud 八】Spring Cloud Gateway网关

gateway网关 系列博客背景一、什么是Spring Cloud Gateway二、为什么要使用Spring Cloud Gateway三、 Spring Cloud Gateway 三大核心概念4.1 Route&#xff08;路由&#xff09;4.2 Predicate&#xff08;断言&#xff09;4.3 Filter&#xff08;过滤&#xff09; 五、Spring …

如何使用Kali Linux进行密码破解?

今天我们探讨Kali Linux的应用&#xff0c;重点是如何使用它来进行密码破解。密码破解是渗透测试中常见的任务&#xff0c;Kali Linux为我们提供了强大的工具来帮助完成这项任务。 1. 密码破解简介 密码破解是一种渗透测试活动&#xff0c;旨在通过不同的方法和工具来破解密码…

力扣初级算法(数组拆分)

力扣初级算法&#xff08;数组拆分&#xff09; 每日一算法&#xff1a; 力扣初级算法&#xff08;数组拆分&#xff09; 学习内容&#xff1a; 1.问题描述 给定长度为 2n 的整数数组 nums &#xff0c;你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) …

机器人CPP编程基础-03变量类型Variables Types

机器人CPP编程基础-02变量Variables 全文AI生成。 C #include<iostream>using namespace std;main() {int a10,b35; // 4 bytescout<<"Value of a : "<<a<<" Address of a : "<<&a <<endl;cout<<"Val…

Vue+ElementUI实现选择指定行导出Excel

这里记录一下&#xff0c;今天写项目时 的一个需求&#xff0c;就是通过复选框选中指定行然后导出表格中选中行的Excel表格 然后这里介绍一个工具箱(模板)&#xff1a;vue-element-admin 将它拉取后&#xff0c;运行就可以看到如下界面&#xff1a; 这里面的很多功能都已经实现…

【NAS群晖drive异地访问】使用cpolar远程访问内网Synology Drive「内网穿透」

文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…

jupyter切换conda虚拟环境

环境安装 conda install nb_conda 进入你想使用的虚拟环境&#xff1a; conda activate your_env_name 在你想使用的conda虚拟环境中&#xff1a; conda install -y jupyter 在虚拟环境中安装jupyter&#xff1a; conda install -y jupyter 重启jupyter 此时我们已经把该安装…