RabbitMQ(三)Work Queues 工作队列

Prometheus之rabbitmq监控指标详解 rabbitmq_messages_deliver_no_ack_rate指标可以帮助您了解未确认消息的数量和速率,并确定是否需要更改客户端消费者的配置或调整队列和交换机的配置以改善系统性能。与"rabbitmq_queue_messages_ready"指标不同的是,它不是单个队列的指标,而是RabbitMQ中所有队列中未被消费的消息数量的总和。队列的状态指标,其中包含了一些关于队列的元数据信息,例如队列的名称、虚拟主机名称、运行模式(磁盘或内存)、队列的持久性设置、队列中消息的数量等。 阅读详情

1.概述

https://www.rabbitmq.com/tutorials/tutorial-two-java.html

工作队列(又名:任务队列)的主要思想是避免立即执行资源密集型任务,而不得不等待它完成。相反,我们安排任务在以后完成。我们将任务封装 为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当您运行许多工作人员时,任务将在他们之间共享。

这个概念在Web应用程序中特别有用,因为在Web应用程序中,不可能在较短的HTTP请求窗口内处理复杂的任务。

2.代码示例

2.1 发送者

/**
 * 消息发送者
 */
public class Sender {
    private  final static String QUEUE = "testWork";//队列名称

    public static void main(String[] args) throws Exception {
        //1.获取连接
        Connection connection = ConnectionUtil.getConnection();
        //2.创建通道
        Channel channel = connection.createChannel();
        //3.声名队列
        //参数1:队列的名称
        //参数2:是否持久化队列,我们的队列模式是在内存中的,如果RabbitMQ重启会丢失,如果设置为true,则会保存在erlang自带的数据库中,重启后恢复
        //参数3:是否排外,有两个作用,第一个当我们的连接关闭后是否自动删除队列;第二,是否私有当前队列,如果私有,其它通道不可访问
        //参数4:是否自动删除
        //参数5:一些其它参数
        channel.queueDeclare(QUEUE,false,false,false,null);
        //4.发送消息
        for (int i = 0; i < 100; i++) {
            String msg = "这是发送的消息"+i;
            channel.basicPublish("",QUEUE,null,msg.getBytes());
        }
        //5.关闭连接
        channel.close();
        connection.close();
    }
}

2.2 消费者1号

import com.rabbitmq.client.*;
import com.shm.demo.util.ConnectionUtil;

import java.io.IOException;

/**
 * 消息消费者
 */
public class Recv1 {
    private  final static String QUEUE = "testWork";//队列名称

    public static void main(String[] args) throws Exception {
        //1.获取连接
        Connection connection = ConnectionUtil.getConnection();
        //2.创建通道
        Channel channel = connection.createChannel();
        //3.声名队列
        //参数1:队列的名称
        //参数2:是否持久化队列,我们的队列模式是在内存中的,如果RabbitMQ重启会丢失,如果设置为true,则会保存在erlang自带的数据库中,重启后恢复
        //参数3:是否排外,有两个作用,第一个当我们的连接关闭后是否自动删除队列;第二,是否私有当前队列,如果私有,其它通道不可访问
        //参数4:是否自动删除
        //参数5:一些其它参数
        channel.queueDeclare(QUEUE,false,false,false,null);
        //4.通知服务器,在消费确认前,不接收新发送的消息
        channel.basicQos(1);
        //5.定义消费者
        DefaultConsumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
               //打印收到的消息
                System.out.println("消费者1收到内容:"+new String(body));
                try {
                    Thread.sleep(10); //模拟耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //7.消费者消息确认:参数2,false 为手动确认收到消息。
                //这里可以在异常捕获的时候,将它设置为true
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        //6.注册消费者,参数2,false代表我们收到消息后需要手动告诉服务器
        channel.basicConsume(QUEUE,false,consumer);

    }
}

2.3 消费者2号

import com.rabbitmq.client.*;
import com.shm.demo.util.ConnectionUtil;

import java.io.IOException;

/**
 * 消息消费者
 */
public class Recv2 {
    private  final static String QUEUE = "testWork";//队列名称

    public static void main(String[] args) throws Exception {
        //1.获取连接
        Connection connection = ConnectionUtil.getConnection();
        //2.创建通道
        Channel channel = connection.createChannel();
        //3.声名队列
        //参数1:队列的名称
        //参数2:是否持久化队列,我们的队列模式是在内存中的,如果RabbitMQ重启会丢失,如果设置为true,则会保存在erlang自带的数据库中,重启后恢复
        //参数3:是否排外,有两个作用,第一个当我们的连接关闭后是否自动删除队列;第二,是否私有当前队列,如果私有,其它通道不可访问
        //参数4:是否自动删除
        //参数5:一些其它参数
        channel.queueDeclare(QUEUE,false,false,false,null);
        //4.通知服务器,在消费确认前,不接收新发送的消息
        channel.basicQos(1);
        //5.定义消费者
        DefaultConsumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
               //打印收到的消息
                System.out.println("消费者2收到内容:"+new String(body));
                try {
                    Thread.sleep(200); //模拟耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //7.消费者消息确认:参数2,false 为手动确认收到消息。
                //这里可以在异常捕获的时候,将它设置为true
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        //6.注册消费者,参数2,false代表我们收到消息后需要手动告诉服务器
        channel.basicConsume(QUEUE,false,consumer);
    }
}

默认情况下,RabbitMQ将按顺序将每个消息发送给下一个使用者。平均而言,每个消费者都会收到相同数量的消息。这种分发消息的方式称为循环。

3.消息确认

channel.basicAck(envelope.getDeliveryTag(),false);

执行任务可能需要几秒钟。您可能想知道,如果其中一个使用者开始一项漫长的任务并仅部分完成而死掉,会发生什么情况。使用我们当前的代码,RabbitMQ一旦向消费者发送了一条消息,便立即将其标记为删除。在这种情况下,如果您杀死一个工人,我们将丢失正在处理的消息。我们还将丢失所有发送给该特定工作人员但尚未处理的消息。

但是我们不想丢失任何任务。如果一个工人死亡,我们希望将任务交付给另一个工人。

为了确保消息永不丢失,RabbitMQ支持 消息确认。消费者发送回一个确认(acknowledgement),以告知RabbitMQ已经接收,处理了特定的消息,并且RabbitMQ可以自由删除它。

如果使用者在不发送确认的情况下死亡(其通道已关闭,连接已关闭或TCP连接丢失),RabbitMQ将了解消息未完全处理,并将重新排队。如果同时有其他消费者在线,它将很快将其重新分发给另一位消费者。这样,即使工人偶尔死亡,您也可以确保不会丢失任何消息。

没有任何消息超时;消费者死亡时,RabbitMQ将重新传递消息。即使处理一条消息花费非常非常长的时间也没关系。

默认情况下,手动消息确认处于打开状态。在前面的示例中,我们通过autoAck = true标志显式关闭了它们。一旦我们完成了一项任务,就该将该标志设置为false并从工作程序发送适当的确认的时候了。

被遗忘的确认
错过basicAck是一个常见的错误。这是一个简单的错误,但是后果很严重。当您的客户端退出时,消息将被重新发送(看起来像是随机重新发送),但是RabbitMQ将消耗越来越多的内存,因为它将无法释放任何未确认的消息。为了调试这种错误,您可以使用rabbitmqctl 打印messages_unacknowledged字段:

sudo rabbitmqctl list_queues名称messages_ready messages_unacknowledged

在Windows上,删除sudo:

rabbitmqctl.bat list_queues名称messages_ready messages_unacknowledged

4.消息持久性

boolean durable = true;
channel.queueDeclare(QUEUE, durable, false, false, null);

如果RabbitMQ服务器停止,我们的任务仍然会丢失。
RabbitMQ退出或崩溃时,它将忘记队列和消息,除非您告知不要这样做。要确保消息不会丢失,需要做两件事:我们需要将队列和消息都标记为持久性。
首先,我们需要确保该队列将在RabbitMQ节点重启后继续存在。为此,我们需要将其声明为持久的:

关于消息持久性的说明
将消息标记为持久性并不能完全保证不会丢失消息。尽管它告诉RabbitMQ将消息保存到磁盘,但是RabbitMQ接受消息但尚未将其保存仍然有很短的时间。另外,RabbitMQ不会对每条消息都执行fsync(2)-它可能只是保存到缓存中,而没有真正写入磁盘。持久性保证并不强,但是对于我们的简单任务队列而言,这已经绰绰有余了。如果您需要更强有力的保证,则可以使用 发布者确认。

5.公平派遣

int prefetchCount = 1 ;
channel.basicQos(prefetchCount);

您可能已经注意到,调度仍然无法完全按照我们的要求进行。例如,在有两名工人的情况下,当所有奇怪的消息都很重,甚至消息都很轻时,一位工人将一直忙碌而另一位工人将几乎不做任何工作。好吧,RabbitMQ对此一无所知,并且仍将平均分配消息。
发生这种情况是因为RabbitMQ在消息进入队列时才调度消息。它不会查看消费者的未确认消息数。它只是盲目地将每第n条消息发送给第n个使用者。


为了克服这一点,我们可以将basicQos方法与 prefetchCount = 1设置一起使用。这告诉RabbitMQ一次不要给工人一个以上的消息。换句话说,在处理并确认上一条消息之前,不要将新消息发送给工作人员。而是将其分派给尚不繁忙的下一个工作人员。

 

(四)RabbitMQ消息队列-服务详细配置与日常监控管理 RabbitMQ服务管理、RabbitMQ配置文件rabbitmq.config,RabbitMQ日志,RabbitMQWEB管理插件 阅读详情

相关推荐

工作队列(Work Queues)

工作队列: 工作队列(又称任务队列,Work Queues)的主要思想是避免立即执行资源密集型任务,而不得不等待它完成。相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时,这些工作线程将一起处理这些任务。 轮训分发消息: 在这个案例中我们会启动两个工作线程,一个消息发送线程,我们来看看他们两个工作线程是如何工作的 抽取工具类: ...

来杯奶茶 1933

消息队列之RabbitMQ

目录 了解RabbitMQ消息队列 消息队列的应用 RabbitMQ安装 RabbitMQ相关命令 python客户端使用RabbitMQ 消息持久化 了解RabbitMQ消息队列 RabbitMQ是一个消息代理,它接收和转发消息,可以理解为是生活的邮局。 你可以将邮件放在邮箱里,你可以确定有邮递员会发送邮件给收件人。 概括: RabbitMQ是接收,存储,转发...

厚积而后薄发 804

RabbitMQ练习(Work Queues)

在本练习中,将创建一个工作队列(Work Queue),它将被用来在多个工作者(Worker)之间分配需要较长时间来完成的任务( time-consuming tasks)。工作队列(也称为任务队列)避免立即执行复杂任务:复杂任务往往是需要花费系统更多时间和更多资源进行处理的任务。工作队列的设计初衷是减少对即时资源的需求。在某些情况下,如果直接执行某些任务,可能会消耗大量计算资源,导致系统响应变慢或无法处理其他请求。延迟执行任务。

zkyqss的博客 1213

RabbitMQ

RabbitMQMQ基本概念MQ简介MQ的优势和劣势使用MQ要满足的条件RabbitMQRabbitMQ 简介rabbitmq六种工作模式RabbitMQ 的工作模式总结 MQ基本概念 MQ简介 MQ全称 Message Queue(消息队列),是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。 小结 MQ,消息队列,存储消息的中间件。 分布式系统通信两种方式:直接远程调用和借助第三方 完成-间接通信。 发送方称为生产者,接收方称为消费者。 MQ的优势和劣势 MQ 的优势 应用解耦:系

保持热爱,持续学习 1742

Spring boot 整合RabbitMQ(二):工作队列(Work queues)

现在,我们将发送一些字符串,把这些字符串当作复杂的任务。我们并没有一个真实的复杂任务,类似于图片大小被调整或 pdf 文件被渲染,所以我们通过 sleep () 方法来模拟这种情况。我们在字符串中加上点号(.)来表示任务的复杂程度,一个点(.)将会耗时 1 秒钟。比如 “Hello…” 就会耗时 3 秒钟。 如果您尚未设置项目,请参阅第一个教程中的设置。我们将遵循与第一个教程相同的模式:创建一个包...

weixin_45821812的博客 755

利用Matlab绘制非线性系统相图:从理论到实践

本文详细介绍了如何利用Matlab进行非线性系统的相图绘制与相平面分析。从理论基础的状态空间转换出发,通过无阻尼线性谐振子和范德波尔振荡器等实例,手把手演示了使用ode45求解器绘制相图、分析平衡点与极限环的完整流程,并分享了方向场绘制、参数分岔探索及常见错误解决方案等高级技巧,为动力学系统分析与控制设计提供了直观强大的可视化工具。

yhn456789的博客 905

消息队列:Rabbit MQ详解一篇搞定

存储消息的队列。消息:比如字符串,对象,二进制数据,json等等。队列:先进先出的数据结构。耗时的场景(比如支付结果查询)异步化的场景(比如远程控制)应用解耦的场景消息队列的好处异步处理削峰填谷应用解耦要给系统引入额外的中间件,维护成本,资源成本,学习成本。消息队列:就需要考虑,消息丢失,消费消息,数据的一致性。中间件消息队列也是中间件的一种,我们可以注意到,它是作为生产和消费的中间人,进行传递消息,实现解耦。

前期后期 8526

eMMC FFU固件更新实战:从协议解析到设备修复

本文详细解析eMMC FFU固件更新技术,从协议原理到实战操作,涵盖EXT_CSD寄存器操作、命令流状态机解析及专业工具使用指南。通过真实维修案例,展示如何利用FFU机制修复设备故障,并提供高级优化技巧与安全注意事项,是硬件工程师和维修技术人员的实用参考。

weixin_29191761的博客 378

【RabbitMQ三】——RabbitMQ工作队列模式(Work Queues)

学习一门知识需要亲自动手去验证去证明这种方式是可行了,这样对于这个知识点才算是理解的更深。按照这样做一定行,而不是应该可以,大概可以吧。

理想主义的花最终会盛开在浪漫主义的土壤里,我的热情永远不会熄灭在现实的平凡之中,我们终将上岸,阳光万里。 1341

用KalmanNet搞定非线性状态估计:当卡尔曼滤波遇上神经网络

本文深入探讨了KalmanNet如何将神经网络与卡尔曼滤波结合,以解决非线性状态估计中的模型失配和噪声不确定性问题。通过保留经典滤波框架并用RNN学习卡尔曼增益,该方法在无人机导航、机器人定位等场景中实现了模型驱动与数据驱动的优势互补,提升了估计的鲁棒性和灵活性。

mango的博客 309

线上专利申请(超详细)| 签名确认

在【法人登录】页面点击【证书登录】按钮,弹出证书登录提示框,点击【确 认】按钮,进入到输入证书密码页面,点击【取消】按钮,取消本次操作。企业在提交申请时,需要增加签名,如使用企业账户点击提交,会弹出“法人、代理机构不能签名,请使用经办人签名”,这个时候就需要换个账号了。在需要签名时,将专利官网的登录方式点击法人登录,选择扫码登录,使用移动端经办人账户的扫一扫功能扫描登录。登录完成后,再点击签名,使用移动端扫一扫功能,扫描签名,输入证书号,确认签名,并提交。最后,祝大家的申请都成功!

weixin_62112323的博客 9109

RabbitMQ(三) Work queues工作队列

一个生产者对应多个消费者 为什么会出现工作队列? Simple队列是一一对应的,而且我们实际开发,生产者发送消息是毫不费力的,而且一般消费者是跟业务相结合的。消费者接收到消息之后就需要处理,可能需要花费时间,这时候队列就会积压很多消息。 默认采用轮询 生产者: package com.dada.work; import com.dada.util.ConnectionUtil; impor...

恶心的小达达 350

FFmpeg 开发(14):Android FFmpeg + MediaCodec 实现视频硬解码

MediaCodec 是 Android 提供的用于对音视频进行编解码的类,它通过访问底层的 codec 来实现编解码的功能,是 Android media 基础框架的一部分,通常和 MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface和AudioTrack 一起使用。

字节流动 3万+

RabbitMQ入门(三)之Work Queues 工作队列

工作队列 在第一个教程中,我们编写了一个程序来发送和接收来自一个指定队列的消息。在这一篇,我们将创建一个工作队列,将信息发送到多个消费者。这中分配方式主要场景是消费者需要根据消息中的内容进行业务逻辑处理,这种消息可以看成是一个任务指令,处理起来比较耗时,通过多个消费者来处理这些消息,来提高数据的吞吐能力。 工作队列(即任务队列)的主要思想是不用一直等待资源密集型的任务处理完成,这就像一个...

程序人生 455

Python 爬虫实战:全国高校录取分数线数据爬取与院校对比分析

本文介绍了一个基于Python的高考志愿填报辅助系统,通过爬取掌上高考平台的全国高校录取分数线数据,构建本地数据库并实现智能分析。系统主要功能包括:1)使用requests+BeautifulSoup爬取院校基本信息和历年分省分科类录取线;2)通过SQLite实现数据持久化与增量更新;3)利用pyecharts生成分数线趋势图、院校对比雷达图等可视化图表;4)提供"冲稳保"三档智能选校推荐。技术栈涵盖网络爬虫、数据清洗、数据库管理和可视化分析,可为考生提供数据驱动的志愿填报决策支持。项目采用模块化设计,包含

u014481728的博客 238

基于Jeecgboot3.9.0的vue3版本前后端分离的flowable流程管理平台

基于Jeecgboot3.9.0的vue3版本前后端分离的flowable流程管理平台

宁波阿成的博客 900

RabbitMQ(三) - 工作队列(Work Queues)

工作队列(又名:任务队列)背后的主要思想是避免立即做资源密集型的任务并且要等到它完成。相反,我们调度这个任务在以后完成。我们封装一个消息任务并把它发送给队列。一个工作进程在后台运行:取出任务并最终执行这个任务。

番薯IT的专栏 444

大数据在电力行业的应用案例解析 -【电力技术】(十)电力数字化运营与大数据精准服务体系建设

电力数字化运营,是大数据在电力行业从技术场景走向业务价值的最终落点。它以数据为纽带,将用户、设备、服务、收益、风险全部纳入统一闭环,实现从 “管好电” 向 “运营好能源资产” 升级。在新型电力系统与市场化改革双重驱动下,谁能用好数据、建好闭环、做好运营,谁就能在服务、成本、效益、安全上建立长期优势。

getusushu的博客 69

RabbitMQ消息中间件(三):工作模式之工作队列(Work queues)

Work Queues: 与入门程序的简单模式相比,多了一个或一些消费端,多个消费端共同消费同一个队列中的消息。 应用场景: 对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度。 ...

HaleyTiger的博客 464

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

RabbitMQ Work Queues (工作队列模式) 使用案例

工作队列模式

明志の博客 5788

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

RabbitMQ教程:工作队列(Work Queues)(二)

在上一篇教程中,我们学习了如何使用RabbitMQ发送和接收消息。今天,我们将探索工作队列(Work Queues),这是一种在多个工作进程(workers)之间分配耗时任务的机制。工作队列也被称为任务队列(Task Queues),它的核心思想是避免立即执行资源密集型任务,而是将任务安排到以后执行。通过这种方式,我们可以将任务封装成消息并发送到队列中,然后由后台运行的工作进程来处理这些任务。

qq_40600379的博客 1485

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

RabbitMQ通讯方式第二讲:Work Queues

1.1官网中的图片:通过官网里的图片,我们可以看到Word Queues 与Hello World 的区别,这里的消费者增加,但是时多个消费者消费单个队列,在这里我们依然要注意,这里面使用的是默认的交换机,并不是直接连接的队列。在消费者二的代码里面,线程休眠了1000ms 显然一的速度更快。RabbitMQ是AMQP协议的一个实现者,它是一个开源的消息队列系统,基于AMQP协议实现。注意这里面的交换机是默认的,与队列连接的方式式直接连接。更好的理解每次的连接都是需要交换机的,对于后续的学习是有帮助的。

hdk5855的博客 1282

RabbitMQ中的Work Queues模式

Work Queues 模式(也称为任务队列模式)是一种消息传递模式,用于在多个消费者之间分配任务。在这种模式下,生产者将任务(消息)发送到队列中,多个消费者从队列中获取任务并进行处理。每个任务只会被一个消费者处理,从而实现负载均衡。负载均衡:多个消费者可以并行处理任务,从而提高系统的处理能力。解耦:生产者和消费者之间通过队列进行通信,彼此之间不需要直接交互。异步处理:任务可以异步处理,生产者不需要等待任务完成即可继续执行其他操作。

weixin_39033358的博客 1506

详解SpringBoot整合RabbitMQ之工作队列模式

详解SpringBoot整合RabbitMQ之工作队列模式。

. 1万+

RabbitMQ Work Queues 消息确认

RabbitMQ Work Queues 简介 Hello Word中只是简单介绍,下面开始重点分析 例如:当我们有复杂需求,我们需要提升效率,毕竟只有一个消费者难免处理不过来,就如官网中所提到的一样——在这篇教程中,将创建一个工作队列(Work Queue),它会发送一些耗时的任务给多个工作者(Worker)。 工作队列(又称:任务队列——Task Queues)是为了避免等待一些占用大量资源、...

十年饮冰,难凉热血 2033
上一篇: RabbitMQ(二)简单队列 Hello World!
下一篇: RabbitMQ(四)Publish/Subscribe 发布/订阅
夜未眠shm
博客等级 码龄14年 15粉丝 101原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值