Spring Boot RabbitMQ死信队列在异常发生时未停止流程。

huangapple go评论88阅读模式
英文:

Spring boot rabbitmq dead queue not stopping flow on exception

问题

I am learning Spring Boot (version 2.2.5.RELEASE) with RabbitMQ based on online resources. The issue I am facing is that when purposely throwing an exception, it should retry only 6 times. However, the message keeps retrying without stopping. Below is my application.yml configuration:

server:
  servlet:
    contextPath: /test

spring:
  rabbitmq:
    username: guest
    password: guest
    listener:
      simple:
        retry:
          enabled: true
          initial-interval: 3s
          max-attempts: 6
          max-interval: 10s
          multiplier: 2

Here is the RabbitMQ configuration class:

@Configuration
public class RabbitMQConfig {

    @Bean
    TopicExchange deadLetterExchange() {
        return new TopicExchange("deadLetterExchange");
    }

    // Other beans...

    @Bean
    SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames("javainuse.queue");
        container.setMessageListener(listenerAdapter);
        return container;
    }

    @Bean
    MessageListenerAdapter listenerAdapter(ReceiveMessageHandler receiver) {
        return new MessageListenerAdapter(receiver, "handleMessage");
    }

}

And here is the class that consumes the message:

@Component
@Slf4j
@RequiredArgsConstructor
public class ReceiveMessageHandler {

    private final SendService sendService;

    public void handleMessage(@Valid dto dto) {

        String test = null;

        // Purposely throw null pointer to test dead queue
        test.toString();

        sendService.sendSomething(dto);

    }
}

Despite configuring max-attempts: 6 in the application.yml, the null pointer exception keeps retrying beyond 6 times. Could someone help me identify what I'm missing here, please?

英文:

I am learning spring boot (version 2.2.5.RELEASE) with RabbitMQ based on online resources:

The issue I am experiencing is that when I am throwing purposely an exception, it should retry only 6 times and after that the message should be moved to the dead queue but it is not the case as it keeps retrying without stopping.

Please find below my application.yml:

server:
  servlet:
    contextPath: /test

spring:
  rabbitmq:
    username: guest
    password: guest
    listener:
      simple:
        retry:
          enabled: true
          initial-interval: 3s
          max-attempts: 6
          max-interval: 10s
          multiplier: 2

Please find below rabbitMQ configuration class:

@Configuration
public class RabbitMQConfig {

 
    @Bean
    TopicExchange deadLetterExchange() {
        return new TopicExchange("deadLetterExchange");
    }

    @Bean
    TopicExchange exchange() {
        return new TopicExchange("javainuseExchange");
    }

    @Bean
    Queue dlq() {
        return QueueBuilder.durable("deadLetter.queue").build();
    }

    @Bean
    Queue queue() {
        return QueueBuilder.durable("javainuse.queue").withArgument("x-dead-letter-exchange", "deadLetterExchange")
                .withArgument("x-dead-letter-routing-key", "deadLetter").build();
    }

    @Bean
    Binding DLQbinding() {
        return BindingBuilder.bind(dlq()).to(deadLetterExchange()).with("deadLetter");
    }

    @Bean
    Binding binding() {
        return BindingBuilder.bind(queue()).to(exchange()).with("javainuse");
    }

    @Bean
    SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames("javainuse.queue");
        container.setMessageListener(listenerAdapter);
        return container;
    }

    @Bean
    MessageListenerAdapter listenerAdapter(ReceiveMessageHandler receiver) {
        return new MessageListenerAdapter(receiver, "handleMessage");
    }

}

Please find below my class that consume the message:

@Component
@Slf4j
@RequiredArgsConstructor
public class ReceiveMessageHandler {

   
    private final SendService sendService;

    public void handleMessage(@Valid dto dto) {

        String test = null;

      
        //purposely throw null pointer to test dead queue
        test.toString();

        sendService.sendSomething(dto);
   
    }

When the null pointer exception is thrown it keeps retrying instead of stopping after 6 times max-attempts: 6 as per application.yml config.

Can anyone point me what I am missing here, please?

答案1

得分: 2

你正在创建自己的容器 bean,因此.yml属性未被应用。使用RetryInterceptorBuilder.stateless()...来构建重试建议并将其注入到监听器容器(建议链)中。

您还需要配置恢复器。

builder.recoverer(new RejectAndDontRequeueRecoverer());

这将在重试用尽时将队列指向死信队列(DLQ)。

请参阅Spring AMQP 文档

英文:

You are creating your own container bean so the .yml properties are not being applied. Use a RetryInterceptorBuilder.stateless() ... to build the retry advice and inject it into the listener container (advice chain).

You also need to configure the recoverer.

builder.recoverer(new RejectAndDontRequeueRecoverer());

Which will direct the queue to the DLQ when retries are exhausted.

See the Spring AMQP documentation.

huangapple
  • 本文由 发表于 2020年8月13日 14:55:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63389684.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定