RabbitMQ4:work模型

news2024/11/24 15:59:48

欢迎来到“雪碧聊技术”CSDN博客!

在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将不断探索Java的深邃世界,分享最新的技术动态、实战经验以及项目心得。

让我们一同在Java的广阔天地中遨游,携手提升技术能力,共创美好未来!感谢您的关注与支持,期待在“雪碧聊技术”与您共同成长!

目录

一、work模型?

1、什么是work模型?

2、案例

①案例介绍

②具体操作

③观察上述现象:无论两个消费者的消费速度一致,还是不一致,最终二者消费的消息数量都是25条(平分,一人从队列取一半)。

3、为何会出现上述问题?

4、如何解决上述问题?

5、根据上述的思路,解决该问题

二、总结

1、知识总结

2、面试题:如何避免消息堆积问题?

①给队列上绑定多个消费者(work模型),从而提高消费速度

②优化代码,使代码执行速度变快,消费速度也就变快了

③rabbitMQ的默认规则:队列中的同一条消息,只能被一个消费者消费。即:不会出现两个消费者消费同一条消息的现象,从而提高消费速度。

④通过设置prefetch,来控制消费者手里最多有1条消息,不允许堆积消息,实现能者多劳。(最重要的一点)


一、work模型?

1、什么是work模型?

        work queues,是一种任务模型。简单来说就是让多个消费者绑定到一个队列,共同消费队列中的消息。

        注意:rabbitMQ默认同一条消息只能被一个消费者消费。

        即:不会出现两个消费者消费同一条消息的现象。

2、案例

①案例介绍

②具体操作

  • 第一步:创建一个队列work.queue

  • 第二步:编写生产者代码,1秒的时间,向队列work.queue发送50条消息

运行结果:

  • 第三步:编写监听者代码,监听队列work.queue的消息
@Component //交给spring管理
public class MqListener {

    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue1(String msg){//消费者1
        System.out.println("消费者1 收到了 work.queue的消息... :【" + msg + "】");
    }

    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue2(String msg){//消费者2
        System.err.println("消费者2 收到了 work.queue的消息... :【" + msg + "】");
    }
    
}

运行结果:

消费者1 收到了 work.queue的消息... :【hello, work, message_1】
消费者2 收到了 work.queue的消息... :【hello, work, message_2】
消费者1 收到了 work.queue的消息... :【hello, work, message_3】
消费者2 收到了 work.queue的消息... :【hello, work, message_4】
消费者1 收到了 work.queue的消息... :【hello, work, message_5】
消费者2 收到了 work.queue的消息... :【hello, work, message_6】
消费者1 收到了 work.queue的消息... :【hello, work, message_7】
消费者2 收到了 work.queue的消息... :【hello, work, message_8】
消费者1 收到了 work.queue的消息... :【hello, work, message_9】
消费者2 收到了 work.queue的消息... :【hello, work, message_10】
消费者1 收到了 work.queue的消息... :【hello, work, message_11】
消费者2 收到了 work.queue的消息... :【hello, work, message_12】
消费者1 收到了 work.queue的消息... :【hello, work, message_13】
消费者2 收到了 work.queue的消息... :【hello, work, message_14】
消费者1 收到了 work.queue的消息... :【hello, work, message_15】
消费者2 收到了 work.queue的消息... :【hello, work, message_16】
消费者1 收到了 work.queue的消息... :【hello, work, message_17】
消费者2 收到了 work.queue的消息... :【hello, work, message_18】
消费者1 收到了 work.queue的消息... :【hello, work, message_19】
消费者2 收到了 work.queue的消息... :【hello, work, message_20】
消费者1 收到了 work.queue的消息... :【hello, work, message_21】
消费者2 收到了 work.queue的消息... :【hello, work, message_22】
消费者1 收到了 work.queue的消息... :【hello, work, message_23】
消费者2 收到了 work.queue的消息... :【hello, work, message_24】
消费者1 收到了 work.queue的消息... :【hello, work, message_25】
消费者2 收到了 work.queue的消息... :【hello, work, message_26】
消费者1 收到了 work.queue的消息... :【hello, work, message_27】
消费者2 收到了 work.queue的消息... :【hello, work, message_28】
消费者1 收到了 work.queue的消息... :【hello, work, message_29】
消费者2 收到了 work.queue的消息... :【hello, work, message_30】
消费者1 收到了 work.queue的消息... :【hello, work, message_31】
消费者2 收到了 work.queue的消息... :【hello, work, message_32】
消费者1 收到了 work.queue的消息... :【hello, work, message_33】
消费者2 收到了 work.queue的消息... :【hello, work, message_34】
消费者1 收到了 work.queue的消息... :【hello, work, message_35】
消费者2 收到了 work.queue的消息... :【hello, work, message_36】
消费者1 收到了 work.queue的消息... :【hello, work, message_37】
消费者2 收到了 work.queue的消息... :【hello, work, message_38】
消费者1 收到了 work.queue的消息... :【hello, work, message_39】
消费者2 收到了 work.queue的消息... :【hello, work, message_40】
消费者1 收到了 work.queue的消息... :【hello, work, message_41】
消费者2 收到了 work.queue的消息... :【hello, work, message_42】
消费者1 收到了 work.queue的消息... :【hello, work, message_43】
消费者2 收到了 work.queue的消息... :【hello, work, message_44】
消费者1 收到了 work.queue的消息... :【hello, work, message_45】
消费者2 收到了 work.queue的消息... :【hello, work, message_46】
消费者1 收到了 work.queue的消息... :【hello, work, message_47】
消费者2 收到了 work.queue的消息... :【hello, work, message_48】
消费者1 收到了 work.queue的消息... :【hello, work, message_49】
消费者2 收到了 work.queue的消息... :【hello, work, message_50】

由于此时两个消费者的消费速度一致(因为方法代码量相同),因此一人消费25条消息。 

  • 第四步:我们让这两个消费者的消费速度一个快,一个慢

运行结果:

消费者1 收到了 work.queue的消息... :【hello, work, message_1】
消费者2 收到了 work.queue的消息... :【hello, work, message_2】
消费者1 收到了 work.queue的消息... :【hello, work, message_3】
消费者1 收到了 work.queue的消息... :【hello, work, message_5】
消费者1 收到了 work.queue的消息... :【hello, work, message_7】
消费者2 收到了 work.queue的消息... :【hello, work, message_4】
消费者1 收到了 work.queue的消息... :【hello, work, message_9】
消费者1 收到了 work.queue的消息... :【hello, work, message_11】
消费者1 收到了 work.queue的消息... :【hello, work, message_13】
消费者1 收到了 work.queue的消息... :【hello, work, message_15】
消费者2 收到了 work.queue的消息... :【hello, work, message_6】
消费者1 收到了 work.queue的消息... :【hello, work, message_17】
消费者1 收到了 work.queue的消息... :【hello, work, message_19】
消费者1 收到了 work.queue的消息... :【hello, work, message_21】
消费者2 收到了 work.queue的消息... :【hello, work, message_8】
消费者1 收到了 work.queue的消息... :【hello, work, message_23】
消费者1 收到了 work.queue的消息... :【hello, work, message_25】
消费者1 收到了 work.queue的消息... :【hello, work, message_27】
消费者1 收到了 work.queue的消息... :【hello, work, message_29】
消费者2 收到了 work.queue的消息... :【hello, work, message_10】
消费者1 收到了 work.queue的消息... :【hello, work, message_31】
消费者1 收到了 work.queue的消息... :【hello, work, message_33】
消费者1 收到了 work.queue的消息... :【hello, work, message_35】
消费者2 收到了 work.queue的消息... :【hello, work, message_12】
消费者1 收到了 work.queue的消息... :【hello, work, message_37】
消费者1 收到了 work.queue的消息... :【hello, work, message_39】
消费者1 收到了 work.queue的消息... :【hello, work, message_41】
消费者2 收到了 work.queue的消息... :【hello, work, message_14】
消费者1 收到了 work.queue的消息... :【hello, work, message_43】
消费者1 收到了 work.queue的消息... :【hello, work, message_45】
消费者1 收到了 work.queue的消息... :【hello, work, message_47】
消费者1 收到了 work.queue的消息... :【hello, work, message_49】
消费者2 收到了 work.queue的消息... :【hello, work, message_16】
消费者2 收到了 work.queue的消息... :【hello, work, message_18】
消费者2 收到了 work.queue的消息... :【hello, work, message_20】
消费者2 收到了 work.queue的消息... :【hello, work, message_22】
消费者2 收到了 work.queue的消息... :【hello, work, message_24】
消费者2 收到了 work.queue的消息... :【hello, work, message_26】
消费者2 收到了 work.queue的消息... :【hello, work, message_28】
消费者2 收到了 work.queue的消息... :【hello, work, message_30】
消费者2 收到了 work.queue的消息... :【hello, work, message_32】
消费者2 收到了 work.queue的消息... :【hello, work, message_34】
消费者2 收到了 work.queue的消息... :【hello, work, message_36】
消费者2 收到了 work.queue的消息... :【hello, work, message_38】
消费者2 收到了 work.queue的消息... :【hello, work, message_40】
消费者2 收到了 work.queue的消息... :【hello, work, message_42】
消费者2 收到了 work.queue的消息... :【hello, work, message_44】
消费者2 收到了 work.queue的消息... :【hello, work, message_46】
消费者2 收到了 work.queue的消息... :【hello, work, message_48】
消费者2 收到了 work.queue的消息... :【hello, work, message_50】

③观察上述现象:无论两个消费者的消费速度一致,还是不一致,最终二者消费的消息数量都是25条(平分,一人从队列取一半)。

3、为何会出现上述问题?

        rabbitMQ的队列,默认轮询给两个消费者分配消息,而不管消费者的消费速度。该问题的关键是消费者手里还能存储消息,即消费不完的可以存下来,慢慢消费。这就导致了两个消费者平分消息的现象。

        类比:一个大人,一个小孩,一起吃苹果。苹果摊老板不管这两个人吃苹果的速度,只是轮流给两个人发苹果,并且大人和小孩是可以存储还没消费完的苹果,最终导致一共50个苹果,一人发了25个。即:小孩虽然吃得慢,但是兜里能揣啊,于是堆积在手里,一点一点吃。最终小孩还是能分到一半的苹果。

       

4、如何解决上述问题?

        解决方案:消费者消息推送限制

        说白了就是,你吃苹果吃得慢是吧,那我不让你存苹果了,而是让你吃完手里的一个,再拿一个。

         根据上述配置,限制了消费者手里只能留一个消息,即:不让消费者再堆积还没消费的消息了。

        类比:此时苹果摊老板,仍然是轮流给两人发苹果,只不过现在多了一条规矩:手里苹果还没吃完的人,就不给他发苹果了,吃完手里那个苹果的人才能再拿一个苹果。这样就限制了小孩堆积苹果的现象。也就解决了上述问题。

5、根据上述的思路,解决该问题

改进问题后,运行代码:

消费者1 收到了 work.queue的消息... :【hello, work, message_1】
消费者2 收到了 work.queue的消息... :【hello, work, message_2】
消费者1 收到了 work.queue的消息... :【hello, work, message_3】
消费者1 收到了 work.queue的消息... :【hello, work, message_4】
消费者1 收到了 work.queue的消息... :【hello, work, message_5】
消费者1 收到了 work.queue的消息... :【hello, work, message_6】
消费者1 收到了 work.queue的消息... :【hello, work, message_7】
消费者1 收到了 work.queue的消息... :【hello, work, message_8】
消费者1 收到了 work.queue的消息... :【hello, work, message_9】
消费者2 收到了 work.queue的消息... :【hello, work, message_10】
消费者1 收到了 work.queue的消息... :【hello, work, message_11】
消费者1 收到了 work.queue的消息... :【hello, work, message_12】
消费者1 收到了 work.queue的消息... :【hello, work, message_13】
消费者1 收到了 work.queue的消息... :【hello, work, message_14】
消费者1 收到了 work.queue的消息... :【hello, work, message_15】
消费者1 收到了 work.queue的消息... :【hello, work, message_16】
消费者1 收到了 work.queue的消息... :【hello, work, message_17】
消费者2 收到了 work.queue的消息... :【hello, work, message_18】
消费者1 收到了 work.queue的消息... :【hello, work, message_19】
消费者1 收到了 work.queue的消息... :【hello, work, message_20】
消费者1 收到了 work.queue的消息... :【hello, work, message_21】
消费者1 收到了 work.queue的消息... :【hello, work, message_22】
消费者1 收到了 work.queue的消息... :【hello, work, message_23】
消费者1 收到了 work.queue的消息... :【hello, work, message_24】
消费者1 收到了 work.queue的消息... :【hello, work, message_25】
消费者2 收到了 work.queue的消息... :【hello, work, message_26】
消费者1 收到了 work.queue的消息... :【hello, work, message_27】
消费者1 收到了 work.queue的消息... :【hello, work, message_28】
消费者1 收到了 work.queue的消息... :【hello, work, message_29】
消费者1 收到了 work.queue的消息... :【hello, work, message_30】
消费者1 收到了 work.queue的消息... :【hello, work, message_31】
消费者1 收到了 work.queue的消息... :【hello, work, message_32】
消费者1 收到了 work.queue的消息... :【hello, work, message_33】
消费者2 收到了 work.queue的消息... :【hello, work, message_34】
消费者1 收到了 work.queue的消息... :【hello, work, message_35】
消费者1 收到了 work.queue的消息... :【hello, work, message_36】
消费者1 收到了 work.queue的消息... :【hello, work, message_37】
消费者1 收到了 work.queue的消息... :【hello, work, message_38】
消费者1 收到了 work.queue的消息... :【hello, work, message_39】
消费者1 收到了 work.queue的消息... :【hello, work, message_40】
消费者1 收到了 work.queue的消息... :【hello, work, message_41】
消费者2 收到了 work.queue的消息... :【hello, work, message_42】
消费者1 收到了 work.queue的消息... :【hello, work, message_43】
消费者1 收到了 work.queue的消息... :【hello, work, message_44】
消费者1 收到了 work.queue的消息... :【hello, work, message_45】
消费者1 收到了 work.queue的消息... :【hello, work, message_46】
消费者1 收到了 work.queue的消息... :【hello, work, message_47】
消费者1 收到了 work.queue的消息... :【hello, work, message_48】
消费者1 收到了 work.queue的消息... :【hello, work, message_49】
消费者2 收到了 work.queue的消息... :【hello, work, message_50】

可见此时显然不是平分消息,而是能者多劳。

消费者1消费速度快,因此消费了43条消息;

消费者2消费速度慢,因此消费了7条消息。

以上就解决了 忽略消费速度而无脑平分消息的问题。

二、总结

1、知识总结

2、面试题:如何避免消息堆积问题?

①给队列上绑定多个消费者(work模型),从而提高消费速度

②优化代码,使代码执行速度变快,消费速度也就变快了

③rabbitMQ的默认规则:队列中的同一条消息,只能被一个消费者消费。即:不会出现两个消费者消费同一条消息的现象,从而提高消费速度。

④通过设置prefetch,来控制消费者手里最多有1条消息,不允许堆积消息,实现能者多劳。(最重要的一点)

以上就是work模型的全部详细内容,想了解更多的RabbitMQ知识,请关注本博主~~

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

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

相关文章

SpringMVC——简介及入门

SpringMVC简介 看到SpringMVC这个名字,我们会发现其中包含Spring,那么SpringMVC和Spring之间有怎样的关系呢? SpringMVC隶属于Spring,是Spring技术中的一部分。 那么SpringMVC是用来做什么的呢? 回想web阶段&#x…

鸿蒙开发-文件与分享

文件分类 按所有者: 应用文件:所有者为应用,包括应用安装文件、应用资源文件、应用缓存文件等。 用户文件:所有者是登录到该终端设备的用户,包括用户私有的图片、视频、音频、文档等。 系统文件:与应用和…

内存级文件原理——Linux

目录 进程与文件 Linux下的文件系统 文件操作,及文件流 C语言函数 文件流 文件描述符 系统调用操作 系统调用参数 重定向与文件描述符 输出重定向 输入重定向 文件内容属性 Linux下一切皆文件 进程与文件 当我们对文件进行操作时,文件必…

KubeSphere 最佳实战:K8s 构建高可用、高性能 Redis 集群实战指南

首发:运维有术。 本指南将逐步引导您完成以下关键任务: 安装 Redis:使用 StatefulSet 部署 Redis。自动或手动配置 Redis 集群:使用命令行工具初始化 Redis 集群。Redis 性能测试:使用 Redis 自带的 Benchmark 工具进…

apr共享内存

下载: Download - The Apache Portable Runtime Project 编译: 使用cmake-gui生成库: apr-1.lib aprapp-1.lib libapr-1.lib libaprapp-1.lib libapr-1.dll 在Developer PowerShell for VS 2019中: 执行nmake -f Makefile.win来…

Javaweb前端HTML css 整体布局

最后一个是线条颜色 盒子,整体还是300,400

5.STM32之通信接口《精讲》之USART通信---实验串口接收程序

根据上节,我们一已经完成了串口发送程序的代码,并且深入的解析探索了串口的原理,接下来,Whappy小编将带领大家进入串口接收程序的探索与实验,并将结合上一节串口发送一起来完成串口的发送和接收实验。 上来两张图 上图…

借助算力云跑模型

算力平台:FunHPC | 算力简单易用 AI乐趣丛生 该文章只讲述了最基本的使用步骤(因为我也不熟练)。 【注】:进入平台,注册登录账号后,才能租用。学生认证+实名认证会有免费的算力资源&#xff0…

SpringMVC 执行流程详解

目录 前言1. SpringMVC 的核心组件概述1.1 DispatcherServlet1.2 HandlerMapping1.3 HandlerAdapter1.4 拦截器(HandlerInterceptor)1.5 ViewResolver 2. SpringMVC 的执行流程详解2.1 接收请求并分发2.2 获取 HandlerExecutionChain2.3 获取 HandlerAda…

安卓应用安装过程学习

声明:此文章来自http://shuwoom.com/?p60的学习记录 启动式安装 public static final IPackageManager main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {PackageManagerService m new PackageManagerService(context, inst…

如何通过OpenSSL来创建自签名的CA证书?

通过创建自签名CA证书可以让我们在没有商业支持的情况下学习与研究PKI(公钥基础设施)和SSL/TLS技术,本文将详细介绍如何通过OpenSSL来创建自签名的CA证书。 1. 初衷:为什么需要创建自签名CA证书? 除了开篇引言中提到的…

mac安装Pytest、Allure、brew

安装环境 安装pytest 命令 pip3 install pytest 安装allure 命令:brew install allure 好吧 那我们在安装allure之前 我们先安装brew 安装brew 去了官网复制了命令 还是无法下载 如果你们也和我一样可以用这个方法哦 使用国内的代码仓库来执行brew的安装脚本…

Python中“暂停”(time.sleep?input?)

input函数最是经典,在多种实现中简单粗暴单纯而经济。 (笔记模板由python脚本于2024年11月22日 10:58:38创建,本篇笔记适合比较熟悉python的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大…

刷题——【模板】二维前缀和

前缀和 题目题目链接题解方法一方法二 题目 描述 给你一个 n 行 m 列的矩阵 A ,下标从1开始。 接下来有 q 次查询,每次查询输入 4 个参数 x1 , y1 , x2 , y2 请输出以 (x1, y1) 为左上角 , (x2,y2) 为右下角的子矩阵的和, 输入描述&#x…

10 - Clickhouse集群部署以及副本和分片

目 一、副本 1、简介 2、副本写入流程 3、副本配置步骤 3.1、启动zookeeper集群 3.2、在 hallo100 的/etc/clickhouse-server/config.d 目录下创建一个名为metrika.xml 的配置文件,内容如下: 3.3、在 hallo100 的/etc/clickhouse-server/config.xml 中增加如…

Ubuntu24.04LTS设置root用户可远程登录

Ubuntu24.04LTS设置root用户可远程登录 文章目录 Ubuntu24.04LTS设置root用户可远程登录1. 设置root密码2. 设置root用户可远程登录1. 查看ssh服务是否安装2. 安装ssh服务3. 再次查看ssh服务是否安装4. 配置ssh文件5. 重启ssh服务6. root远程登录 1. 设置root密码 Ubuntu安装后…

DMA理论篇

DMA理论篇 简介 传统的数据传输都是需要CPU来实现,从一个地方拷贝到另一个地方;而DMA(Direct Memory Access)则不完全依赖CPU,DMA更新芯片SOC的一个控制器,他可以控制数据从内存中传输到另一个地方(外设、soc其它模块)&#xff…

理解原子变量之三:原子性与memory_order_relaxed

目录 CPU与内存的关系 原子性 典型使用场景 在本系列的第一篇文章理解原子变量之一:从互斥锁到原子变量,最粗浅的认识_原子互斥-CSDN博客,我通过几个实例从感性认识的角度介绍了原子性。本文在第一篇文章的基础上,从理性认识的…

医院信息化与智能化系统(22)

医院信息化与智能化系统(22) 这里只描述对应过程,和可能遇到的问题及解决办法以及对应的参考链接,并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图,可以试试PlantUML,告诉GPT你的文件结构,让他给你对应…

青少年编程等级考试C++一级,硬币反转问题

代码 #include<iostream>using namespace std;bool a[300];int main(){ int n,m; cin >> n >> m; for(int i 1;i < m;i) { for (int j 1;j < n;j) { if( j % i 0) { a[j] !a[j];…