RabbitMQ中的单个确认、批量确认、异步确认模式

准备代码 生产Channel的工具类

    public static Channel getChannel() {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setUsername("guest");
        factory.setPassword("guest");
        try {
            connection = factory.newConnection();
            channel = connection.createChannel();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return channel;
    }

(一)、单个消息确认

重点代码

//消息确认
boolean flag = channel.waitForConfirms();
Channel channel = RabbitUtils.getChannel();
channel.queueDeclare(PUBLISH_QUEUE, true, false, false, null);
//开启发布确认
channel.confirmSelect();
long begin = System.currentTimeMillis();
for (int i = 0; i < MESSAGE_NUM; i++) {
    String message = i+"";
    channel.basicPublish("", PUBLISH_QUEUE, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));
    //单个消息马上进行确认
    boolean flag = channel.waitForConfirms();
    if (flag) {
       System.out.println("消息被确认 = " + message);
    }
}
long end = System.currentTimeMillis();
System.out.println("end-begin = " + (end - begin));

(二)、批量确认

重点代码

boolean flag = channel.waitForConfirms();
public static void publishMessageBatch() throws Exception {
        Channel channel = RabbitUtils.getChannel();
        channel.queueDeclare(PUBLISH_QUEUE, true, false, false, null);
        //开启发布确认
        channel.confirmSelect();
        long begin = System.currentTimeMillis();
        for (int i = 0; i < MESSAGE_NUM; i++) {
            String message = i+"";
            channel.basicPublish("", PUBLISH_QUEUE, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));

            if (i % 100 == 0) {
                boolean flag = channel.waitForConfirms();
                System.out.println("消息被确认 = " + message);
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("批量确认时间 :end-begin = " + (end - begin));
}

(三)、异步确认

重点代码:

//监听确认回调和未确认回调
channel.addConfirmListener(confirmCallback, nackCallback);

 完整代码:

public static void publishMessageAsync() throws Exception {
        Channel channel = RabbitUtils.getChannel();
        channel.queueDeclare(PUBLISH_QUEUE, true, false, false, null);
        //开启发布确认
        channel.confirmSelect();

        //消息确认成功回调
        ConfirmCallback confirmCallback = (deliveryTag, multiple) ->{
            System.out.println("已确认的消息" + deliveryTag);
        };
        //消息确认失败回调
        //deliveryTag :  消息的标记
        //multiple : 是否批量确认
        ConfirmCallback nackCallback = (deliveryTag, multiple)->{
            System.out.println("未确认的消息" + deliveryTag);
        };
        //开启消息监听,监听哪些消息成功,哪些消息失败
        channel.addConfirmListener(confirmCallback, nackCallback);

        long begin = System.currentTimeMillis();
        for (int i = 0; i < MESSAGE_NUM; i++) {
            String message = i+"";
            channel.basicPublish("", PUBLISH_QUEUE, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));
        }
        long end = System.currentTimeMillis();
        System.out.println("异步确认时间 :end-begin = " + (end - begin));
}

异步确认优化:

记录所有消息的标记和内容,然后判断哪些消息被接收到哪些没有

 重点代码

1、创建一个ConcurrentSkipListMap存放消息的序号和消息

/*
* 线程安全有序的一个哈希表,适用于高并发情况下
* 优点1:能很好的将序号(key)和消息(value)关联起来
* 优点2:轻松批量删除条目,只要给到序号
* 优点3:适用于高并发(多线程)
* */
ConcurrentSkipListMap<Long, String> outstandingConfirms= new ConcurrentSkipListMap<>();

 

public static void publishMessageAsync() throws Exception {
        Channel channel = RabbitUtils.getChannel();
        channel.queueDeclare(PUBLISH_QUEUE, true, false, false, null);
        //开启发布确认
        channel.confirmSelect();
        /*
        * 线程安全有序的一个哈希表,适用于高并发情况下
        * 优点1:能很好的将序号(key)和消息(value)关联起来
        * 优点2:轻松批量删除条目,只要给到序号
        * 优点3:适用于高并发(多线程)
        * */
        ConcurrentSkipListMap<Long, String> outstandingConfirms= new ConcurrentSkipListMap<>();

        //消息确认成功回调
        ConfirmCallback confirmCallback = (deliveryTag, multiple) ->{
            if (multiple) {
                ConcurrentNavigableMap<Long, String> confirmed = outstandingConfirms.headMap(deliveryTag);
                confirmed.clear();
            } else {
                outstandingConfirms.remove(deliveryTag);
            }
            System.out.println("已确认的消息" + deliveryTag);
        };
        //消息确认失败回调
        //deliveryTag :  消息的标记
        //multiple : 是否批量确认
        ConfirmCallback nackCallback = (deliveryTag, multiple)->{
            System.out.println("未确认的消息" + deliveryTag);
            System.out.println("outstandingConfirms = " + outstandingConfirms);
        };
        //开启消息监听,监听哪些消息成功,哪些消息失败
        channel.addConfirmListener(confirmCallback, nackCallback);

        long begin = System.currentTimeMillis();
        for (int i = 0; i < MESSAGE_NUM; i++) {
            String message = i+"";
            channel.basicPublish("", PUBLISH_QUEUE, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));
            //outstandingConfirms中存放序号和消息
            outstandingConfirms.put(channel.getNextPublishSeqNo(), message);
        }
        long end = System.currentTimeMillis();
        System.out.println("异步确认时间 :end-begin = " + (end - begin));
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值