rabbitMq不公平分发

rabbitMq默认是公平分发的,即轮询分发,有多少个消费者,多少个消费者平均消费消费。具体例子请看我之前写的文章《rabbitMq消息应答–ack机制》。但是在工作中,我们希望消费速度快的机器就消费更多的消息。这时候我们可以在消费者设置channel.basicQos(1);不公平分发,来让消费速度快的消费者消费更多的消息。意思就是如果这个任务我还没有处理完或者我还没有应答你,你先别分配给我,我目前只能处理一个任务,然后 rabbitmq 就会把该任务分配给没有那么忙的那个空闲消费者。
不公平分发的缺点:如果所有的消费者都没有完成手上任务,队列还在不停的添加新任务,队列有可能就会遇到队列被撑满的情况,这个时候就只能添加新的 worker 或者改变其他存储任务的策略。
具体例子如下:
消费者一

public class WorkAck {
    public static final String QUEUE_NAME = "ack_queue";

    /**
     * 消息手动应答代码示例
     * @param args
     * @throws IOException
     * @throws TimeoutException
     */
    public static void main(String[] args) throws IOException, TimeoutException {

        Channel channel = RabbitUtils.getChannel();
        System.out.println("线程1较快,在等待消息:");
        DeliverCallback deliverCallback = new DeliverCallback() {
            @Override
            public void handle(String consumerTag, Delivery message) throws IOException {
                System.out.println(Thread.currentThread().getName() + "接收到了消息:" + new String(message.getBody()));
                // 消息手动应答
                channel.basicAck(message.getEnvelope().getDeliveryTag(), false);
            }
        };
        CancelCallback cancelCallback = new CancelCallback() {
            @Override
            public void handle(String consumerTag) throws IOException {
                System.out.println(Thread.currentThread().getName()+"取消发送了");
            }
        };
        System.out.println(Thread.currentThread().getId() + "消费者正在等待消息----");
        /**
         * 第一个参数是队列名称
         * 第二个参数表示是否自动应答,如果是true,则无需手动应答,如果是false,则需要手动应答;
         * 手动应答是消费者处理完本条消息,然后会向mq服务器进行消息确认,允许mq服务器在队列中把消息删除;一旦消费者没有向mq服务器进行确认,即使消费者断开后;
         * mq服务器也会把消息重新入到mq队列,给其他的消费者消费。
         *  生产上一般都开启手动应答;自动应答存在消费者还没处理完消息时,队列清空了消息,导致消息无法重新入队,有消息丢失的风险;
         */
         // 设置不公平分发,默认是0,0表示公平分发。
        channel.basicQos(1);
        channel.basicConsume(QUEUE_NAME, false, deliverCallback, cancelCallback);
    }
}

消费者二:

public class WorkAck2 {
    public static final String QUEUE_NAME = "ack_queue";

    /**
     * 消息手动应答代码示例
     * @param args
     * @throws IOException
     * @throws TimeoutException
     */
    public static void main(String[] args) throws IOException, TimeoutException {

        Channel channel = RabbitUtils.getChannel();
        System.out.println("线程2非常慢,在等待消息:");
        DeliverCallback deliverCallback = new DeliverCallback() {
            @Override
            public void handle(String consumerTag, Delivery message) throws IOException {
                System.out.println(Thread.currentThread().getName() + "接收到了消息:" + new String(message.getBody()));

                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "在处理消息:" + new String(message.getBody()));
                // 消息手动应答
                channel.basicAck(message.getEnvelope().getDeliveryTag(), false);
            }
        };
        CancelCallback cancelCallback = new CancelCallback() {
            @Override
            public void handle(String consumerTag) throws IOException {
                System.out.println(Thread.currentThread().getName()+"取消发送了");
            }
        };
        System.out.println(Thread.currentThread().getId() + "消费者正在等待消息----");
         // 设置不公平分发,默认是0,0表示公平分发。
        channel.basicQos(1);
        /**
         * 第一个参数是队列名称
         * 第二个参数表示是否自动应答,如果是true,则无需手动应答,如果是false,则需要手动应答;
         * 手动应答是消费者处理完本条消息,然后会向mq服务器进行消息确认,允许mq服务器在队列中把消息删除;一旦消费者没有向mq服务器进行确认,即使消费者断开后;
         * mq服务器也会把消息重新入到mq队列,给其他的消费者消费。
         *  生产上一般都开启手动应答;自动应答存在消费者还没处理完消息时,队列清空了消息,导致消息无法重新入队,有消息丢失的风险;
         */
        channel.basicConsume(QUEUE_NAME, false, deliverCallback, cancelCallback);
    }
}

测试结果:

Connected to the target VM, address: '127.0.0.1:8969', transport: 'socket'
线程1较快,在等待消息:
1消费者正在等待消息----
pool-1-thread-4接收到了消息:AA
pool-1-thread-5接收到了消息:CC
pool-1-thread-6接收到了消息:DD

线程2非常慢,在等待消息:
1消费者正在等待消息----
pool-1-thread-4接收到了消息:BB
pool-1-thread-4在处理消息:BB

从测试结果来看,消费者一消费的速度比较快能够消费3条消息,消费者二消费速度比较慢,只能消费1条消息。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值