RabbitMQ(二):工作队列(Work queues)

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

开发版本为 Spring Boot 2.2.4.RELEASE 版本,开发工具为 Eclipse IDE for Enterprise Java Developers(Version: 2019-09 R (4.13.0)),Jave 版本为 1.8,RabbitMQ 3.8.2,Erlang 22.2。
参考资料
本文为 https://windmt.com/2018/04/12/rabbitmq-2-work-queues/ 的学习笔记。

前言

在前一篇文章中,我们实现了一个简单的发送、接收消息的程序。在本文中,我们将创建一个工作队列,用于在多个消费者之间分发耗时的任务。
在这里插入图片描述
工作队列(也称为:任务队列,Task Queues)主要是为了避免等待一些占用大量资源、时间的操作。当我们把任务(Task)当作消息发送到队列中,一个运行在后台的工作者(worker)进程就会取出任务然后处理。当你运行多个工作者(workers),任务就会在它们之间共享。

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

准备

在前一篇文章中,我们发送了一条包含 Hello World 的消息。现在我们将发送一些字符串来当作复杂任务。我们并没有一个真实的复杂任务,类似于图片大小被调整或 pdf 文件被渲染,所以我们通过 sleep () 方法来模拟这种情况。我们在字符串中加上点号(.)来表示任务的复杂程度,一个点(.)将会耗时 1 秒钟。比如 “Hello…” 就会耗时 3 秒钟。

代码实现

  1. 配置类
    与 tut1 类似,首先创建包 tut2 来存放本文的相关代码。
    新增配置类 Tut2Config:
package com.example.demo.tut2;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Profile({ "tut2", "work-queues" })
@Configuration
public class Tut2Config {
	@Bean
	public Queue hello() {
		return new Queue("work-queues");
	}

	@Profile("receiver")
	private static class ReceiverConfig {

		@Bean
		public Tut2Receiver receiver1() {
			return new Tut2Receiver(1);
		}

		@Bean
		public Tut2Receiver receiver2() {
			return new Tut2Receiver(2);
		}

	}

	@Profile("sender")
	@Bean
	public Tut2Sender sender() {
		return new Tut2Sender();
	}
}

其中,我们添加了两个配置文件:tut2 和 work-queues。我们利用 Spring 将队列公开为 bean,并在配置消费者时,定义两个 bean,对应了上图中的两个消费者 C1 和 C2。

  1. 生产者
    简单修改下生产者的代码,在消息 hello 后自动添加 . 。
package com.example.demo.tut2;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.concurrent.atomic.AtomicInteger;

public class Tut2Sender {
	@Autowired
	private RabbitTemplate template;

	@Autowired
	private Queue queue;
	
	AtomicInteger dots = new AtomicInteger(0);

	AtomicInteger count = new AtomicInteger(0);
	
	/**
	 * 用定时任务来模拟生产者定时发送消息
	 */
	@Scheduled(fixedDelay = 1000, initialDelay = 500)
	public void send() {
		StringBuilder builder = new StringBuilder("Hello");
		
		if (dots.getAndIncrement() == 3) {
			dots.set(1);
		}
		
		for (int i = 0; i < dots.get(); i++) {
			builder.append('.');
		}
		
		builder.append(count.incrementAndGet());
		
		String message = builder.toString();
		this.template.convertAndSend(queue.getName(), message);
		System.out.println(" [x] Sent '" + message + "'");
	}
}
  1. 消费者
    在 Tut2Receiver 中,我们通过 doWork() 方法模拟了一个耗时的虚假任务,每有一个 .,就多花 1 秒的操作。为 Tut2Receiver 添加了一个实例编号,用以显示是哪个实例消费了消息和处理的时长。
package com.example.demo.tut2;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.util.StopWatch;

@RabbitListener(queues = "work-queues")
public class Tut2Receiver {

	private int instance;

	public Tut2Receiver(int instance) {
		this.instance = instance;
	}

	@RabbitHandler
	public void receive(String in) throws InterruptedException {
		StopWatch watch = new StopWatch();
		watch.start();
		System.out.println("instance " + this.instance + " [x] Received '" + in + "'");
		doWork(in);
		watch.stop();
		System.out.println("instance " + this.instance + " [x] Done in " + watch.getTotalTimeSeconds() + "s");
	}

	private void doWork(String in) throws InterruptedException {
		for (char ch : in.toCharArray()) {
			if (ch == '.') {
				Thread.sleep(1000);
			}
		}
	}
}

运行

  1. 右键项目,依次执行 Run As -> Maven clean 和 Run As -> Maven install,生成 jar 包。
  2. 打开 cmd,切换到工程目录,如 D:\eclipse-workspace\rabbitmq-tutorial,分别执行以下语句:
#shell1 消费者
java -jar target/rabbitmq-tutorial-0.0.1-SNAPSHOT.jar --spring.profiles.active=tut2,receiver  --tutorial.client.duration=60000
#shell2 生产者
java -jar target/rabbitmq-tutorial-0.0.1-SNAPSHOT.jar --spring.profiles.active=tut2,sender  --tutorial.client.duration=60000
  1. 消费者的消息如下:
// Sender
Ready ... running for 10000ms
 [x] Sent 'Hello.1'
 [x] Sent 'Hello..2'
 [x] Sent 'Hello...3'
 [x] Sent 'Hello.4'
 [x] Sent 'Hello..5'
 [x] Sent 'Hello...6'
 [x] Sent 'Hello.7'
 [x] Sent 'Hello..8'
 [x] Sent 'Hello...9'

// Receiver
Ready ... running for 10000ms
instance 1 [x] Received 'Hello.1'
instance 2 [x] Received 'Hello..2'
instance 1 [x] Done in 1.005s
instance 1 [x] Received 'Hello...3'
instance 2 [x] Done in 2.007s
instance 2 [x] Received 'Hello.4'
instance 2 [x] Done in 1.005s
instance 1 [x] Done in 3.01s
instance 1 [x] Received 'Hello..5'
instance 2 [x] Received 'Hello...6'
instance 1 [x] Done in 2.006s
instance 1 [x] Received 'Hello.7'
instance 1 [x] Done in 1.002s
instance 1 [x] Received 'Hello...9'
instance 2 [x] Done in 3.01s
instance 2 [x] Received 'Hello..8'

可以看到 C1 和 C2 是依次接收到消息的。我认为 在 Spring 中,RabbitMQ 分发的消息逻辑应是循环调度:判断 C1 的未确认消息数是否小于 prefetchCount,若小于,则将消息分派给 C1,否则判断下一个消费者 C2 是否符合,依次循环往复,而 Spring 中,prefetchCount 的默认值为 250(于org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer 中 看到 DEFAULT_PREFETCH_COUNT 设置为了250)。

修改 prefetch

  1. 方法1
    可在 application.yml 中设置 spring.rabbitmq.listener.simple.prefetch=1,这会影响到本 Spring Boot 应用中所有使用默认 SimpleRabbitListenerContainerFactory 的消费者。
  2. 方法2
    为了只针对特定的消费者,如本文中,只针对 Tut2Receiver2,那么可以通过在 Tut2Config 配置类中添加以下 Bean:
@Bean
public RabbitListenerContainerFactory<SimpleMessageListenerContainer> prefetchOneRabbitListenerContainerFactory(ConnectionFactory rabbitConnectionFactory) {
	SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
	factory.setConnectionFactory(rabbitConnectionFactory);
	factory.setPrefetchCount(1);
	return factory;
}

并在 Tut2Receiver2 的RabbitListener 注解中指定 containerFactory:

@RabbitListener(queues = "work-queues", containerFactory = "prefetchOneRabbitListenerContainerFactory")

若将 prefetch 设置为 1,则将得到以下结果:

Ready ... running for 60000ms
instance 1 [x] Received 'Hello.1'
instance 2 [x] Received 'Hello..2'
instance 1 [x] Received 'Hello...3'
instance 2 [x] Received 'Hello.4'
instance 2 [x] Received 'Hello..5'
instance 1 [x] Received 'Hello...6'
instance 2 [x] Received 'Hello.7'
instance 2 [x] Received 'Hello..8'
instance 1 [x] Received 'Hello...9'
instance 2 [x] Received 'Hello.10'
instance 2 [x] Received 'Hello..11'
instance 1 [x] Received 'Hello...12'

此结果可通过以上循环调度的逻辑解释。

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

相关推荐

工作队列(Work Queues)

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

来杯奶茶 1933

RabbitMQ 的工作模式——Work Queues 工作队列模式

一、模式说明 Work Queues:与入门程序的简单模式相比,多了一个或一些消费端,多个消费端共同消费同一个队列中的消息。 应用场景:对于任务过重或任务较多情况,使用工作队列可以提高任务处理的速度。 二、代码 Producer_WorkQueues package com.itheima.producer; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.cli

dingd1234的博客 1192

深入解析AUTOSAR中IIC的MCAL实现与Vector配置实践

本文深入解析AUTOSAR架构中IIC总线的MCAL实现与Vector配置实践,探讨IIC在汽车电子中的特殊定位及Vector的折中方案。通过Channel与Sequence设计模式、Chain特性应用及DaVinci Configurator配置步骤,提供IIC驱动的优化与安全实现方法,助力开发者高效解决车载通信问题。

weixin_29172963的博客 407

RabbitMQ:工作队列模式

RabbitMQ:工作队列模式

Leon_Jinhai_Sun的博客 790

跟着Cell学单细胞转录组分析(五):单细胞转录组marker基因鉴定及细胞群注释

书接上回(跟着Cell学单细胞转录组分析(四):单细胞转录组测序UMAP降维聚类)。完成数据降维和细胞聚类后,最主要的环节和工作就是确定各个细胞群,明确是什么类型的细胞,正群的细胞定群很关键,涉及到整个研究,所以这一步宁愿多费时间,也不要出错。当然,这也不是一蹴而就的,需要反复的确认。 要确定各个群是什么细胞,首先需要了解细胞群的marker基因,因为不同类型的细胞突出 表达的基因也是不同的。这里使用FindAllMarkers鉴定各个细胞群的高表达基因。 DefaultAssay(scedata)

qq_42090739的博客 1万+

台达PLC DIAdesigner-AX 编程笔记

1、登陆台达思图软件网站,选择Download,登陆注册好的账号,下载DIAInstaller,下载后安装(安装目录不要修改);

weixin_45823621的博客 6675

springBoot集成rabbitmq 之工作模式(Work queues)

springBoot集成rabbitmq 之工作模式(Work queues)

weixin_45730866的博客 586

C51:PWM+舵机角度控制

PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如方波的占空比就是50%.脉冲宽度调制通过占空比编码模拟信号一个周期内,高电平占据时长的百分比如下图所示,最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制。

qq_73379310的博客 3388

【RabbitMQ】Basic Queue 简单队列模型与WorkQueue

SpringAMQP是基于RabbitMQ封装的一套模板,并且还利用SpringBoot对其实现了自动装配,使用起来非常方便。

少年你真的要止步于此嘛。 528

FPGA工程师面试试题集锦11~20

时钟抖动是指芯片的某一个给定点上时钟周期发生暂时性变化,也就是说时钟周期在不同的周期上可能加长或缩短。它是一个平均值为0的平均变量。

FPGA/MATLAB学习教程/源码/项目合作开发 678

微信小程序——01开发前的准备和开发工具

微信小程序——01开发前的准备和开发工具

总裁余(余登武)博客 1万+

SpringBoot的RabbitMQ消息队列: 三、第二模式"Work queues"

上一节的两个工程,一个负责发送,一个负责接收,也就是一一对于的关系。      只要消息发出了,接收者就处理;当接收效率较低时,就会出现接收者处理不过来,我们就可能会处理不过来,于是我们就可能多配置接受者。这个模式就是"Work queues",它的结构如下     多个接收者,它们会出现什么情况呢?是否像大锅饭,有的人撑死,有的人饿死。这个通过例子验证。 一、再建一个接收者工程 H

lxhjh的专栏 1万+

MSVS C# Matlab的混合编程系列2 - 构建一个复杂(含多个M文件)的动态库:

本节我们尝试将一个有很多函数和文件的Matlab算法文件集成到C#的项目里面。

山云的专栏 2068

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

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

qq_40600379的博客 1485

华为OD机试双机位C卷 - 高矮个子排队 (C++/Py/Java/Js/Go/C)

华为OD机试双机位C卷 高矮个子排队,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。华为OD机试 - 高矮个子排队。

qq_45776114的博客 2160

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

【RabbitMQ】基础二:工作队列模式(Work queues)

【RabbitMQ】二、工作队列模式(Work queues)1. 模式说明2. 示例代码2.1 生产者2.2 消费者2.3 测试3. 小结 1. 模式说明 Work Queues 与入门程序的 简单模式 相比,多了一个或一些消费端,多个消费端共同消费同一个队列中的消息。 应用场景:对于 任务过重或任务较多情况使用工作队列可以提高任务处理的速度。 在work模式中可以分为两种模式,一种是两个消费者平均消费队列中的消息,即使他们的消费能力是不一样的,这种似乎不太符合实际的情况。另一种是能者多劳模式,处理消息

来日浅谈的博客 600

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

rabbitmq(二)Work Queues(工作队列)

Round-robin dispatching(轮询分发)默认情况下,rabbitmq会将生产者的每个消息依次分发给各个消费者,比如有3个消费者(c1,c2,c3),生产者将8条消息(msg1,msg2…msg8)分发出去,那么消费者c1将得到消息msg1,msg4,msg7;消费者c2将得到msg2,msg5,msg8;消费者将得到msg3,msg6。这就是所谓的轮询分发。示例:Worker.ja

g110029017的专栏 2013

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

RabbitMQ学习(二) 工作队列(work queues)

RabbitMQ工作队列(work queues)        工作队列(又称任务队列)的主要思想是避免立即执行资源密集型任务,造成消息堆积。利用多个消费者同时消费队列中不同的消息,处理速度快的消费者多分配一些消息,相反,处理速度慢的消费者少分配一下消息。当您运行许多工作任务时,任务将在他们之间共享。所有的消费者将 (注意:不是消费同一条消息,而是在默认情况下将一些消息平均分配给不同的消费者消费,类似于nginx的负载均衡) 消费不同

困难总比办法多 331

RabbitMQ 6 种工作模式 - (二)Work queues 工作队列模式

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

一颗小松丸的博客 394

【c#】RabbitMQ学习文档(二)Work Queues(工作队列)

今天开始RabbitMQ教程的第二讲,废话不多说,直接进入话题。 (使用.NET 客户端 进行事例演示) 在第一个教程中,我们编写了一个从命名队列中发送和接收消息的程序。在本教程中,我们将创建一个工作队列,这个队列将用于在多个工人之间分配耗时的任务。 工作队列【又名:任务队列】背后主要的思想是避免立刻执行耗时的工作任务,并且一直要等到它结束为止。相反,我们规...

weixin_30455067的博客 72

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

工作队列模式

明志の博客 5788

RabbitMQ中的Work Queues模式

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

weixin_39033358的博客 1506

RabbitMQ Work Queues 消息确认

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

十年饮冰,难凉热血 2033

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

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

. 1万+

RabbitMQ学习(二):Work Queues

说明 通过翻译上篇博文,我们初步了解了RabbitMQ的使用方式,本篇博文将继续翻译官方的第二篇教程Work Queues, 通过本次翻译,我将简单记录梳理有关RabbitMQ的消息派发方式,消息确认机制,消息持久化等内容。 正文 任务队列 在第一篇教程中,我们写了从指定队列中发送和接收消息的程序。在本篇教程中我们将创建一个工作队列,它将被用于在多个消费者中分发耗时任务。 工作队列(又名:任务队...

wds的博客 940
上一篇: RabbitMQ(一):Hello World
下一篇: Spring Cloud: 服务容错保护 Hystrix
我很低调嘛
博客等级 码龄13年 2583粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值