RabbitMQ工作模式——Work queues 工作队列模式

大伙可以到我的RabbitMQ专栏​​​​​​​获取更多信息

模式说明

RabbitMQ工作模式——Work queues 工作队列模式_第1张图片

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" 获取消息:

RabbitMQ工作模式——Work queues 工作队列模式_第2张图片

RabbitMQ工作模式——Work queues 工作队列模式_第3张图片

RabbitMQ工作模式——Work queues 工作队列模式_第4张图片

运行生产者向MQ中 "workQueues" 中发送10条消息:

RabbitMQ工作模式——Work queues 工作队列模式_第5张图片

MQ的控制台监控到了这10条消息,之后两个客户端开始竞争队列中的消息,情况如下:

分明显,10条消息被两个消费者依次消费了,所以在Work queues模式下,所有的消费者的“竞争”是公平的,并且每条message只能被唯一一个消费者获取到

 

 

 

你可能感兴趣的:(#,RabbitMQ,work,queues,rabbitmq,java)