Spring @事务性兔子侦听器导致无限循环

Spring @事务性兔子侦听器导致无限循环,spring,rabbitmq,spring-rabbit,Spring,Rabbitmq,Spring Rabbit,嗨,我的Rabbit侦听器有问题,它会导致无限循环异常(requeue消息)。我的配置看起来: @Bean(name = "defContainer") public RabbitListenerContainerFactory containerFactory(ConnectionFactory connectionFactory, PlatformTransactionManager transactionManager){ SimpleRabbitListenerContainer

嗨,我的Rabbit侦听器有问题,它会导致无限循环异常(requeue消息)。我的配置看起来:

@Bean(name = "defContainer")
public RabbitListenerContainerFactory containerFactory(ConnectionFactory connectionFactory, PlatformTransactionManager transactionManager){
    SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory();
    containerFactory.setConnectionFactory(connectionFactory);
    containerFactory.setConcurrentConsumers(5);
    containerFactory.setAcknowledgeMode(AcknowledgeMode.AUTO);
    containerFactory.setTransactionManager(transactionManager);
    containerFactory.setMessageConverter(messageConverterAmqp());
    containerFactory.setDefaultRequeueRejected(false);

    return new TxRabbitListenerContainerFactory(containerFactory);
}
其中transactionManager是postgre db上事务的JpaTransactionManager。 TxRabbitListenerContainerFactory是我的工厂,它将setAlwaysRequeueWithTxManagerRollback设置为false:

public class TxRabbitListenerContainerFactory implements RabbitListenerContainerFactory {
private SimpleRabbitListenerContainerFactory factory;

public TxRabbitListenerContainerFactory(SimpleRabbitListenerContainerFactory factory) {
    this.factory = factory;
}

@Override
public MessageListenerContainer createListenerContainer(RabbitListenerEndpoint endpoint) {
    SimpleMessageListenerContainer container = factory.createListenerContainer(endpoint);
    container.setAlwaysRequeueWithTxManagerRollback(false);
    return container;
}
}

现在我有了listner,比如:

@RabbitListener(bindings = @QueueBinding(
        value = @Queue(value = "topic.two", durable = "true"),
        exchange = @Exchange(value = "topic.def", type = "topic", durable = "true"),
        key = "letter.*"
), errorHandler = "rabErrorHandler", containerFactory = "defContainer")
@Transactional
public Motorcycle topicLetters(Motorcycle motorcycle) throws Exception{
    motorcycle.setId(UUID.randomUUID().toString());
    Testing testing = new Testing();
    testingRepository.save(testing);
    throwEx();
    return motorcycle;
}
其中方法throwEx()抛出未检查的异常。 数据库中的数据已正确回滚(未提交),但消息会不断重新查询,请在侦听器中查看:

@Bean
public RabbitListenerErrorHandler rabErrorHandler(){
    return new RabbitListenerErrorHandler() {
        @Override
        public Object handleError(Message message, org.springframework.messaging.Message<?> message1, ListenerExecutionFailedException e) throws Exception {
            System.out.println("FFFFFFFFFFF");
            return null;
        }
    };
}
@Bean
公共RabbitListenerErrorHandler rabErrorHandler(){
返回新的RabbitListenerErrorHandler(){
@凌驾
公共对象handleError(Message Message,org.springframework.messaging.Message message1,ListenerExecutionFailedException e)引发异常{
System.out.println(“FFFFFFFFFFF”);
返回null;
}
};
}
如何预防无限循环,为什么会发生

编辑:


日志:

在容器工厂上将
defaultRequeueRejected
设置为
false

要以编程方式决定何时重新排队或不重新排队,请将其保留为
true
,并在不希望重新排队时抛出
AmqpRejectAndDontRequeueException

编辑

有点不对劲

protected void prepareHolderForRollback(RabbitResourceHolder resourceHolder, RuntimeException exception) {
    if (resourceHolder != null) {
        resourceHolder.setRequeueOnRollback(isAlwaysRequeueWithTxManagerRollback() ||
                RabbitUtils.shouldRequeue(isDefaultRequeueRejected(), exception, logger));
    }
}
如果两个布尔值都为false,则不重新求值。

发现问题:
原因:由侦听器级别上指定的errorHandler处理程序引起。在某些情况下,错误处理程序返回null-这会导致无限循环(而不是重新引发异常和回滚事务)

实际上我已经将containerFactory.setDefaultRequeueRejected(false);在工厂里。这就是为什么我不知道为什么它仍然是重播的原因。我还有一个修改过的工厂,它设置container.setAlwaysRequeueWithTxManagerRollback(false);在每个容器上,因为它需要设置,因为在这种情况下,tx被jpaTransactionManagerSorry抓取-错过了这一点;你用的是什么版本?能否附加显示循环的调试日志片段?另请参见我的编辑。