大伙可以到我的RabbitMQ专栏获取更多信息
Work queues:显而易见,与简单模式不同的是,Work queues 模式存在多个消费者,多个消费者其实是竞争关系,C1 C2只有一个能从MQ队列中获取到消息
应用场景:对于任务过重或者任务较多情况下,使用Work queues模式可以提高任务的处理速度
比如P端的任务每秒有1000个,但是每个C端每秒只能处理500个,所以两个C端共同“竞争”MQ中的任务就可以处理1000个消息了,需要注意的是C1和C2获得的消息互不相同。
其实Work queues模式就是在简单模式上的一对多模式:这个“一”并不能理解为生产者,因为实际业务场景中产生消息的生产者有很多,而这个“一”指的是多有C端对应的那个队列。
改造简单模式的代码
生产者代码基本不需要变动,就是多产生几条message供消费者竞争
package com.leolee.rabbitmq;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @ClassName ProducerHelloWorld
* @Description: MQ生产者 work queues模式
* @Author LeoLee
* @Date 2020/11/5
* @Version V1.0
**/
public class ProducerWorkQueues {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//2.设置参数
connectionFactory.setHost("127.0.0.1");//默认值为localhost
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/LeoLee");//默认值为:/
connectionFactory.setUsername("LeoLee");
connectionFactory.setPassword("lyl512240816");
//3.创建连接 connection
Connection connection = connectionFactory.newConnection();
//4.创建channel
Channel channel = connection.createChannel();
//5.创建队列queue(由于简单模式不需要Exchange,其实是使用默认的交换机,所以消息直接入队列)
/*
String queue:队列名称
boolean durable:是否持久化
boolean exclusive: 有如下两个意义
是否独占,只有一个消费者监听这个队列
当connection关闭时,是否删除队列
boolean autoDelete:是否自动删除,当没有消费者的时候自动删除
Map arguments: 一些配置参数
*/
//如果没有一个名字叫Hello_world的队列,则会创建,如果存在该队列,则复用
channel.queueDeclare("workQueues", false, false, false, null);
//6.发送消息
/*
String exchange:交换机名称,简单模式下交换机使用默认的 ""
String routingKey:路由名称,简单模式下就是队列名称
boolean mandatory:
boolean immediate:
BasicProperties props:配置信息
byte[] body:发送的消息数据
*/
for (int i = 1; i <= 10; i++) {
String msg = "[" + i + "]:Hello RabbitMQ";
channel.basicPublish("", "workQueues", null, msg.getBytes());
}
//7.释放资源
channel.close();
connection.close();
}
}
消费者代码
package com.leolee.rabbitmq;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @ClassName ConsumerHelloWorld
* @Description: MQ消费者 work queues模式
* @Author LeoLee
* @Date 2020/11/5
* @Version V1.0
**/
public class ConsumerWorkQueues1 {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//2.设置参数
connectionFactory.setHost("127.0.0.1");//默认值为localhost
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/LeoLee");//默认值为:/
connectionFactory.setUsername("LeoLee");
connectionFactory.setPassword("lyl512240816");
//3.创建连接 connection
Connection connection = connectionFactory.newConnection();
//4.创建channel
Channel channel = connection.createChannel();
//5.创建队列queue(由于简单模式不需要Exchange,其实是使用默认的交换机,所以消息直接入队列),消费者可以不需要创建队列,但是创建了也不影响
/*
String queue:队列名称
boolean durable:是否持久化
boolean exclusive: 有如下两个意义
是否独占,只有一个消费者监听这个队列
当connection关闭时,是否删除队列
boolean autoDelete:是否自动删除,当没有消费者的时候自动删除
Map arguments: 一些配置参数
*/
//如果没有一个名字叫Hello_world的队列,则会创建,如果存在该队列,则复用
channel.queueDeclare("workQueues", false, false, false, null);
//6.接收消息
/*
* String queue:队列名称
* boolean autoAck:是否自动确认,当消费者收到消息之后会自动给MQ一个回执,告诉MQ消息已经收到
* Consumer callback:回调方法
*/
Consumer consumer = new DefaultConsumer(channel){
/*
* 功能描述:
* 〈回调方法〉当客户端收到消息并向MQ确认消息已经收到,将回调该方法
* @Param: [consumerTag消息唯一标识,
* envelope获取一些信息,包含交换机信息、routing key...等,
* properties配置信息,生产者发送消息时候的配置,
* body数据]
* @Return: void
* @Author: LeoLee
* @Date: 2020/11/5 11:56
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
/*System.out.println("consumerTag:" + consumerTag);
System.out.println("envelope.exchange:" + envelope.getExchange());
System.out.println("envelope.routingKey:" + envelope.getRoutingKey());
System.out.println("properties:" + properties);*/
System.out.println("body:" + new String(body));
}
};
channel.basicConsume("workQueues", true, consumer);
//7.消费者不需要关闭资源,不然无法完成自动确认
}
}
运行多个消费者端,成功与MQ建立连接,都是从队列 "workQueues" 获取消息:
运行生产者向MQ中 "workQueues" 中发送10条消息:
MQ的控制台监控到了这10条消息,之后两个客户端开始竞争队列中的消息,情况如下:
分明显,10条消息被两个消费者依次消费了,所以在Work queues模式下,所有的消费者的“竞争”是公平的,并且每条message只能被唯一一个消费者获取到。