Spring AMQP @RabbitListener自定义重试业务错误的最佳实践

时间:2017-03-28 14:22:26

标签: java spring spring-amqp

以下场景:我有一个@RabbitListener从RabbitMQ收到消息。有时,消息会遇到错误,因为我找不到相关的业务对象。在这种情况下,我无法回复发件人,所以我只想在一定量的重试后忽略此消息。

我的解决方案:在我的@RabbitListener中,只要找不到业务对象,我就会抛出自定义运行时异常。在我的配置中,我有RetryOperationsInterceptor最大尝试次数和自定义恢复者。

处理此类案件的最佳做法是什么?当有多个@RabbitListener时,我可以配置不同的recoverer类吗?

请参阅我的配置:

@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setMessageConverter(new CustomMessageConverter());
    factory.setConnectionFactory(connectionFactory());
    factory.setAcknowledgeMode(AcknowledgeMode.AUTO);
    factory.setConcurrentConsumers(1);
    factory.setMaxConcurrentConsumers(20);

    Advice[] adviceChain = new Advice[] { interceptor() };
    factory.setAdviceChain(adviceChain);
    return factory;
}

@Bean
RetryOperationsInterceptor interceptor() {
    return RetryInterceptorBuilder.stateless()
            .maxAttempts(5)
            .recoverer(new CustomRejectAndRecoverer())
            .build();
}

这是我的CustomRejectAndRecoverer

public class CustomRejectAndRecoverer implements MessageRecoverer {

    @Override
    public void recover(Message message, Throwable cause) {
        if (ExceptionUtils.getRootCause(cause) instanceof BusinessObjectNotFoundRuntimeException) {
            throw new ListenerExecutionFailedException("Retry Policy Exhausted",
                    new AmqpRejectAndDontRequeueException(cause), message);
        }
    }
}

2 个答案:

答案 0 :(得分:2)

您目前需要为每个不同的重试配置使用不同的容器工厂。

2.0中,我们为注释添加了一个新的errorHandler属性,因此每个侦听器都可以拥有一个自定义的错误处理程序,无论它是由哪个容器工厂创建的。

这是在first milestone release;目前的里程碑是M2,M3即将推出。 GA预计将于6月发布。

答案 1 :(得分:0)

如果共享SimpleRabbitListenerContainerFactory中的常见逻辑不符合您对特定@RabbitListener的要求,则必须使用这些自定义选项声明一个新选项,例如关于此事的新MessageRecoverer

为此目的,@RabbitListener具有属性:

/**
 * The bean name of the {@link org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory}
 * to use to create the message listener container responsible to serve this endpoint.
 * <p>If not specified, the default container factory is used, if any.
 * @return the {@link org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory}
 * bean name.
 */
String containerFactory() default "";