Qu’est-ce que l’architecture Microservices ? A quoi ça sert ? Julien Pontillo revient ce sur concept en détaillant les avantages et en portant un focus sur Nodejs, souvent plébiscité lorsqu’on souhaite y dévelloper des outils et des APIs.

Dans des entreprises de toutes tailles, on en parle. Tout le monde l’a déjà entendu, beaucoup l’utilisent sans le savoir, d’autres en parlent sans savoir ce que c’est. L’architecture Microservices est aujourd’hui dans la bouche de tout le monde, pour tous les avantages qu’elle apporte : maintenabilité, portabilité, réduction du blast radius en cas de crash et possibilité de marier plusieurs technologies sur une application n’étant que quelques avantages souvent cités. Lorsqu’il s’agit de développer des APIs et outils dans une architecture Microservices, NodeJS arrive souvent assez rapidement sur le tapis. Pourquoi ? Découvrons-le ensemble.

Rappel sur les Microservices

Le but d’une architecture Microservices est de découper une application (ou un ensemble applicatif) en Services. Ces services sont des unités fonctionnelles autonomes, développées, maintenues, déployées, monitorées et gérées indépendamment les unes des autres.

Beaucoup d’avantages, comme ceux cités plus haut, mais également une tonne d’inconvénients, parmi lesquels le besoin de penser ou repenser son application en modules non plus connectés par des import dans le code mais par d’autres moyens (souvent des requêtes HTTP, mais RCP et autres ne sont pas à écarter si besoin), également celui de devoir gérer plusieurs déploiements pour une seule application, ce qui veut dire plus de complexité dans la gestion mais également un Overhead — consommation de ressources non directement liées à l’utilisation de l’application mais à sa simple présence dans le SI — plus grand.
Le but de tout service dans cette architecture est d’embarquer un ou un ensemble de traitements spécifiques à un domaine, à une responsabilité. Appeler des bases de données, envoyer des emails ou encore appeler d’autres sous-services, beaucoup de petites unités de traitement qui, ensemble, constituent notre application dans son intégralité fonctionnelle.

NodeJS et son architecture

NodeJS est un moteur Javascript. Javascript est un langage événementiel, notre code étant presque
toujours attaché à un événement.
L’architecture de NodeJS gravite autour d’un concept simple, celui de l’event loop, une boucle
d’événements globale au moteur, dans laquelle se pilent tous les traitements.
Pour comprendre NodeJS, il faut comprendre le concept de processus Synchrone (bloquant) et
Asynchrone (non-bloquant). Imaginez une écriture dans un fichier :

1. Vous écrivez dans un fichier

Facile non ? Sauf que… non. Il faut bien comprendre que ce n’est pas votre programme qui manipule
les fichiers sur le disque dur, mais le système d’exploitation, qui lui-même repose sur le microcode
du disque dur lui-même (pour simplifier). Cette opération a l’air rapide, mais ce n’est pas le cas. De
plus, le temps que le système fasse toutes les opérations requises pour l’écriture, il fige votre
processus et ne lui rend la main que lorsque l’opération a terminé.
Dans la majorité des langages, ce processus est Synchrone (bloquant), ce qui veut dire que le temps
de ces opérations, rien d’autre ne sera fait par l’application.

En réalité, le processus ressemble plutôt à ça :

1. Vous demandez une écriture dans un fichier
2. Le système place processus est mis en attente
3. Le système manipule le driver du disque dur pour faire l’écriture dans le fichier et vérifier
l’intégrité des données
4. Le système rend la main à votre processus, qui peut continuer

Il faut bien comprendre que là, nous parlons d’écriture dans un fichier, mais il en va de même pour
la lecture dans une base de données, un appel HTTP à un sous-service, etc…
Dans la majorité des technologies web serveur, ce problème est pallié par la multiplication des
processus, créant de l’Overhead.
Maintenant, NodeJS, de par son architecture Asynchrone (non-bloquante), nous permet de
continuer à faire d’autres choses pendant ce genre d’exécutions. Revenons sur l’event loop.

Lorsque vous voulez par exemple écrire dans un fichier :
1. Vous demandez l’écriture dans un fichier, et qu’à la fin la fonction fileWritten soit exécutée
2. Node commence l’exécution de l’écriture en écrivant dans son event loop que la fonction
fileWritten doit être exécutée à la fin
3. NodeJS continue de traiter d’autres processus de son event loop
4. L’écriture a terminé, le système notifie Node
5. La fonction fileWritten est appelée

Le point important à retenir de tout cela est que le temps que le système fasse sa tambouille, notre
processus continue de tourner et notre API continue de répondre à des requêtes.
Pour rappel, la majorité des opérations effectuées par une API sont des opérations qui ne sont pas
effectuées directement par l’API, comme des accès base de données, des appels HTTP à d’autres
services ou encore des manipulations de fichiers, on comprend donc rapidement l’intérêt que toutes
ces opérations s’effectuent de manière non-bloquantes.
Pour faire une comparaison, imaginez-vous devoir rester assis sur une chaise à chaque fois que vous
demandez à quelqu’un de faire quelque chose en attendant qu’il ait terminé…
Il est également bon de noter que NodeJS a un tout petit Overhead, quelques Mégas de RAM et
quelques microunités de CPU suffisent à lancer une API complexe.
C’est ça, le truc. C’est précisément ça, la force de NodeJS dans une architecture Microservices: un
processus est plus puissant que 500 d’une autre technologie car il traite tout en même temps.
> Faire plus pour moins <

Parfait… ou presque

Notons que si NodeJS, de par son architecture, excelle dans la rapidité de traitement des opérations
non-bloquantes, il présente également un gros point faible : il est mono-thread.
Ça n’a l’air de rien (et en réalité ce n’est pas grand-chose), mais cela fait que tout traitement
bloquant se répercutera sur l’ensemble des clients de l’API (de cette instance de l’API du moins). On
peut par exemple penser un traitement lourd en CPU, comme un calcul conséquent, mais ce peut
être tout simplement un développeur qui a oublié de réfléchir en Asynchrone et qui a fait une
opération bloquante d’une demi seconde….
Je dis qu’en réalité ce n’est pas grand-chose car, de par son faible Overhead, NodeJS est candidat à
un scaling de masse. On peut déployer des dizaines de fois son API en parallèle pour vraiment pas
très cher, et ça, c’est bien.

Conclusion

NodeJS est le candidat parfait pour la réalisation d’APIs et autres dans une architecture microservices.
Que ce soit de par sa capacité à tout traiter en même temps ou par son faible Overhead, on
comprend pourquoi autant d’entreprises l’ont accepté en masse.
Notons que certains de ses concurrents sont plus pertinents dans certaines situations. Python,
Erlang ou encore Go font de superbes APIs, très performantes, et possèdent tous des communautés
conséquentes.

Julien Pontillo