How retry message in Rabbit MQ from client?

Viewed 2714

How to resend messages repeatedly after to others consumer reject message or not answer after some time? Excluding current consumer?

2 Answers

With RabbitMQ you can use Acknowledgements. Once a message is successfully processed your consumer would ACK (acknowledge) the message and the message would then be removed from the queue. If an error is triggered while processing the message you can have your consumer NACK (negative acknowledgment) the message.

You can configure your Rabbit broker to have a Dead Letter Queue (DLQ). Once a message is marked as NACK then the message would be moved to the DLQ. Furthermore, you can set the TTL (time to live) for messages in a specific queue. If a message has been in the queue for the length of the TTL then the message would be moved to the DLQ.

Callbacks is an answer

This method relies on the fact, that you will use some third party datastore.

With Sprint Boot AMQP (java), for example you should do the following

1. Create RabbitConfirmCallback

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;


@Component
public class RabbitConfirmCallback implements RabbitTemplate.ConfirmCallback {
    private static final Logger logger = LoggerFactory.getLogger(RabbitConfirmCallback.class);

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack && correlationData != null && correlationData.getId() != null) {
            logger.info("CorrelationData with id " + correlationData.getId() + " acknowledged;");

            // TODO Save to some Data Store information
            // that your data with this correlationData.getId()
            // wasn't successfulully delivered
            // and you must try to send it again
        } else {
            if (ack) {
                logger.warn("Unknown message acknowledgement received: " + correlationData);
            } else {
                logger.info("Broker didn't accept message: " + cause);
            }
        }
    }
}

This callback method confirm(...) will be triggered after the message is delivered: whether successful, or not.

2. Set this callback to RabbitTemplate

@Autowired
public void post(RabbitTemplate rabbitTemplate, RabbitConfirmCallback rabbitConfirmCallback){
    rabbitTemplate.setConfirmCallback(rabbitConfirmCallback);
}

3. Add the following property to your application.yaml

spring:
  rabbitmq:
    publisher-confirm-type: correlated

4. When sending messages, add CorrelationData

rabbitTemplate.convertAndSend(exchange, routingKey, message, new CorrelationData(dataId));

Where dataId can be your understandable-on-callback's-side identifier

With such a method, consider having some maxRetries setting, to not to start an infinite cycle

Related