В случае исключения A: повторная попытка в течение конечного числа раз и, наконец, когда количество повторных попыток исчерпано, сообщение записывается в очередь недоставленных сообщений

В случае исключения B: просто, сообщение должно быть записано в очередь недоставленных сообщений

Я пытаюсь реализовать тот же вариант использования, что и в, и я выполнил все шаги в соответствии с правильным ответом, тем не менее, я вижу свое пользовательское исключение, заключенное в ListenerExecutionFailedException. Я не могу заставить его прекратить повторять пользовательское исключение.

Я следовал инструкциям ниже ответов spring amqp разрешить повторную попытку по конфигурации и предотвратить ее согласно указанному исключению

А также

Весенний кролик пытается доставить отклоненное сообщение. Это нормально?


@Bean
    public SimpleRetryPolicy rejectionRetryPolicy(){
        Map<Class<? extends Throwable> , Boolean> exceptionsMap = new HashMap<Class<? extends Throwable> , Boolean>();        
        exceptionsMap.put(AmqpRejectAndDontRequeueException.class, false);//not retriable
        exceptionsMap.put(ListenerExecutionFailedException.class, true); //retriable
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3 , exceptionsMap ,true);
        return retryPolicy;
    }

    @Bean
    public RetryOperationsInterceptor workMessagesRetryInterceptor() {
        return RetryInterceptorBuilder.stateless().retryPolicy(rejectionRetryPolicy())

                //.backOffOptions(1000, 2, 10000)
                .recoverer(new RepublishMessageRecoverer(defaultTemplate, this.getDlqExchange(), this.getDlqroutingkey()))
                .build();
    }


/* My Rabbit MQ Error handler */

@Component
public class RabbitRetryHandler implements RabbitListenerErrorHandler {

    private static final Logger log = LoggerFactory.getLogger(RabbitRetryHandler.class);

    @Override
    public Object handleError(Message amqpMessage, org.springframework.messaging.Message<?> message,
            ListenerExecutionFailedException exception) throws Exception {      
        if (amqpMessage.getMessageProperties().isRedelivered() || exception.getCause().getMessage().equals("DontRetry")) {          
            throw new AmqpRejectAndDontRequeueException(exception.getCause());
        } else {
            throw exception;
        }
    }
}

/* And finally my Listener */

@Override
    @RabbitListener(queues = "${queueconfig.queuename}",containerFactory = "sdRabbitListenerContainerFactory",errorHandler="rabbitRetryHandler")
    public void processMessage(Message incomingMsg) throws Exception {
        log.info("{} - Correlation ID: {} Received message: {} from {} queue.", Thread.currentThread().getId(),
                incomingMsg.getMessageProperties().getCorrelationId(), new String(incomingMsg.getBody()),
                incomingMsg.getMessageProperties().getConsumerQueue());
        try {
            performAction();
        } catch(CustomDontRequeueException cex) {
            throw cex;
        } catch (Exception ex) {
            throw ex;
        }
    }


@Override
    public void performAction() throws Exception {
        try {

        } catch (HttpClientErrorException ex) {
            if (ex.getStatusCode() == HttpStatus.NOT_FOUND || ex.getStatusCode() == HttpStatus.REQUEST_TIMEOUT) {

                throw new RuntimeException(ex);
            } else {
                throw new CustomDontRequeueException("DontRetry",ex);
            }
        }catch (Exception e) {          
            throw new CustomDontRequeueException(e);
        } 

    }

Ожидаемый результат: если выброшено исключение CustomDontRequeueException, оно не должно повторно запрашивать сообщение.

Фактический результат, сообщение попадает в очередь независимо от того, какое исключение оно составляет n раз, а затем сбрасывается в DLQ.

0
Naveen Kumar Pandian 19 Апр 2019 в 10:34

2 ответа

Лучший ответ
    exceptionsMap.put(AmqpRejectAndDontRequeueException.class, false);//not retriable
    exceptionsMap.put(ListenerExecutionFailedException.class, true); //retriable

Вы не настроили CustomDontRequeueException, чтобы не повторять попытку, вы настроили AmqpRejectAndDontRequeueException.

Кроме того, вы не должны явно устанавливать ListenerExecutionFailedException, потому что он будет найден первым, предотвращая обход причины.

0
Gary Russell 19 Апр 2019 в 13:49

Мой измененный код:

/* Kept 2 different custom exceptions one for retry and one for not retry*/
    @Bean
    public SimpleRetryPolicy rejectionRetryPolicy(){
        Map<Class<? extends Throwable> , Boolean> exceptionsMap = new HashMap<Class<? extends Throwable> , Boolean>();        
        exceptionsMap.put(CustomDontRequeueException.class, false);//not retriable
        exceptionsMap.put(CustomRequeueException.class, true);//retriable
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3 , exceptionsMap ,true);
        return retryPolicy;
    }

    @Bean
    public RetryOperationsInterceptor workMessagesRetryInterceptor() {
        return RetryInterceptorBuilder.stateless().retryPolicy(rejectionRetryPolicy())
                .backOffPolicy(exponentialBackOffPolicy)
                .recoverer(new RepublishMessageRecoverer(defaultTemplate, this.getDlqExchange(), this.getDlqroutingkey()))
                .build();
    }

/* Listener --- removed error handler*/
@Override
    @RabbitListener(queues = "${queueconfig.signdocuments.queuename}",containerFactory = "asdrabbitListenerContainerFactory")
    public void processMessage(Message incomingMsg) throws Exception {      
        try {
            performAction();
        } catch(CustomDontRequeueException cex) {
            throw cex;
        } catch (Exception ex) {
            throw ex;
        }
    }

/* Action which throws custom exceptions depending on what exceptions they get*/

@Override
    public void performAction() throws Exception {
        try {

        } catch (HttpClientErrorException ex) {
            if (ex.getStatusCode() == HttpStatus.NOT_FOUND || ex.getStatusCode() == HttpStatus.REQUEST_TIMEOUT) {               
                throw new CustomRequeueException("Retry",ex);
            } else {                
                throw new CustomDontRequeueException("DontRetry",ex);
            }
        }catch (Exception e) {
            throw new CustomDontRequeueException("DontRetry",e);
        }       
    }
0
Naveen Kumar Pandian 19 Апр 2019 в 21:00