RabbitMQ 06 工作队列模式
工作队列模式结构图:

这种模式非常适合多个工人等待任务到来的场景。任务有多个,一个一个丢进消息队列,工人也有很多个,就可以将这些任务分配个各个工人,让他们各自负责一些任务,并且做的快的工人还可以多完成一些(能者多劳)。
要实现这种模式,只需要创建多个监听器即可。
先监听再发消息
这里先介绍先监听再发送消息的情况。
定义配置类。
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.ExchangeBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* RabbitMQ配置类
*
* @author CodeSail
*/
@Configuration
public class RabbitMqConfig { /**
* 定义交换机,可以很多个
* @return 交换机对象
*/
@Bean("directExchange")
public Exchange exchange(){
return ExchangeBuilder.directExchange("amq.direct").build();
} /**
* 定义消息队列
* @return 消息队列对象
*/
@Bean("testQueue")
public Queue queue(){
return QueueBuilder
// 非持久化类型
.nonDurable("test_springboot")
.build();
} /**
* 定义绑定关系
* @return 绑定关系
*/
@Bean
public Binding binding(@Qualifier("directExchange") Exchange exchange,
@Qualifier("testQueue") Queue queue){
// 将定义的交换机和队列进行绑定
return BindingBuilder
// 绑定队列
.bind(queue)
// 到交换机
.to(exchange)
// 使用自定义的routingKey
.with("test_springboot_key")
// 不设置参数
.noargs();
}
}
创建两个监听器,监听同一队列。
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component; /**
* 工作队列监听器
*
* @author 廖航
*/
@Component
public class WorkListener { @RabbitListener(queues = "test_springboot")
public void receiver1(String message) {
System.out.println("1号监听器:" + message);
} @RabbitListener(queues = "test_springboot")
public void receiver2(String message) {
System.out.println("2号监听器:" + message);
} }
定义生产者。
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.TimeUnit; @SpringBootTest
class RabbitMqSpringBootTests { /**
* RabbitTemplate封装了大量的RabbitMQ操作,已经由Starter提供,因此直接注入使用即可
*/
@Autowired
private RabbitTemplate rabbitTemplate; /**
* 生产者
*/
@Test
void producer() throws InterruptedException { for (int i = 0; i < 10; i++) {
TimeUnit.SECONDS.sleep(1);
rabbitTemplate.convertAndSend("amq.direct", "test_springboot_key", "Hello World");
}
} }
启动生产者发送消息。

可以看到,当同一个队列有多个监听器时,默认采用轮询的方式消费消息。
先发消息再监听
前面介绍了先监听再发消息的情况,下面介绍先发消息再监听的情况。
向队列中发送10条消息。

启动服务消费消息。

可以看到,如果是一开始就存在消息,会被一个消费者一次性全部消费,这是因为没有对消费者的Prefetch count(预获取数量,一次性获取消息的最大数量)进行限制。
默认的Prefetch count为250。

也就是说如果希望消费者一次只拿一个消息,而不是将所有的消息全部都获取,需要设置Prefetch count。
要对这个数量进行配置,需要在配置类中定义一个自定义的ListenerContainerFactory,可以在这里设置消费者Channel的PrefetchCount的大小。
配置类中定义
ListenerContainerFactory。import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.ExchangeBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* RabbitMQ配置类
*
* @author CodeSail
*/
@Configuration
public class RabbitMqConfig { @Autowired
private CachingConnectionFactory connectionFactory; ... @Bean(name = "listenerContainer")
public SimpleRabbitListenerContainerFactory listenerContainer(){
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 将PrefetchCount设定为1表示一次只能取一个
factory.setPrefetchCount(1);
return factory;
}
}
监听器中指定。
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component; /**
* 工作队列监听器
*
* @author 廖航
*/
@Component
public class WorkListener { @RabbitListener(queues = "test_springboot", containerFactory = "listenerContainer")
public void receiver1(String message) {
System.out.println("1号监听器:" + message);
} @RabbitListener(queues = "test_springboot", containerFactory = "listenerContainer")
public void receiver2(String message) {
System.out.println("2号监听器:" + message);
} }
向队列中发送10条消息。

启动服务消费消息。

可以看到,两个监听器又实现了轮询消费消息。
Prefetch count设为了1。

至此,工作队列模式的两种情况就介绍完毕了。
- 环境
- JDK 17.0.6
- Maven 3.6.3
- SpringBoot 3.0.4
- spring-boot-starter-amqp 3.0.4
- 参考
RabbitMQ 06 工作队列模式的更多相关文章
- RabbitMQ六种队列模式-工作队列模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列 [本文]RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...
- 【RabbitMQ】工作模式介绍
一.前言 之前,笔者写过< CentOS 7.2 安装 RabbitMQ> 这篇文章,今天整理一下 RabbitMQ 相关的笔记便于以后复习. 二.模式介绍 在 RabbitMQ 官网上提 ...
- RabbitMQ六种队列模式-简单队列模式
前言 RabbitMQ六种队列模式-简单队列 [本文]RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...
- RabbitMQ六种队列模式-发布订阅模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅 [本文]RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...
- RabbitMQ六种队列模式-路由模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式 [本文]RabbitMQ六种队列模式-主 ...
- RabbitMQ六种队列模式-主题模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主题模式 [ ...
- java面试一日一题:rabbitMQ的工作模式
问题:请讲下rabbitMQ的工作模式 分析:该问题纯属概念题,需要掌握rabbtiMQ的基础知识,同时该题也是切入MQ的一个引子: 回答要点: 主要从以下几点去考虑, 1.rabbitMQ的基本概念 ...
- RabbitMQ之消息模式(下)
目的: RabbitMQ之消息模式(上):https://www.cnblogs.com/huangting/p/11994539.html 消费端限流 消息的ACK与重回队列 TTL消息 死信队列 ...
- 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_9.RabbitMQ研究-工作模式-发布订阅模式-消费者
消费者需要写两个消费者 定义邮件的类 复制以前的代码到邮件类里面进行修改 最上面 声明队列的名称和交换机的名称 监听修改为email 的队列的名称 手机短信接收端 复制一份email的接收端的代码 改 ...
- 【RabbitMQ】六种模式与SpringBoot整合
添加rabbitmq的依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...
随机推荐
- 带你领略下iOS中OC的“alloc”源代码,让你在工作中不在迷惑
前言 前面我们使用官方开源的objc源码进行了编译调试 objc4-818.2源码编译调试笔记 前言为什么会想要调试源码? 苹果开源了部分源码, 但相似内容太多, 基本找不到代码见的对应关系, 如果能 ...
- sql组合索引怎样使用?怎样命中?
一.联合索引的使用 本文中联合索引的定义为(MySQL): ALTER TABLE table_name ADD INDEX (col1,col2,col3); 二.联合索引的本质 当创建(col1, ...
- 【Azure 应用服务】应用服务中发布Docker Container,如何添加卷(如Azure File Share)以便永久存储文件
问题描述 应用服务中发布Docker Container,如何添加卷(如Azure File Share)以便永久存储文件 问题解答 App Service可以通过门户配置Mount Storage, ...
- JAVA微服务分布式事务的几种实现方式
基础理论 CAP理论 一致性(Consistency) :在分布式系统中所有的数据备份,在同一时刻都保持一致状态,如无法保证状态一致,直接返回错误: 可用性(Availability):在集群中一部分 ...
- Acwing第132场周赛
AcWing 5366. 大小写转换 签到题,可以用stl里面的tolower函数 #include <bits/stdc++.h> #define ls p<<1 #defi ...
- MYSQL中正则表达式检索数据库
1.MySQL中使用通配符检索数据库,之外还可以使用正则表达式来检索数据. 使用通配符 '_' 和 '%'的区别如下, 使用通配符的技巧:一般的来说 通配符可以处理数据,但是消耗内存较大 ...
- git 全局用户名改为英文,中文生成的git记录文件 不能有中文,现场反馈 git config user.name
设置用户名和邮箱 git config --global user.name "username" git config --global user.email useremail ...
- 摆脱鼠标操作 vscode-vim-use-readme.md
vscode-vim 学习笔记 梳理下自己定义的快捷键 Normal模式返回 ESC capsLock 双击shift ctrl+[ jj ctrl+c (这个键比较特殊 用习惯y的话,考虑这个) 一 ...
- 霞鹜文楷 字体推荐 - 'Fira Code', '霞鹜文楷等宽 Light',
霞鹜文楷 字体推荐 字体推荐 在vscode里面 'Fira Code', '霞鹜文楷等宽 Light', 仓库 https://github.com/lxgw/LxgwWenKai https:// ...
- git cherry-pick 摘樱桃 vscode
git cherry-pick -n b2e9bf7530ce42910a5be99c358fa8c7ab6af507 -n 就是临时到暂存里面 SHA 可以为多个 逗号拼接