二、 工作队列 work queue模式

特点:
一个生产者对应几个消费者。模型如图:
在这里插入图片描述
1、 轮询分发 Round robin
1.1、生产者

package com.june.rabbitmq.workqueue;

import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Send {
    private static final String QUEUE_NAME = "june_work_queue";

    public static void main(String[] args) {
        try {
            //获取连接
            Connection connection = ConnectionUtil.getConnection();
            //建立通道
            Channel channel = connection.createChannel();
            //声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);

            for (int i=0;i<50;i++){
                String msg = "send message june " + i + " hello!";
                channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
                System.out.println("send message : " + msg);
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

1.2、 消费者1

package com.june.rabbitmq.workqueue;

import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Recevice1 {
    private static final String QUEUE_NAME = "june_work_queue";

    public static void main(String[] args) {
        try {
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            DefaultConsumer consumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = new String(body, "utf-8");
                    System.out.println("[1] recevice message : " + message);
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        System.out.println("[1] done!");
                    }
                }
            };
            //监听队列  注册一个监听事件
            channel.basicConsume(QUEUE_NAME, true, consumer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

    }
}

1.3、 消费者2

package com.june.rabbitmq.workqueue;

import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Recevice2 {
    private static final String QUEUE_NAME = "june_work_queue";

    public static void main(String[] args) {
        try {
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            DefaultConsumer consumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = new String(body, "utf-8");
                    System.out.println("[2] recevice message : " + message);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        System.out.println("[2] done!");
                    }
                }
            };
            //监听队列  注册一个监听事件
            channel.basicConsume(QUEUE_NAME, true, consumer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

    }
}

1.4、现象:
消费者1和消费者2接收消息数量是一样的,消费者1接收的是奇数,消费者2接收的都是偶数。
这种叫轮询分发(Round-robin),均匀的给各个消费者分发消息,并不会忙或闲的都接收到一样多的消息。
注:需要先注册两个或以上消费者,不然如果先注册发送至再注册消费者的话,那会只给一个消费者发送。

2、 公平分发Fair dispatch
设置单个消费者同时处理的消息数量,在收到回发确认消息前,不再给消费者发送消息。这样就达到了谁处理快,谁就拿得多的目的,basicAck自动应答需要改成手动的。
注:这种的可以小注册发送端,因为不会一股脑的就给消费者全发过去。

2.1、生产者

package com.june.rabbitmq.workfair;

import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Send {
    private static final String QUEUE_NAME = "june_work_queue";

    public static void main(String[] args) {
        try {
            //获取连接
            Connection connection = ConnectionUtil.getConnection();
            //建立通道
            Channel channel = connection.createChannel();
            //声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);

            /**设置一次只处理一个消息,每个消费者在回发确认消息之前,队列不会发送第二个消息给同一个消费者
            *   限制一个消费者同时消费的信息数量,限制为1条
             * */
            channel.basicQos(1);

            for (int i=0;i<50;i++){
                String msg = "send message june " + i + " hello!";
                channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
                System.out.println("send message : " + msg);
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            channel.close();
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

2.2、消费者1

package com.june.rabbitmq.workfair;

import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Recevice1 {
    private static final String QUEUE_NAME = "june_work_queue";

    public static void main(String[] args) {
        try {
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            //设置同时只消费一条
            channel.basicQos(1);
            DefaultConsumer consumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = new String(body, "utf-8");
                    System.out.println("[1] recevice message : " + message);
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        System.out.println("[1] done!");
                        channel.basicAck(envelope.getDeliveryTag(), false);
                    }
                }
            };
            //自动应答改为false
            boolean autoAck = false;
            //监听队列  注册一个监听事件
            channel.basicConsume(QUEUE_NAME, autoAck, consumer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

    }
}

2.3、消费者2

package com.june.rabbitmq.workfair;

import com.june.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Recevice2 {
    private static final String QUEUE_NAME = "june_work_queue";

    public static void main(String[] args) {
        try {
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            channel.basicQos(1);
            DefaultConsumer consumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = new String(body, "utf-8");
                    System.out.println("[2] recevice message : " + message);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        System.out.println("[2] done!");
                        channel.basicAck(envelope.getDeliveryTag(), false);
                    }
                }
            };
            boolean autoAck = false;
            //监听队列  注册一个监听事件
            channel.basicConsume(QUEUE_NAME, autoAck, consumer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值