SimpleRabbitListenerContainerFactory和defaultRequeueRejected

时间:2017-06-02 01:57:41

标签: spring-amqp

根据doc,defaultRequeueRejected的默认值为true,但查看代码似乎是错误的。我不确定我是否遗漏了任何东西,或者我们必须在SimpleRabbitListenerContainerFactory.java中更改它

修改

示例代码,在将消息放入测试队列后,我预计它会因为失败而保持在队列中,但它会将其丢弃。我希望重试消息,所以我在容器工厂配置它,如果它在重试后失败,我希望它回到队列中。我相信我在这里缺乏理解。

@SpringBootApplication
public class MsgRequeExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(MsgRequeExampleApplication.class, args);
    }

    @Bean(name = "myContainerFactory")
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        factory.setMissingQueuesFatal(false);

        FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
        backOffPolicy.setBackOffPeriod(500);
        factory.setAdviceChain(new Advice[] { org.springframework.amqp.rabbit.config.RetryInterceptorBuilder.stateless()
                .maxAttempts(2).backOffPolicy(backOffPolicy).build() });
        return factory;
    }

    @RabbitListener(queues = "test", containerFactory = "myContainerFactory")
    public void processAdvisory(Message message) throws MyBusinessException {
        try{
            //Simulating exception while processing message
            String nullString=null;
            nullString.length();
        }catch(Exception ex){
            throw new MyBusinessException(ex.getMessage());
        }
    }

    public class MyBusinessException extends Exception {
        public MyBusinessException(String msg) {
            super(msg);
        }
    }

}

1 个答案:

答案 0 :(得分:4)

SimpleMessageListenerContainer JavaDocs中有一个很好的描述:

/**
 * Set the default behavior when a message is rejected, for example because the listener
 * threw an exception. When true, messages will be requeued, when false, they will not. For
 * versions of Rabbit that support dead-lettering, the message must not be requeued in order
 * to be sent to the dead letter exchange. Setting to false causes all rejections to not
 * be requeued. When true, the default can be overridden by the listener throwing an
 * {@link AmqpRejectAndDontRequeueException}. Default true.
 * @param defaultRequeueRejected true to reject by default.
 */
public void setDefaultRequeueRejected(boolean defaultRequeueRejected) {
    this.defaultRequeueRejected = defaultRequeueRejected;
}

对你有意义吗?

<强>更新

要在重试耗尽后重新排队,您需要在MessageRecoverer上使用以下代码配置一些自定义RetryInterceptorBuilder

.recoverer((message, cause) -> {
        ReflectionUtils.rethrowRuntimeException(cause);
})

这样会将异常抛出到侦听器容器,并根据其defaultRequeueRejected消息将被重新排队。