最近在写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的方案得不到结果,有可能是它出错了,毕竟它的方案是没有经过实践检验的。这个时候就会发现原始资料的重要性了。博客还是有它存在的价值的。