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

RabbitMQ工作队列(work queues)

在这里插入图片描述
       工作队列(又称任务队列)的主要思想是避免立即执行资源密集型任务,造成消息堆积。利用多个消费者同时消费队列中不同的消息,处理速度快的消费者多分配一些消息,相反,处理速度慢的消费者少分配一下消息。当您运行许多工作任务时,任务将在他们之间共享。所有的消费者将 (注意:不是消费同一条消息,而是在默认情况下将一些消息平均分配给不同的消费者消费,类似于nginx的负载均衡) 消费不同的消息,开启消息自动确认机制时平均分配的,如果关闭自动消息确认机制,利用手动确认,则会实现能者多劳的消费模式,具体详情代码说明。

代码实现

默认平均分配

生产者

package com.mahy.notes.workqueues;

import com.mahy.utils.RabbitMQUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;

/**
 * @Auther : mahy
 * @Date : 2020/7/27 21:10
 * @Description : RabbitMQ的工作队列 参数说明请查看直连模式中的说明
 */
public class Provider {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("workqueues",true,false,false,null);
        for (int i= 1;i<=10;i++){
            channel.basicPublish("","workqueues",null,"WorkQueues is OK!".getBytes());
        }
        RabbitMQUtils.closeConnection(channel,connection);
    }
}

消费者

消费者1
package com.mahy.workqueue;

import com.mahy.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import java.io.IOException;

/**
 * @Auther : mahy
 * @Date : 2020/7/27 21:17
 * @Description : 工作队列消费者1.
 */
public class Customer001 {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("workqueuees",true,false,false,null);
        //消费消息
        channel.basicConsume("workqueues",true,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));
            }
        });
    }
}
消费者2
package com.mahy.workqueue;

import com.mahy.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import java.io.IOException;

/**
 * @Auther : mahy
 * @Date : 2020/7/27 21:17
 * @Description : 工作队列消费者1.
 */
public class Customer002 {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("workqueuees",true,false,false,null);
        //消费消息
        channel.basicConsume("workqueues",true,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));
            }
        });
    }
}

注意:消费者代码一样。

运行结果

消费者1消费的消息:

在这里插入图片描述

消费者2消费的消息:

在这里插入图片描述
说明:通过上面的结果可以看出,工作队列默认情况下是平均分配消息给消费者的,但是又会出现另外一种情况:如果一个消费者消费的速度快,另外一个慢,怎么提高消息的消费效率,而不是平均分配消息给每个消费者。下面时如何让工作队列处于能者多劳模式:

能者多劳模式(提高消息被消费的效率)

步骤:

  • 关闭消息自动确认机制
  • 设置通道每次消费的消息为一条
  • 使用手动消息确认机制

代码实现

生产者
package com.mahy.notes.workqueues;

import com.mahy.utils.RabbitMQUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;

/**
 * @Auther : mahy
 * @Date : 2020/7/27 21:10
 * @Description : RabbitMQ的工作队列 代码没有变化.
 */
public class Provider {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("workqueues",true,false,false,null);
        for (int i= 1;i<=20;i++){
            channel.basicPublish("","workqueues",null,(i + "WorkQueues is OK!").getBytes());
        }
        RabbitMQUtils.closeConnection(channel,connection);
    }
}
消费者
消费者1
package com.mahy.notes.workqueues;

import com.mahy.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import java.io.IOException;

/**
 * @Auther : mahy
 * @Date : 2020/7/27 21:17
 * @Description : 工作队列消费者1.
 */
public class Customer001 {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        //每次只能消费一条消息
        channel.basicQos(1);
        channel.queueDeclare("workqueuees",true,false,false,null);
        //消费消息
        //关闭消息自动自动确认机制:参数二设置为false
        channel.basicConsume("workqueues",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                //睡眠1秒方便观看效果
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("消费者1消费:" + new String(body));
                /**
                 * 手动确认消息
                 * 参数一: 具体那条消息的标志
                 * 参数二: 是否开启多条消息同时确认(由于上面指定了一次只能消费一条消息 所以关闭)
                 */
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }
}
消费者2
package com.mahy.notes.workqueues;

import com.mahy.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import java.io.IOException;

/**
 * @Auther : mahy
 * @Date : 2020/7/27 21:17
 * @Description : 工作队列消费者1.
 */
public class Customer002 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtils.getConnection();
        Channel channel = connection.createChannel();
        //每次只能消费一条消息
        channel.basicQos(1);
        channel.queueDeclare("workqueuees",true,false,false,null);
        //消费消息
        //关闭消息自动自动确认机制:参数二设置为false
        channel.basicConsume("workqueues",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                //睡眠3秒方便观看效果
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("消费者2消费:" + new String(body));
                /**
                 * 手动确认消息
                 * 参数一: 具体那条消息的标志
                 * 参数二: 是否开启多条消息同时确认(由于上面指定了一次只能消费一条消息 所以关闭)
                 */
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }
}
结果
消费者1的结果

在这里插入图片描述

消费者2的结果

在这里插入图片描述
这样就能实现能者多劳的功能了,这就是工作队列。

最后说明

这是观看BILIBILI上“编程不良人”大神的视频学习记录的笔记,如果眼花有记错的地方,希望能够提出,大家共同努力,谢谢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值