RabbitMQ在手动消费的模式下设置失败重新投递策略

最近在写RabbitMQ的消费者,因为业务需求,希望失败后重试一定次数,超过之后就不处理了,或者放入死信队列。我这里就达到重试次数后就不处理了。本来以为很简单的,问了kimi,按它的方法配置之后,发现报错之后一直重复消费,进入了死循环。

下面是kimi给的"最佳实践"的示例代码:

java 复制代码
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistrar;
import org.springframework.amqp.rabbit.listener.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {

    @Bean
    public SimpleRabbitListenerContainerFactory myFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        return factory;
    }
}

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class RabbitMQConsumer {

    @RabbitListener(queues = "your-queue-name", containerFactory = "myFactory")
    public void receiveMessage(final Message message, com.rabbitmq.client.Channel channel) {
        // 消息处理逻辑
        try {
            String payload = new String(message.getBody());
            System.out.println("Received message: " + payload);
            // 业务逻辑处理
            // ...

            // 手动确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            System.out.println("Error processing message: " + e.getMessage());
            try {
                // 拒绝消息并重新入队
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            } catch (Exception ex) {
                // 如果消息拒绝失败,则关闭通道
                channel.close();
            }
        }
    }
}

问题出在哪里呢?

看起来是很完美的,但是......,还是有漏洞:

这样写是有问题的,会导致失败后消息重新入队,应该是因为重新计算重试次数,如果一直失败,就一直重试,一直清空,那永远不能达到最大次数,导致死循环......

所以,这个地方正确的处理方式是抛异常,

直接throw 一个异常即可。这样就能正确重试了。

这个过程参考了这个博文:rabbitmq消费(失败)重试3次(多次) - 幂次方 - 博客园

总结教训:AI不是万能的,如果按AI的方案得不到结果,有可能是它出错了,毕竟它的方案是没有经过实践检验的。这个时候就会发现原始资料的重要性了。博客还是有它存在的价值的。

相关推荐
2301_800050991 小时前
ceph分布式存储
笔记·分布式·ceph
YDS8292 小时前
SpringCloud —— 分布式事务管理Seata详解
分布式·spring·spring cloud·seata
回家路上绕了弯4 小时前
分布式系统重试策略详解:可靠性与资源消耗的平衡艺术
分布式·后端
无名小卒Rain4 小时前
Jmeter性能测试-分布式压测配置和执行过程
分布式·jmeter
a程序小傲4 小时前
蚂蚁Java面试被问:分布式Session的实现方案
java·分布式·面试
a努力。4 小时前
京东Java面试:如何设计一个分布式ID生成器
java·分布式·后端·面试
前端世界5 小时前
HarmonyOS 分布式硬件实战指南:从原理到可运行 Demo
分布式·华为·harmonyos
汪不止5 小时前
【 分布式唯一业务单号生成方案:Redis + 数据库双保险架构】
数据库·redis·分布式