zoukankan      html  css  js  c++  java
  • rabbitmq 重复ACK导致消息丢失

    rabbitmq 重复确认导致消息丢失

    背景

    rabbitmq 在应用场景中,大多采用工作队列 work-queue的模式。

    在一个常见的工作队列模式中,消费者 worker 将不断的轮询从队列中拉取最新消息,当队列负载压力增大时允许添加多个worker 进行处理。
    然而执行一个任务可能需要相当的时长,这是由业务特性所决定的;如果 worker执行任务过程中出现异常甚至宕机,此时消息便会丢失,这是简单消息队列难以解决的问题。

    rabbitmq 采用了消息确认机制来防止此类问题,在该机制中,worker需要向 MQ Server 返回 ACK响应以表示消息已确认处理;
    在以下情况下,rabbitmq 会对消息进行重新投递:
    1 client 未响应ACK, 主动关闭 Channel;
    2 client 未响应ACk, 网络异常断开;

    消息的重发机制没有超时限制,只要client 不响应ACK,那么会一直投递;
    如果启用了消息持久化机制,那么消息将有进一步的保障。

    问题描述及分析

    1 客户端为简化应答处理,可以设置自动应答选项,如:

      boolean autoAck = false;
      channel.basicConsume(TASK_QUEUE_NAME, autoAck, consumer);
    

    2 如果不启用自动应答,需要应用代码手动进行应答:

        try {
              doWork(message);
            } finally {
              logger.info(" xxx work done");
              channel.basicAck(envelope.getDeliveryTag(), false);
            }
    

    3 当两种方案同时存在

    由于客户端的编码失误,先启用了自动应答选项,又在应用代码执行了应答的代码:
    
         // enable autoAck
         boolean autoAck = true;
         consumerChannel.basicConsume(queueName, autoAck, this);
    
         //...
    
         // snipper from Consumer.handleDelivery method
         // send ack to server  
         try {
                consumerChannel.basicAck(deliveryTag, true);
            } catch (Exception e) {
         }
    

    多了一次确认,应用代码貌似一切如常。 但在频繁进行消息收发测试时发现 消息存在随机性丢失处理的情况!
    检查 rabbitmq server日志发现以下异常:

      {amqp_error,precondition_failed,"unknown delivery tag 1",'basic.ack'}
      ...
      {amqp_error,precondition_failed,"unknown delivery tag 1",'basic.ack'}
      ...
      {amqp_error,precondition_failed,"unknown delivery tag 1",'basic.ack'}
      ...
    

    提示未知的 delivery tag=1,该字段为MQ server 用于消息确认的标记,服务端因无法识别而打印错误。
    另外一个现象则是,连续收发消息 5次,其中丢失消息处理1次,而 rabbitmq server错误日志出现 4次!

    经过分析,发现问题原因所在:
    rabbitmq 为每一个channel维护了一个delivery tag的计数器,这里采用正向自增,新消息投递时自增,当消息响应时自减;
    在连续收发的场景中,由于消息发送的间隔较短,部分消息因 consumer的重复确认被rabbitmq 当做已处理而丢弃。

    解决方案

    取消consumer 的自动应答机制,仅保留手动应答的处理,问题解决。

    参考资料

    关于 rabbitmq 消息确认机制:
    http://www.rabbitmq.com/confirms.html#when

  • 相关阅读:
    VS.NET的新用途
    ASP.NET缓存引起的问题
    增加了查看最新回复功能
    高级浏览功能可以使用了
    转载JGTM'2004 [MVP]的文章
    首页文章字数统计改进
    请推荐好的工作流产品
    不错的工具:Reflector for .NET
    寻找文件同步软件
    javascript引起博客园首页不能显示问题说明
  • 原文地址:https://www.cnblogs.com/littleatp/p/6087856.html
Copyright © 2011-2022 走看看