spring - 设置最大 AMQP 客户端尝试次数
问题描述
我有一个案例,我可能将 Java NPE 放入接受队列有效负载的侦听器中。我得到了多次尝试和错误:
18:41:50.549 [processingeContainer-1] WARN o.s.a.r.l.ConditionalRejectingErrorHandler - Execution of Rabbit message listener failed.
2019-09-24 18:41:50,551 INFO [stdout] (processingContainer-1) org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener method 'transactionProcess' threw exception
有什么方法可以限制 AMQP 客户端尝试吗?
解决方案
您确实应该修复 NPE,但您可以配置侦听器容器错误处理程序。
默认ConditionalRejectingErrorHandler
将某些异常视为致命异常。
它使用DefaultExceptionStrategy
具有以下代码的 a:
private boolean isCauseFatal(Throwable cause) {
return cause instanceof MessageConversionException // NOSONAR boolean complexity
|| cause instanceof org.springframework.messaging.converter.MessageConversionException
|| cause instanceof MethodArgumentResolutionException
|| cause instanceof NoSuchMethodException
|| cause instanceof ClassCastException
|| isUserCauseFatal(cause);
}
/**
* Subclasses can override this to add custom exceptions.
* @param cause the cause
* @return true if the cause is fatal.
*/
protected boolean isUserCauseFatal(Throwable cause) {
return false;
}
因此,使用覆盖返回 trueConditionalRejectingErrorHandler
的子类配置您自己的。DefaultExceptionStrategy
isUserCauseFatal()
NullPointerException
然后,您将错误处理程序注入侦听器容器或侦听器容器工厂。
另一种技术是添加重试拦截器;默认情况下,仅在重试用尽后记录错误。使用 Spring Boot,默认恢复器是RejectAndDontRequeueRecoverer
.
编辑
我刚刚测试了它,它工作得很好......
@SpringBootApplication
public class So58087354Application {
public static void main(String[] args) {
SpringApplication.run(So58087354Application.class, args);
}
@RabbitListener(queues = "foo")
public void listen(String in) {
System.out.println("here");
throw new NullPointerException("Test");
}
}
spring.rabbitmq.listener.simple.retry.enabled=true
spring.rabbitmq.listener.simple.retry.initial-interval=1000ms
spring.rabbitmq.listener.simple.retry.max-attempts=2
和
here
here
2019-10-01 09:07:11.936 WARN 75435 --- [ntContainer#0-1] o.s.a.r.r.RejectAndDontRequeueRecoverer : Retries exhausted for message (Body:'[B@6d890bbc(byte[3])' MessageProperties [headers={}, contentLength=0, receivedDeliveryMode=NON_PERSISTENT, redelivered=false, receivedExchange=, receivedRoutingKey=foo, deliveryTag=1, consumerTag=amq.ctag-mwYtmPtBplrefsOa05hG0w, consumerQueue=foo])
...
2019-10-01 09:07:11.937 WARN 75435 --- [ntContainer#0-1] s.a.r.l.ConditionalRejectingErrorHandler : Execution of Rabbit message listener failed.
...
Caused by: org.springframework.amqp.AmqpRejectAndDontRequeueException: null
... 19 common frames omitted
编辑2
要手动向容器工厂添加重试建议...
@Component
class ContainerRetryConfigurer {
ContainerRetryConfigurer(AbstractRabbitListenerContainerFactory<?> factory) {
factory.setAdviceChain(RetryInterceptorBuilder.stateless()
.maxAttempts(2)
.backOffOptions(1000, 1.0, 1000)
.build());
}
}