Spring amqp по умолчанию разрешает повтор и запрещает его в соответствии с указанным исключением - PullRequest
0 голосов
/ 19 апреля 2019

В случае исключения 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.

Ответы [ 2 ]

0 голосов
/ 20 апреля 2019

Мой модифицированный код:

/* 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 голосов
/ 19 апреля 2019
    exceptionsMap.put(AmqpRejectAndDontRequeueException.class, false);//not retriable
    exceptionsMap.put(ListenerExecutionFailedException.class, true); //retriable

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

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

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