【发布时间】:2018-10-20 00:17:42
【问题描述】:
您好,如果抛出特定异常,我正在尝试重新排队某些消息,但对于任何验证失败,我希望它们直接进入死信队列。我启用了相关的队列和死信队列。我发现我的验证失败已到达 dlq,但其他失败一直处于 unack 状态并不断重试,超出了我设置的最大尝试次数和乘数,有什么想法吗?下面的代码我使用的是 Spring boot 2.0.4 版本
@RabbitListener(queues = "${queuename}")
public void consume(final @Valid @Payload MyRequest myRequest) {
if (method.fail()) {
throw new RuntimeException("");
}
}
@Bean
public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
factory.setMessageConverter(jackson2Converter());
factory.setValidator(amqpValidator());
return factory;
}
@Override
public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
registrar.setMessageHandlerMethodFactory(myHandlerMethodFactory());
}
@Bean
public Validator amqpValidator() {
return new OptionalValidatorFactoryBean();
}
@Bean
public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory listenerContainerFactory =
new SimpleRabbitListenerContainerFactory();
listenerContainerFactory.setConnectionFactory(connectionFactory());
listenerContainerFactory.setErrorHandler(new ConditionalRejectingErrorHandler(
new MyErrorPayload()));
listenerContainerFactory.setMessageConverter(jackson2JsonMessageConverter());
return listenerContainerFactory;
}
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(rabbitQueueHost);
connectionFactory.setUsername(rabbitQueueUsername);
connectionFactory.setPassword(rabbitQueuePassword);
connectionFactory.setVirtualHost(rabbitQueueVirtualHost);
return connectionFactory;
}
public class MyErrorPayload implements FatalExceptionStrategy {
@Override
public boolean isFatal(Throwable t) {
if (t instanceof ListenerExecutionFailedException &&
(t.getCause() instanceof MessageConversionException ||
t.getCause() instanceof MethodArgumentNotValidException )
) {
return true;
}
return false;
}
}
application.yml(属性)
spring:
rabbitmq:
host: localhost
username: uu
password: pp
virtual-host: /
listener:
simple:
default-requeue-rejected: false
retry:
enabled: true
initial-interval: 2000
multiplier: 1.5
max-interval: 10000
max-attempts: 3
【问题讨论】:
-
我认为存在两个不同的侦听器容器。你调试发现哪个容器调用了 isFatal ?
-
开启调试日志以观察重试活动。如果您无法从中弄清楚,请将日志发布到某个地方。
-
@GaryRussell 我可以通过在侦听器方法中抛出 RuntimeException 并复制上面的 application.yml 来重现此示例 global-handler 的问题。你能检查一下吗?
-
@Barath,感谢您指向该示例;看我的回答。
标签: spring spring-boot rabbitmq amqp spring-amqp