189 8069 5689

RabbitMQ消费失败重试策略、及重试策略应用场景详解-创新互联

前言:
RabbitMQ消费者一般情况下,如果消费失败出现异常,那么消费端默认是无限重试消费,这样就会带来非常不好的一个情况,就是陷入死循环,一直报错一直重试。所以我们需要对消费异常重试次数、重试间隔时间进行限制

专注于为中小企业提供成都网站制作、网站设计服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业振安免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了超过千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

一、限制消费异常重试次数、重试间隔时间

1、配置限制策略,如下:

rabbitmq:
    host: xxx
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    listener:
      simple:
        default-requeue-rejected: false
        acknowledge-mode: manual  # 确认模式为手动确认-需要在代码中手动ACK
        retry:
          enabled: true           # 开启消费者出现异常情况下,进行重试消费,默认false
          max-attempts: 5         # 大重试次数,默认为3
          initial-interval: 3000  # 重试间隔时间,默认1000(单位毫秒)

其中 retry 节点及以下的属性就是重试策略

2、验证重试策略是否生效
这里使用一张 user 信息表作演示

【1】演示代码

@RabbitListener(queues = {MqConstants.DIRECT_QUEUE_1})
    public void listenerDirectQueue1(Message message, Channel channel) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        //验证消费失败(出现异常)重试策略 start
        String msgBody = new String(message.getBody());
        System.out.println("消费者接收到消息:【" + msgBody + "】");
        int i = 1 / 0;
        channel.basicAck(deliveryTag, false);
        //验证消费失败(出现异常)重试策略 end
    }

模拟了一个除数为0的异常

【2】演示结果

从控制台输出可以看出,异常后尝试了5次后仍然失败,就放弃重试,符合预期结果

二、消息消费异常重试策略应用场景,并不是所有消息异常后都需要重试

1、说明:
【1】比如我们调用第三方接口、或者调用别的服务的接口,那么这时候出现异常要不要重试?当然要重试,因为调用接口异常可能是网络波动导致,并不是业务代码异常,所以重试后可能就可以正常调用
【2】比如我们在消费过程中,业务代码出现异常(空指针、除数为0等)这类代码不健壮导致的异常,那么这时候需要重试吗?当然不需要重试,因为业务代码异常就算重试再多次也依然会异常,代码异常需要发版修复解决,所以重试没有意义。这种情况我们可以把代码块 try catch 一下:

@RabbitListener(queues = {MqConstants.DIRECT_QUEUE_1})
    public void listenerDirectQueue1(Message message, Channel channel) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        String msgBody = new String(message.getBody());

        //验证消费失败(出现异常)重试策略 start
        try {
            System.out.println("消费者接收到消息:【" + msgBody + "】");
            int i = 1 / 0;
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            log.info("异常消息:" + msgBody);
            //此时可以把异常消息写入表中,以供人工或定时任务做重试补偿
            channel.basicAck(deliveryTag, false);
        }
        //验证消费失败(出现异常)重试策略 end
    }

可以看见异常被捕捉了,所以没有触发重试策略

小结:
在 catch 块中不要抛出异常就不会触发重试策略,在 catch 块中我们把该条消息记录到日志数据表或者其他特定的表,以供过后人工或定时任务单独处理异常消息补偿即可

2、应用场景总结:
【1】类似调用第三方接口这种场景出现异常,需要重试
【2】业务代码出现异常(空指针、除数为0等)这类代码不健壮导致的异常,不需要重试,没有意义
【3】异常不需要触发重试策略的消息,需要把该条消息记录到日志数据表或者其他特定的表,以供过后人工或定时任务单独处理异常消息补偿

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻名称:RabbitMQ消费失败重试策略、及重试策略应用场景详解-创新互联
路径分享:http://cdxtjz.cn/article/dihjio.html

其他资讯