RabbitMQ ne plus perdre de message avec l'utilisation d'Alternate Exchange et fanout

Publier un message dans RabbitMQ est très facile, malheureusement RabbitMQ ne fournit en retour aucune information sur la réussite ou non de la publication dans une queue. Une simple faute de frappe dans la routing key et le message sera perdu à jamais sans pouvoir en être informé. L'option Alternate Exchange permet de récupérer les messages dans une queue spécifique.

1. Principe

Un exchange de type fanout dans RabbitMQ à la particularité de transmettre tous les messages qu'il reçoit dans toutes les queues qu'il connait. On va donc utilister ce type d'exchange en lui attachant une seule queue. Ensuite on utilisera l'option "alternate-exchange" sur les exchanges de notre application pour que tout les messages qui ne sont pas distribués dans des queues attérissent dans notre fanout.

2. Création de l'exchange fanout et de sa queue

On va donc créer un exchange fanout que l'on va nommer "unroutable" et une queue avec le même nom que l'on va "binder" sans définir de routing key.

créer l'exchange fanout unroutable

créer la queue unroutable

binder la queue et l'exchange

On peut également déclarer la configuration avec l'outil rabbitmqadmin en ligne de commande. Il peut être télécharger depuis le plugin d'administration s'il est installé depuis l'url 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. Utilisation de l'option alternate-exchange

On va donc utiliser l'option alternate-exchange sur un exchange de notre application pour que tous les messages qui ne sont pas délivrés dans des queues soient envoyés à notre exchange unroutable.

utilisation de l'option alternate-exchange


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


Le problème ici, c'est qu'on définis l'option "alternate-exchange" lors de la création de l'exchange et il n'est pas possible de modifier les options d'un exchange déjà créé dans RabbitMQ. Il y a donc la solution de supprimer l'exchange et de le re-créer mais ça implique d'arrêter les publisher pendant la maintenance et de refaire  tous les bindings des queues attachées à cet exchange. D'un coup c'est un peu moins sexy et même si l'on scripte cette modification en passant par la ligne de commande, la tâche sera laborieuse.

Il existe une solution, pour appliquer un alternate-exchange à des exchanges déjà existant, c'est l'utilisation des "Policies" dans RabbitMQ. Une policiy est une régle appliquée à un exchange, une queue ou les deux. Elle permet d'ajouter après coup, la plus part des options disponibles lors de la création des exchanges et des queues sur des éléments déjà existant.

configuration de la policy


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


Et voilà! Maintenant tous les messages publiés dans l'exchange "collector" qui ne seront pas mis dans des queues seront envoyés dans l'exchange "unroutable" et finiront dans la queue "unroutable". Il ne reste plus qu'à surveiller que cette queue reste toujours vide.

Ajouter un commentaire