Search code examples
javaspringrabbitmqamqpspring-amqp

Handling undeliverable messages to consumers in Spring AMQP


Here is a situation where in a message refuses to deliver itself to the consumer due to improper handling by the client and therefore this message bounces infinitely between the server and the client resulting into continuous stream of log messages which fills up the disk space.

How to avoid this situation? Or in other words how to restrict the retry to a limited number of times?

I tried retry template with rabbit template but with no success. Please find the configuration below:

<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" reply-timeout="10" retry-template="retryTemplate"/>

<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
<property name="backOffPolicy">
    <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
        <property name="initialInterval" value="500" />
        <property name="multiplier" value="10.0" />
        <property name="maxInterval" value="10000" />
    </bean>
</property>
</bean>

I referred this article for my problem: Handling AMQP messages gracefully with spring-amqp


Solution

  • Using a retry template with a rabbit template is for retrying publishing messages and has nothing to do with consuming (unless you are using template.receive().

    To add retry and abort to the listener container, see the documentation. You need to add a retry interceptor to the listener container's advice chain; if your messages don't have a message id, you have to use stateless retry because the framework needs to know how many times a message has been retried and amqp doesn't provide that information.

    See the discussion about what to do when the retries are exhausted. By default the message is just logged and dropped but you can configure an appropriate recoverer. An RejectAndDontRequeueRecoverer will reject it and rabbit can be configured to send the message to a dead letter exchange/queue. Or you can use a RepublishMessageRecoverer to write the message to another queue, including information about the failure.

    See this question/answer for an example. But note that using stateful recovery with a random message ID won't work.