Quand on écoute de nombreuses personnes, on serait tenté de croire que pour faire une architecture microservices il faut nécessairement Docker et Kafka, et pour du DevOps il faut nécessairement un Jenkins et Docker. Bref ces gens confondent les méthodes ou patterns, ici microservices et DevOps, ce qui est un biais fort regrettable. Dans la suite, pour remettre les choses en place, on va prendre l’exemple des microservices. Après tout, c’est le buzzword à la mode en ce moment, pas vrai ? 😉
Le pattern microservices
La notion de microservices est un design-pattern d’architecture en complète opposition avec les applications monolithiques habituelles. Typiquement, on retrouvera :
- Des services métiers faiblement couplés les uns aux autres et qui ne concernent chacun qu’un seul domaine métier – les services peuvent d’ailleurs être codés dans des technos différentes telles que Python pour l’un et Java pour l’autre,
- Habituellement chaque service a sa propre base de données,
- Un broker de messages pour les faire communiquer entre eux de manière asynchrone. Dans certains cas une communication directe entre microservices peut aussi être nécessaire, auquel cas on passera par une API REST HTTP.
Les avantages d’une telle architecture sont notamment :
- Une grande modularité de l’application, avec la possibilité d’avoir différents composants avec des cycles de vie radicalement différents.
- La possibilité d’isoler les domaines métiers les uns des autres, suivant les bonnes pratiques du Domain Driven Design.
- La possibilité de faire des mises à jour de l’application à chaud, en changeant des composants à la volée sans que l’utilisateur ne s’en rende compte et sans interruption de service.
- Une grande facilité à faire du déploiement horizontal pour gérer les variations de charge.
En contrepartie, cette architecture présente les inconvénients suivants :
- Le coût de mise en place est nettement supérieur à celui d’une architecture classique.
- Certains résultats plus difficiles à atteindre, en particulier au niveau des transactions.
Bref comme tout design pattern celui-ci a ses domaines d’application, et d’autres situations dans lesquelles il n’est pas adapté. On peut dire qu’une telle architecture est très bien adaptée à des sites web d’e-commerce ainsi que des systèmes qui ont besoin d’être disponibles 24h/24.
Un exemple d’architecture microservices
On va prendre pour notre cas d’étude l’architecture microservices d’un site d’e-commerce. Pour simplifier, on va dire que les microservices du site sont les suivants :
- Un microservice de référentiel, dans lequel les différents produits sont listés ainsi que d’autres données telles que leur prix et de savoir s’ils sont encore au catalogue. Ce microservice est invoqué de manière synchrone par les autres services.
- Un microservice de facturation.
- Un microservice de gestion des stocks.
- Un microservice de préparation des commandes.
- Un microservice d’envoi d’e-mails.
Quand un utilisateur passe une commande, voici ce qu’il se passe :
- Le microservice de facturation vérifie que les produits demandés sont bien au catalogue ainsi que leur prix en contactant de manière synchrone le référentiel.
- Ensuite, il contacte la banque de l’utilisateur pour lancer l’opération de paiement.
- Une fois le paiement fait, il envoie une notification sur le broker.
Parallèlement au niveau du microservice de stocks il se passe les opérations suivantes :
- Le microservice de stocks contacte le référentiel pour vérifier que les produits demandés sont bien valides.
- Il les note comme verrouillés pour la commande. Note : on ne gère pas ici le cas de la rupture de stocks, qui passerait là aussi par un autre microservice pour passer commande.
Une fois que le service de gestion des stocks a reçu un message de confirmation de paiement via le broker il confirme la réservation des articles demandés, puis envoie un message au service d’expédition des commandes à travers le broker. Parallèlement, lorsque le service d’envoi des e-mails reçoit ce même message de confirmation de paiement il envoie un e-mail à l’utilisateur.
Enfin lorsque l’envoi est fait le service des expéditions envoie un message au broker. À la réception de ce message en provenance du broker le service des e-mails envoie un message à l’utilisateur.
Comme vous pouvez le voir il ne s’agit là que d’une logique très classique pour du e-commerce, bien que j’aie pris des raccourcis qui me vaudront probablement de me faire taper dessus par les puristes. 😉
Une proposition d’implémentation
Je ne vais pas rentrer dans les détails du code, mais pour faire simple, on peut parfaitement implémenter une architecture microservices avec un… cluster de serveurs d’EJB 2.1 ou supérieur ! En effet ce dernier fournit bien un broker de messages via JMS. Et en implémentant chacun des microservices sus-cités sous forme de beans de type Message Driven on arrive à ce qu’on veut !
Il suffit ensuite pour ce faire de livrer chacun des microservices dans un EJB différent, de façon à pouvoir les redéployer à chaud. S’ils sont bien écrits un serveur JBoss pourra le faire sans problème, de même qu’il sera capable d’agrandir ou de réduire le pool de beans à la volée. Chacun des EJB contiendra autant de message-driven beans que nécessaires, qui s’abonneront à des topics du broker de messages pour la communication inter-microservices. Et bien évidemment chaque EJB aura un schéma de base de données dédié.
Enfin, pour le référentiel, on pourra utiliser tout simplement le serveur web embarqué dans le serveur d’EJB, et l’implémenter en utilisant une API REST.
Question et réponses
En lisant ce qui est écrit ci-dessus, vous me considérerez probablement comme un taré, ce sur quoi vous n’avez probablement pas tort. 😉 Bref je vais tenter de répondre à vos questions.
Es-tu fier de ton design ?
Absolument ! Ça permet de troller tous ceux qui considèrent que pour du microservice il faut nécessairement du Docker et du Kafka.
Quels sont les avantages de ta proposition par rapport à une architecture Docker + (Kafka ou RabbitMQ) ?
Les serveurs d’EJB gèrent l’autoscaling nativement. Autrement dit ils sont en mesure d’accroître ou de réduire à la volée les beans alloués à chaque fonctionnalité. Il est possible d’arriver à un tel résultat aussi avec des cluster managers de type Mesos mais la mise en oeuvre de cette fonctionnalité n’est pas si triviale qu’avec un serveur d’EJB. On peut toutefois y arriver avec Marathon.
Ce design respecte totalement les standards JEE, bref elle est portable entre les serveurs d’EJB… en théorie du moins, parce qu’en pratique… 😉
Appliquerais-tu un tel design dans la vraie vie ?
Je vous rassure, certainement pas. D’une les EJB sont morts, la dernière spécification a presque dix ans. Richard Monson-Haefel, qui a pourtant écrit nombre de livres sur le sujet l’affirmait déjà en 2006.
Deuxièmement développer sur un serveur d’EJB est une vraie galère tant c’est lourd. Il paraît que les derniers JBoss se sont améliorés mais quand même. Et même si les EJB 3.x se sont bien améliorés grâce à Spring coder sur ce dernier framework reste bien plus agréable du fait justement de sa relative légèreté, chaque microservice pouvant être une application Spring Boot par exemple.
En bref : les méthodes restent, les outils meurent
Si vous vous souvenez, le GoF présentait tous ses exemples avec le langage Smalltalk, et depuis ce dernier est mort et enterré mais pas les design patterns. De même l’architecture évoquée ci-dessus avec des microservices sur un cluster d’EJB n’aurait pas été considérée comme stupide voilà une dizaine d’années.
Tout ça pour dire que comme vous pouvez le voir ci-dessus de nombreux outils sont morts alors que les concepts leur ont survécu. Et c’est encore le cas maintenant, il suffit de constater que Kafka monte de plus en plus face à RabbitMQ.
De manière générale quand vous concevez un projet, pensez d’abord son architecture en fonction des besoins, et ensuite choisissez les technologies pour la mettre en oeuvre. Et ne faites pas l’inverse comme on le voit trop souvent, où le fonctionnel est adapté au technique. Maintenant ça ne signifie pas qu’il ne faut pas connaître d’outils, bien au contraire. Certaines technologies sont plus ou moins adaptées à certains cas d’usage, et plus on est renseigné sur le sujet plus on est en mesure de faire des choix pertinents. Mais surtout ne mettez pas la charrue avant les boeufs, et rappelez-vous, les microservices ne sont pas la solution à tout !
Besoin de tester ton niveau en développement informatique ?
Cet article vous a plu ? Vous aimerez sûrement aussi :
- La démarche DevOps
- Pour ou contre les frameworks ?
- De mauvaises habitudes de développement et les moyens de les perdre
Julien
Moi c’est Julien, ingénieur en informatique avec quelques années d’expérience. Je suis tombé dans la marmite étant petit, mon père avait acheté un Apple – avant même ma naissance (oui ça date !). Et maintenant je me passionne essentiellement pour tout ce qui est du monde Java et du système, les OS open source en particulier.
Au quotidien, je suis devops, bref je fais du dév, je discute avec les opérationnels, et je fais du conseil auprès des clients.