RabbitMQ no longer loses message with the use of Alternate Exchange and fanout

Posting a message in RabbitMQ is very easy, unfortunately RabbitMQ does not provide any feedback on the success or failure of the delivery in a queue. A simple typo in the routing key and the message will be lost forever without being informed. The Alternate Exchange option allows you to retrieves these "lost" messages in a specific queue.

1. Idea

An Exchange of type fanout in RabbitMQ delivers all messages to every queues binded to him. We will use this type of exchange with only one queue binded. Then we add aternate-exchange option in Exchange declaration to let RabbitMQ post all messages that can't be deliver to a queue in the original exchange to this fanout exchange.

2. Declaration of the fanout echange and his queue

We are declaring an exchange of type fanout. We use the same name "unroutable" for exchange and queue. Queue are binding to the exchange without routing key, they are not needed with fanout exchange.

créer l'exchange fanout unroutable

créer la queue unroutable

binder la queue et l'exchange

We can use rabbitmqadmin cli tool to declare this configuration. You can get this tool from your RabbitMQ instance if you had installed administration plugin by going to this uri http://<domain>:15672/cli/rabbitmqadmin

$ ./rabbitmqadmin --vhost=collector declare exchange \
> name=unroutable type=fanout durable=true
$ ./rabbitmqadmin --vhost=collector declare queue \
> name=unroutable durable=true
$ ./rabbitmqadmin --vhost=collector declare binding \
> source=unroutable destination=unroutable

3. Use of alternate-exchange option

We need to use alternate-exchange option when creating new exchange if we want RabbitMQ to post messages he can't deliver into unroutable exchange.

utilisation de l'option alternate-exchange

$ ./rabbitmqadmin --vhost=collector declare exchange \
> name=collector type=direct durable=true \
> arguments='{"alternate-exchange": "unroutable"}'

The problem here is that we set the option "alternate-exchange" when creating the exchange and it is not possible to change the options of an exchange already created in RabbitMQ. So there is the solution to remove the exchange and re-create it but it involves stopping the publisher during maintenance and redo all bindings queue attached to this exchange. Suddenly it's a little less sexy and even if we script this change through the command line, the task will be laborious.

There is another solution, to apply an alternate-exchange to existing exchanges, it is use of "Policies" in RabbitMQ. A policiy is a rule applied to an exchange, a queue or both. It allows to add most of the options available when creating exchanges and queues on already existing elements.

configuration de la policy

$ ./rabbitmqadmin --vhost=collector declare policy \
> name=AE pattern=collector apply-to=exchanges \
> definition='{"alternate-exchange": "unroutable"}'

There you go! Now all the posts published in the "collector" exchange that will not be deliver to queues will be sent in the "unroutable" exchange and will end up in the "unroutable" queue. It only remains to monitor that this queue is always empty.

Add a comment