@Transactional兔子监听器导致无限循环

时间:2018-01-22 20:20:39

标签: spring rabbitmq spring-rabbit

嗨我的Rabbit监听器有问题导致异常无限循环(重新排队消息)。我的配置看起来:

@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;
}

}

现在我有了以下列表:

@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(); 抛出未经检查的异常。 来自DB的数据被正确地回滚(未提交),但是消息不断被重新排队,在监听器中看到它:

@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;
        }
    };
}

如何克服无限的loope,为什么会这样?

修改

日志:pasted logs

2 个答案:

答案 0 :(得分:1)

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

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

修改

有些东西没有加起来......

protected void prepareHolderForRollback(RabbitResourceHolder resourceHolder, RuntimeException exception) {
    if (resourceHolder != null) {
        resourceHolder.setRequeueOnRollback(isAlwaysRequeueWithTxManagerRollback() ||
                RabbitUtils.shouldRequeue(isDefaultRequeueRejected(), exception, logger));
    }
}

如果两个布尔都是假的,我们就不会重新排队。

答案 1 :(得分:0)

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