logo le blog invivoo blanc

Introduction à RabbitMQ

11 avril 2023 | Java | 0 comments

Les micro-services, très répandus ces dernières années, ont dominé les structures et développement des applications et logiciels. Une méthode qui permet le développement des applications comme des services modulables et indépendants. Chacun de ces services exécute un processus unique qui est capable d’être déployé, testé et modifié d’une manière indépendante des autres micro-services. Et finalement, ces derniers doivent pouvoir communiquer avec les autres services grâce à un mécanisme qui assure l’arrivée et l’intégrité des données échangées entre les micro-services.

En effet, assurer une communication robuste et optimisée est une priorité pour cette architecture. En revanche, les méthodes traditionnelles, telles que Restful API et protocol SOAP au fil du temps, présentent des lacunes qui prouvent leur incapacité à gérer le rythme des flux importants des données échangées entre les services. Par exemple, les appels REST API reposent sur la communication synchrone et directe entre les micro services. Ce qui peut engendrer dans certains cas, la perte des données envoyées lorsqu’un micro-service est occupé ou non fonctionnel. Ces lacunes peuvent être comblées par les « message queuing » tel que RabbitMQ.

1. Protocol AMQP :

AMQP (Advanced Message Queuing Protocol) est un protocole open source publié pour la transmission des messages asynchrones. Cet intermédiaire de messagerie permet aux services d’envoyer et de recevoir des messages. Le courtier de messages est hébergé séparément et fonctionne indépendamment du micro-service.

Architecture AMQP

2. RabbitMQ

C’est un logiciel qui implémenté le protocole AMQP et, également connu sous le nom de «Message Broker», il permet de gérer la mise en file d’attente (queues) des messages. Les micro-services se connectent au message broker pour envoyer et recevoir un ou plusieurs messages à travers des publicateurs de messages, des files d’attentes et des consommateurs de messages.

RabbitMQ repose sur trois composants principaux i.e échanges (Exchanges), file d’attente (Queues) et liaisons (Bindings).

Un micro-service A qui souhaite envoyer un message est un producteur de message (Publisher). Le micro-service B qui reçoit le message est un consommateur (Consumer). Quand un message est émis par micro-service A, il est stocké dans un échange (Exchange) dans RabbitMQ qui permet une meilleure gestion du routage du message, selon les liaisons (Binding), qui permettent de savoir vers où acheminer le contenu du message grâce à une clé de routage (Routing Key). Le message est acheminé vers la file d’attente (Queue) qui est définie dans le micro-service B pour écouter les messages provenant du micro-service A.

Il existe trois types d’Exchange qui émettent des messages :

  • Direct exchange :

Un message est dirigé d’un exchange vers une queue avec les mêmes exactes Routing key

  • Fanout exchange :

Un message sera envoyé à toutes les queues liées par un binding vers l’Exchange en ignorant le routing key.

  • Topic exchange :

Un message est envoyé d’un exchange vers toutes les queues liées par un pattern de routing key. Exemple : si Exchange A avec routing key message.Send.* souhaite envoyer un message vers queue B avec routing key  message.Send.B, queue C avec routing key message.Send.C et queue D avec routing key message.D. Le message sera envoyé aux queues B et C mais pas au D car il ne suit pas le pattern du routing key.

3. RabbitMQ VS Restful APIs :

  • RabbitMQ offre une communication asynchrone qui permet au consommateur de lire le message dès qu’il est fonctionnel et disponible. Les messages ne seront pas perdus grâce au système de souscription qui permet aux queues d’écouter sur un exchange et consomment les messages qui arrivent.
  • REST API est synchrone et en cas de non disponibilité du service qui reçoit les informations, les données sont perdues.
  • On peut définir une durée de vie pour chaque queue pour limiter ou étendre la durée d’écoute des messages selon le besoin.
  • Avec plusieurs requêtes concurrentes, REST API ne gère pas l’affluence des données.
  • RabbitMQ ne requiert pas des informations sur le micro-service qui recevra les le message (indépendant du language de programmation utilisé).

Exemple RabbitMQ :

RabbitMQ peut être intégré dans les projets SpringBoot à travers la dépendance spring-amqp. Il faut ajouter une instance de RabbitMQ  pour interagir avec RabbitMQ. RabbitMQ utilise le port 5672 pour les applications et pour la connexion à l’interface de Rabbit il faut utiliser le port 15672.

RabbitMQ utilise la dépendance de Springboot AMQP qui permet d’accéder à la librairie de rabbit template :

<dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

Prenons l’exemple d’un utilisateur de type User, qu’on souhaite modifier.

Tout d’abord, il est nécessaire de déclarer toutes les queues, exchanges et routing-keys dans la classe dédiée à la configuration avec l’annotation @Configuration.

@Configuration
public class RabbitMQConfig {
    @Bean
    Queue queue() {
                 return new Queue(“user-update-queue”, false);
    }
    @Bean
    TopicExchange exchange() {
                 return new TopicExchange(“user-update-exchange”);
     }
    @Bean
    Binding binding(Queue queue, TopicExchange exchange)     {
                 return BindingBuilder.bind(“user-update-queue”).to(“user-update-exchange”).with(“user-update.routingkey”);
    }
   @Bean
   public MessageConverter jsonMessageConverter() {
                 return new Jackson2JsonMessageConverter();
   }
   @Bean
   public AmqpTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
                 final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
                 rabbitTemplate.setMessageConverter(jsonMessageConverter());
                 return rabbitTemplate;
   }
}

Il suffit de créer des Beans qui renvoient un objet Queue, TopicExchange (pour le type Topic des échanges )  contenant le nom des objets.

Le binding permet de faire le routage entre l’échange “user-update-exchange” et la queue “user-update-queue” à travers le routing-key “user-update.routingkey”.

Afin de pouvoir modifier l’utilisateur, on lance un évènement à travers un Controller qui permet d’envoyer le payload UserUpdateRequest de l’échange vers la queue. Le message est envoyé grâce à la méthode de RabbitTemplate convertAndSend.

@RestController
@RequestMapping(value = "/api”,produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public class RabbitController {
                 @Autowired
                 UserUpdateService userUpdateService;
                 @PostMapping(value = "/user ")
                 public ApiResponse updateUser(@RequestBody UserUpdateRequest userUpdateRequest) {
                      rabbitTemplate.convertAndSend(“user-update-exchange”, “user-routing-key”, userUpdateRequest)
                 }
}

On peut toujours vérifier la bonne réception du message sur la queue “user-update-queue” avec le @RabbitListener qui écoute sur la queue et dès qu’un message est détecté, il lance la méthodeonUserUpdate.

@Service
public class UserUpdateService{
   @RabbitListener(queues = {"user-update-queue"})
     public void onUserUpdate(UserUpdateRequest event) {
                  log.info("Modification utilisateur reçue: {}", event);
                  System.out.println(“notification : l’utilisateur a été modifié “);
     }
}

Conclusion :

RabbitMQ offre une solution robuste pour gérer la bonne communication et assurer le bon acheminement des données entre les micros-services. L’envoi asynchrone des données assure leur sécurité jusqu’à réception par le consommateur du message indépendamment de la disponibilité immédiate de receveur du message. Cet atout favorise le messaging asynchrone contrairement à Rest API qui ne garantit pas ces avantages.

Références :

https://www.irjet.net/archives/V7/i5/IRJET-V7I5893.pdf

https://medium.com/swlh/a-quick-guide-to-understanding-rabbitmq-amqp-ba25fdfe421d

https://docs.spring.io/spring-amqp/reference/html/#amqp

https://medium.com/javarevisited/getting-started-with-rabbitmq-in-spring-boot-6323b9179247#:~:text=Set%20up%20RabbitMQ&text=Open%20your%20browser%20and%20hit,now%20it%20should%20be%20fine.

https://www.javainuse.com/spring/spring-boot-rabbitmq-hello-world

https://www.tutorialspoint.com/rabbitmq/index.htm#

https://www.rabbitmq.com/tutorials/tutorial-one-java.html

https://solace.com/blog/experience-awesomeness-event-driven-microservices/

https://medium.com/capital-one-tech/choosing-between-rest-web-apis-and-message-streaming-8e2f4813a058#:~:text=REST%20APIs%20are%20best%20suited,want%20to%20take%20action%20upon.