RabbitMQ基础篇(六)-不公平分发

概念

不公平分发可以理解为能者多劳,按照消费者的处理能力进行消息分配(处理快,消息分配多),以此提高队列消息处理速度,充分利用了消费者的性能。一般情况下会使用不公平分发,而不使用轮询。

  1. // 消费方设置 prefetch = 1,即开启不公平分发

  2. channel.basicQos(1);

预取值

可以为消费者指定分配固定任务数量,假设有七个任务,可以给A分配2个任务,给B分配4个任务。

// 消费者A:设置prefetch = 2
channel.basicQos(2);
// 消费者B:设置 prefetch=4
channel.basicQos(4);

发布确认

消费者能消费消息的前提是,提供者能正确推送消息到队列中。然而,如果在提供者往队列中推送消息时,RabbitMQ出现某些突发意外,比如重启,导致消息推送时丢失,这时就需要手动处理和恢复推送失败的消息。

三种发布确认方式:

  1. 单个确认

问题排查相对简单,但效率低。

  1. 批量确认

出现问题不易定位具体问题。执行效率高。

  1. 异步确认

发布消息的同时,采用异步确认方式提高执行效率。

实例代码:

单次发布确认
public static void producerSingleton() throws Exception {
        Connection connection = RabbitConnectionUtil.getConnection();
        // 队列声明
        Channel channel = connection.createChannel();
        channel.queueDeclare(queenName, true, false, false, new HashMap<>());
        // 开启发布确认
        channel.confirmSelect();
        long startTime = System.currentTimeMillis();

        for (int i = 0; i < SEND_COUNT; i++) {
            String sendMessage = "第<" + i + ">消息  ";
            channel.basicPublish("", queenName, null, sendMessage.getBytes(StandardCharsets.UTF_8));
            // 单个消息马上进行发布确认
            boolean flag = channel.waitForConfirms();
            if (flag) {
                System.out.println("消息发送成功!");
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("单个发布确认:耗时:" + (endTime - startTime));
}
批量确认
public static void producerBatch() {
        try {
            Connection connection = RabbitConnectionUtil.getConnection();
            // 队列声明
            Channel channel = connection.createChannel();
            channel.queueDeclare(queenName, true, false, false, new HashMap<>());
            // 开启发布确认
            channel.confirmSelect();
            long startTime = System.currentTimeMillis();

            // 50条确认一次
            int confirmPoint = 50;

            for (int i = 0; i < SEND_COUNT; i++) {
                String sendMessage = "第<" + i + ">消息  ";
                channel.basicPublish("", queenName, null, sendMessage.getBytes(StandardCharsets.UTF_8));
                // 批量确认
                if (i % confirmPoint == 0) {
                    channel.waitForConfirms();
//                    System.out.println("消息发送成功!");
                }
            }
            long endTime = System.currentTimeMillis();
            System.out.println("批量发布确认:耗时:" + (endTime - startTime));
        } catch (IOException | TimeoutException | InterruptedException e) {
            e.printStackTrace();
        }
}
异步确认
public static void producerSync() {
        try {
            Connection connection = RabbitConnectionUtil.getConnection();
            // 队列声明
            Channel channel = connection.createChannel();
            channel.queueDeclare(queenName, true, false, false, new HashMap<>());
            // 开启发布确认
            channel.confirmSelect();
            long startTime = System.currentTimeMillis();

            // 消息确认成功回调 (消息标记,是否批量确认)
            ConfirmCallback ackCallback = (deliverTag, multiple) -> {
                System.out.println("消息监听成功" + deliverTag);
            };

            // 消息确认失败回调 (消息标记,是否批量确认)
            ConfirmCallback nackCallback = (deliverTag, multiple) -> {
                System.out.println("监听失败 ==> " + deliverTag);
            };

            // 准备消息监听器,监听哪些消息状态
            channel.addConfirmListener(ackCallback, nackCallback);

            for (int i = 0; i < SEND_COUNT; i++) {
                String sendMessage = "第<" + i + ">消息  ";
                channel.basicPublish("", queenName, null, sendMessage.getBytes(StandardCharsets.UTF_8));
            }
            long endTime = System.currentTimeMillis();
            System.out.println("批量发布确认:耗时:" + (endTime - startTime));
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
}

测试:

    public static void main(String[] args) throws Exception {
        // 1、单个确认: 可以快速定位确认失败位置,效率低
        producerSingleton();
        // 2、批量确认:不好定位确认位置,效率高
        producerBatch();
        // 3、异步批量确认: 兼容二者,效率高,可监听消息发送状态
        producerSync();

    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值