Quand utiliser une API REST ou un message sur un bus d’événements ?
A ma grande surprise, on me pose régulièrement la question de quand utiliser une API REST ou un message sur un bus d’événements. Alors que la réponse semble évidente, je me dois de mettre ma casquette d’architecte et de répondre : ça dépend !
Sommaire
Définitions
Avant de continuer, il est préférable de préciser ce que l’on entend par une API REST et un message sur bus d’événements.
Tout d’abord, une API REST est un Web Service respectant les principes REST définis par Roy Fielding. Dit plus simplement, elle utilise le protocole HTTP et les fonctionnalités offertes pour proposer un standard d’utilisation. Le mode de communication entre l’appelant et l’appelé est par défaut synchrone.
Pour faciliter cet article, je définis un message d’événement comme le mode de communication asynchrone entre deux systèmes ne se connaissant pas et dialoguant au travers d’un Message-oriented Middleware (MoM). On ne fera pas la différence ici entre une file de messages (queue) ou un fil de notification (topic), ni entre un Message Broker, un Mediator, un Data Stream ou je ne sais quel autre MoM.
A noter que je précise bien API REST car selon moi un système de messages est une API. Nous avons donc deux types d’API ici : REST et messages.
Problème
Maintenant que nous avons une définition commune, pouvons-nous répondre à la question initiale ? Vous êtes tenté de répondre :
« API REST quand la communication doit être synchrone et message quand elle doit être asynchrone. »
Mais ce n’est peut-être pas si évident. Regardons de plus près chaque solution.
Solutions
API REST
Nous devrions utiliser une API REST pour :
- Des requêtes/réponses synchrones puisque HTTP met en scène sur un jeu de question/réponse.
- Des requêtes/réponses dans un temps limité car les requêtes HTTP sont bloquantes.
- L’ouverture de l’API au public
- HTTP repose sur des standards définis par l’IETF.
- Les messages peuvent être facilement documentés (avec OpenAPI).
- L’écosystème de sécurisation pour REST est robuste (pare-feu, authentification, cache, …).
- Le support des transactions
- De petits projets : car REST est plus simple et facile à déployer.
Ses défauts sont :
- Un couplage fort qui tient essentiellement au fait que l’appelant doit connaitre l’appelé.
- Des appels bloquants comme vu précédemment.
- La gestion des erreurs n’est pas toujours triviale car elle repose sur le code de status des requêtes couplé au document retourné et éventuellement des entêtes HTTP. En cas d’échec, il est nécessaire de mettre en place des mécanismes de réessai ou de réconciliation dans le client.
Message sur bus d’événements
Alors que nous devrions utiliser des événements pour :
- La communication asynchrone : chaque composant s’occupe de sa tâche sans soucier de ce qui se passe avant ou après. Les files permettent de répartir ou lisser la charge. Et les notifications permettent d’informer sur l’occurence d’un événement à qui veut le savoir.
- Le couplage lâche : les composants ne se connaissent pas et peuvent être testés indépendamment.
- La scalabilité plus facile : car peut être localisée sur un composant en particulier1.
- Le support de la reprise : en rejouant le journal d’événements.
- Une meilleure résilience et gestion des erreurs en s’appuyant sur les fonctionnalités du MoM (telles que les dead letter queues, poison queues, la persistance, etc…).
Les défauts sont :
- L’absence de standard : chaque MoM a sa propre API.
- Expose les détails d’implémentation : si vous changez de MoM, vos clients devront réimplémenter les appels vers votre système.
- Pas encore de standard pour documenter les messages échangés (AsyncAPI pourrait changer la donne).
- De nombreux MoM imposent un échange de messages de petite taille2.
Conclusion
En listant les caractéristiques de ces solutions, on en déduit qu’il n’y a pas une architecture RESTful (revisite plus simple et plus moderne de l’architecture SOA) d’un côté et une architecture orientée événements de l’autre. Il est possible et recommandé de combiner les deux pour tirer le meilleur parti de chacun :
- Exposez au monde extérieur vos APIs sous la forme d’API REST car ce sera plus simple à utiliser pour le client et vous bénéficierez de tout l’écosystème HTTP (sécurisation, cache, quota, …)3.
- A noter que vous pouvez mettre en place un système de notification avec le monde extérieur au travers des webhooks. Ces derniers peuvent être des API REST et sont supportés par OpenAPI 3.1.
- Même si ce n’est pas le comportement par défaut, il est possible de proposer une API REST asynchrone via la technique des callbacks (également supportés par OpenAPI).
- De même, les API REST sont là pour masquer les détails d’implémentation à vos clients.
- Alors que les messages d’événements vont vous aider à gérer la charge à l’intérieur de votre système : « accepter la tâche maintenant et la traiter plus tard ».
- De plus, l’utilisation de ces messages d’événements facilitent la construction d’un système résilient.
- Au sein de votre système, privilégiez les APIs REST pour les requêtes synchrones qui attendent une réponse et qui peuvent être traitées rapidement. Pour le reste, passez par des messages d’événement sur un MoM4.
Comme vous pouvez le voir, API REST ou message sur bus d’événements n’est pas qu’une simple question de synchrone ou asynchrone. Il ne faut pas oublier les consommateurs de vos APIs.
- Je vous accorde qu’avec les Load balancers semble relativement facile également pour les API REST. ↩
- Même si cette limitation peut être augmentée, elle traduit souvent au choix de conception du système que l’on ne peut ignorer. ↩
- Le contre-exemple est sûrement le cas de l’IoT avec MQTT qui semble bien développé et être une API assez standardisée. ↩
- Si votre système est suffisant important pour que la mise en place du MoM ne devienne pas significatif. ↩
Laisser un commentaire