如何使用amqp StatefulRetryOperationsInterceptor

时间:2018-09-28 13:25:01

标签: amqp spring-amqp

我尝试像这样在mycode中使用StatefulRetryOperationsInterceptor:

@Bean
public StatefulRetryOperationsInterceptor statefulRetryOperationsInterceptor(){
   return RetryInterceptorBuilder.stateful()
          .maxAttempts(5)
          .backOffOptions(1000,2.0,10000)
          .build();
}

 @Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
    logger.info("==> custom rabbitmq Listener factory:"+ connectionFactory);
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setConcurrentConsumers(3);
    factory.setMaxConcurrentConsumers(10);
    factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    factory.setPrefetchCount(200);
    factory.setAdviceChan(new Advice[]{
       statefulRetryOperationsInterceptor()
    })  //add retry
    return factory;
}

我的代码运行良好,但是当使用者中有异常时,根本不会重试。 那么如何使用StatefulRetryOperationsInterceptor?该类用于捕获异常并重新发送吗?

如果发生Exception,我想重新排队并再次发送给消费者5次,然后将消息发送到死队列,如何更优雅地使用amqp?


根据@Gary Russell的回答,我使用redis记录异常,是否有像StatefulRetryOperationsInterceptor这样的方法可以使操作更优雅?

try {
     receiveMessage(message);
    channel.basicAck(deliveryTag, false);           
    redisTemplate.opsForHash().delete(MQConstants.MQ_CONSUMER_RETRY_COUNT_KEY, messageProperties.getMessageId());
        } 
 catch (Exception e) {     
            if (consumerCount >= MQConstants.MAX_CONSUMER_COUNT) {         
                channel.basicReject(deliveryTag, false);
            } else {
               redisTemplate.opsForHash().increment(MQConstants.MQ_CONSUMER_RETRY_COUNT_KEY,
                        messageProperties.getMessageId(), 1);
                Thread.sleep((long) (Math.pow(MQConstants.BASE_NUM, consumerCount)*1000));
                channel.basicNack(deliveryTag, false, true);
            }
        }

1 个答案:

答案 0 :(得分:1)

  

factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);

由于您使用的是手动挡板,因此您可以自己操作;容器无法帮助您。您需要对状态重试使用AUTO或使用channel.basicReject()进行重新排队。