以下场景:我有一个@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);
}
}
}
答案 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 "";