RabbitMQ4:work模型

欢迎来到“雪碧聊技术”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){//消费者1System.out.println("消费者1 收到了 work.queue的消息... :【" + msg + "】");}@RabbitListener(queues = "work.queue")public void listenWorkQueue2(String msg){//消费者2System.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.mzph.cn/diannao/61792.shtml

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

相关文章

基于SpringBoot的数据结构系统设计与实现(源码+定制+开发)

博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…

100.【C语言】数据结构之二叉树的堆实现(顺序结构) 1

目录 1.顺序结构 2.示意图 ​编辑 从物理结构还原为逻辑结构的方法 3.父子节点编号的规律 4.顺序存储的前提条件 5.堆的简介 堆的定义 堆的两个重要性质 小根堆和大根堆 6.堆的插入 7.堆的实现及操作堆的函数 堆的结构体定义 堆初始化函数HeapInit 堆插入元素函…

Mac 环境变量配置基础教程

MacOS 下一般配置有多个 Shell,如 Bash、ZSH 等,不同的 Shell 其创建 Terminal 时使用的环境变量配置文件也不尽相同,但一般都会读取并执行脚本文件 /etc/profile 来加载系统级环境变量,而用户级别环境变量,一般都会在…

支持多种快充协议和支持多种功能的诱骗取电协议芯片

汇铭达XSP15是一款应用于手持电动工具、智能家居、显示器、音箱等充电方案的大功率快充协议芯片,支持最大功率100W给设备快速充电,大大缩短了充电时间。芯片支持通过UART串口发送电压/电流消息供其它芯片读取。支持自动识别连接的是电脑或是充电器。支持…

Three.js 相机控制器Controls

在 3D 场景中,摄像机的控制尤为重要,因为它决定了用户如何观察和与场景互动。Three.js 提供了多种相机控制器,最常用的有 OrbitControls、TrackballControls、FlyControls 和 FirstPersonControls。OrbitControls 适合用于查看和检查 3D 模型…

Glide源码学习

前言 开始 基本使用非常简单,链式调用把context对象传入,设置要加载的URL,设置要填充的ImageView控件,方法很简洁,每次都是传入的最核心的参数,底层加载的缓存逻辑,加载的引擎,加载…

CMake笔记:install(TARGETS target,...)无法安装的Debug/lib下

1. 问题描述 按如下CMake代码,无法将lib文件安装到Debug/lib或Release/lib目录下,始终安装在CMAKE_INSTALL_PREFIX/lib下。 install(TARGETS targetCONFIGURATIONS DebugLIBRARY DESTINATION Debug/lib) install(TARGETS targetCONFIGURATIONS Release…

docker安装使用Elasticsearch,解决启动后无法访问9200问题

1.docker安装、启动es docker pull elasticsearch:8.13.0docker images启动容器 docker run -d -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS"-Xms256m -Xmx256m" --name es01 8ebd258614f1-d 后台运行-p 9200:9200 -p 9300:9300 开放与主机映射端口-e ES_JAVA_OPTS…

java-排序算法汇总

排序算法: 冒泡排序(Bubble Sort) 选择排序(Selection Sort) 插入排序(Insertion Sort) 快速排序(Quick Sort) 归并排序(Merge Sort) 堆排序&…

【笔记】自动驾驶预测与决策规划_Part7_数据驱动的预测方法

文章目录 0. 前言1. 多模态传感器的编码方式1.1 栅格化表示1.2 向量化表示 Vectornet1.3 基于点云或者多模态输入的预测1.4 基于Transformer的方法 2. 网络输出的表达形式2.1 多模态轨迹回归2.2 轨迹分类2.3 轨迹回归轨迹分类2.4 目标点预测 3.场景级别的预测和决策3.1 论文&am…

Python操作neo4j库py2neo使用(一)

Python操作neo4j库py2neo使用(一) 安装(只用于测试) docker-compose .yml 文件 version: 3.8 services:neo4j:image: neo4j:5.6.0-enterprise #商业版镜像hostname: neo4jcontainer_name: neo4jports:- "7474:7474"-…

Tortoise ORM

官方文档:Tortoise ORM - Tortoise ORM v0.22.0 Documentation 简介 Tortoise ORM:异步,API和Django ORM 大多类似集成Pydantic;多用于asgi starlette / sanic / FastAPI...Sqlalchemy:支持异步,Flask / …

Pinia 实战教程:构建高效的 Vue 3 状态管理系统

前言 在前端开发中,状态管理已成为必不可少的一部分,Vue.js 生态系统中提供了多种状态管理解决方案。Pinia 是 Vue 3 推出的一种全新的状态管理库,旨在取代 Vuex,提供更简洁的 API、更优雅的 TypeScript 支持以及更高效的性能表现…

Android Framework AudioFlinge 面试题及参考答案

目录 请解释什么是 AudioFlinger? AudioFlinger 在 Android 系统中的位置是什么? AudioFlinger 的主要职责有哪些? AudioFlinger 如何管理音频流? 在 AudioFlinger 中,什么是音频会话? 请简述 AudioFlinger 的工作流程。 AudioFlinger 是如何与硬件交互的? 在 A…

【大数据学习 | Spark-Core】关于distinct算子

只有shuffle类的算子能够修改分区数量,这些算子不仅仅存在自己的功能,比如分组算子groupBy,它的功能是分组但是却可以修改分区。 而这里我们要讲的distinct算子也是一个shuffle类的算子。即可以修改分区。 scala> val arr Array(1,1,2,…

java基础概念36:正则表达式1

一、正则表达式的作用 作用一:校验字符串是否满足规则;作用二:在一段文本中查找满足要求的内容。——爬虫 二、正则表达式 2-1、字符类 示例: public static void main(String[] args) {System.out.println("a".matc…

Python 3 和 JSON 数据格式

Python 3 和 JSON 数据格式 Python 3 是一种广泛使用的编程语言,以其简洁明了的语法和强大的功能而闻名。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。Python 3 提供了内置的 json 模块,使得在 Python 程序…

oracle的静态注册和动态注册

oracle的静态注册和动态注册 静态注册: 静态注册 : 指将实例的相关信息手动告知 listener 侦 听 器 , 可以使用netmgr,netca,oem 以及直接 vi listener.ora 文件来实现静态注册,在动态注册不稳定时使用,特点是:稳定&…

html+js实现图片的放大缩小等比缩放翻转,自动播放切换,顺逆时针旋转

效果图&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>图片预览</title><sty…

Selenium+Java(19):使用IDEA的Selenium插件辅助超快速编写Pages

前言 或是惊叹于Selenium对于IDEA的支持已经达到了这样的地步,又或是由于这个好用的小工具的入口就在那里,它已经陪伴了我这么久,而我这么久的时间却都没有发现它。在突然发现这个功能的一瞬间,真的是喜悦感爆棚,于是赶快写下了这篇文章。希望可以帮助到其他同样在做UI自动…