RabbitMQ学习总结(六)之消息应答

9 篇文章 1 订阅
7 篇文章 0 订阅

作者处于学习阶段,刚刚完成RabbitMQ的学习,作为学生,我会用更通俗的说法,来叙述自己对RabbitMQ的了解。愿各位大佬看到有见解错误的地方和叙述不好的地方,能够帮忙纠正。来帮助大家更加深入的了解RabbitMQ。

  1. 发布确认原理
    生产者将信道设置为confirm模式, 信道上发布的每一条消息都会携带唯一的ID。当消息成功到达队列后,队列返回给生产者一个确认,让生产者知道消息被接受到了。如果消息和队列设置了持久化(上一节有提到过,链接:RabbitMQ学习总结(五)之消息应答和持久化),那么发布成功的消息将会先存储到磁盘,然后再发送给生产者。
    confirm 模式最大的好处在于他是异步的,一旦发布一条消息,生产者应用程序就可以在等信
    道返回确认的同时继续发送下一条消息,当消息最终得到确认之后,生产者应用便可以通过回调
    方法来处理该确认消息,如果 RabbitMQ 因为自身内部错误导致消息丢失,就会发送一条 nack 消
    息,生产者应用程序同样可以在回调方法中处理该 nack 消息。

  2. 如何开启发布确认
    在channel上调用congirmSelect()方法,便可以开启发布确认。
    在这里插入图片描述

  3. 单个确认发布
    简单来说就是单个确认,一个一个的确认,当确认一条消息后,才能继续后续消息的发布。缺点:速度慢,若出现一条消息没有确认便会堵塞后续消息。
    对应代码:`//单个确认
    public static void publishMessageIndividually() throws Exception{
    Channel channel = RabbitMqUtils.getChannel();

     //队列的声明
     String queueName = UUID.randomUUID().toString();
     channel.queueDeclare(queueName,true,false,false,null);
     //开启发布确认
     channel.confirmSelect();
     //开始时间
     long begin = System.currentTimeMillis();
    
     //批量发消息
     for(int i=0;i<MESSAGE_COUNT;i++){
         String message = i + "";
         channel.basicPublish("",queueName,null,message.getBytes());
         //单个消息就马上进行发布确认
         boolean flag = channel.waitForConfirms();
         if(flag){
             System.out.println("成功");
         }else {
             System.out.println("失败");
         }
     }
     //结束时间
     long end = System.currentTimeMillis();
     System.out.println((end-begin)+"ms");
    

    }`

  4. 批量确认发布
    由名知意,便是多条一起确认。当接收多条后,再发布确认。但是当出现问题时,不知道具体是哪条消息,而且当出现问题后,后续的消息同样阻塞。
    对应代码:`public static void publishMessageBatch() throws Exception{
    Channel channel = RabbitMqUtils.getChannel();

     //队列的声明
     String queueName = UUID.randomUUID().toString();
     channel.queueDeclare(queueName,true,false,false,null);
     //开启发布确认
     channel.confirmSelect();
     //开始时间
     long begin = System.currentTimeMillis();
    
     //批量确认消息大小
     int batchSize = 1000;
     //批量发布确认消息
     for(int i= 0;i<MESSAGE_COUNT;i++){
         String message = i + "";
         channel.basicPublish("",queueName,null,message.getBytes());
         if((i+1)%batchSize==0){
             //发布确认
             channel.waitForConfirms();
             System.out.println("确认成功");
         }
     }
    
     //结束时间
     long end = System.currentTimeMillis();
     System.out.println((end-begin)+"ms");
    

    }`

  5. 异步确认发布
    在学习时,看了很多网上的知识,好多只是把图片放在了上面,并没有进行讲解,只不过是原搬原抄。我将我的理解在下总结,如有问题,请多指正。
    生产者将消息发送到队列中,队列将收到的消息和未收到的消息全部放入到回调函数中,生产者调用回调函数便可以知道哪个消息发送成功,哪个消息出现问题。

    对应代码:`public static void publishMessageAsync() throws Exception{
    Channel channel = RabbitMqUtils.getChannel();

     //队列的声明
     String queueName = UUID.randomUUID().toString();
     channel.queueDeclare(queueName,true,false,false,null);
     //开启发布确认
     channel.confirmSelect();
    
     /**
      * 1. 线程安全有序的一个哈希表 适用于高并发的情况下
      * 2.轻松批量删除条目 只需要给到序号
      * 3.支持高并发
      */
     ConcurrentSkipListMap<Long,String> outstandingComfirms =
             new ConcurrentSkipListMap<>();
    
     //开始时间
     long begin = System.currentTimeMillis();
    
     //消息确认成功 回调函数
     ConfirmCallback ackCallback = (deliveryTag, multiple) -> {
         if (multiple){
             //2.删除已经确认的消息 剩下的就是确认失败的消息
             ConcurrentNavigableMap<Long, String> confrmed = outstandingComfirms.headMap(deliveryTag);
             confrmed.clear();
         }else{
             outstandingComfirms.remove(deliveryTag);
         }
         System.out.println("确认的消息内容"+deliveryTag);
     };
     //消息确认失败 回调函数
     /**
      * 1.消息的标记
      * 2.是否为批量确认
      */
     ConfirmCallback nackCallback = (deliveryTag, multiple) -> {
         String message = outstandingComfirms.get(deliveryTag);
         System.out.println("未确认的消息是:"+message+"未确认的消息" + deliveryTag);
     };;
     //准备消息的监听器 监听哪些消息成功了 哪些消息消失了
     channel.addConfirmListener(ackCallback,nackCallback);
    
     //批量发送消息
     for (int i = 0; i < MESSAGE_COUNT; i++) {
         String message = "消息"+i;
         channel.basicPublish("",queueName,null,message.getBytes());
    
         //1:此处记录下所有要发送的消息 消息的总和
         outstandingComfirms.put(channel.getNextPublishSeqNo(),message);
    
     }
     //结束时间
     long end = System.currentTimeMillis();
     System.out.println((end-begin)+"ms");
    

    }`

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱分享的小邓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值