De l'application monolithique aux architectures microservices

Comme nous avons pu le voir dans le billet précédent, l’évolution du web est passée par l’évolution de nos outils. Des applications codées from scratch, nous disposons aujourd’hui de cadres de développement pour réaliser tout un tas d’applications.

Ce qui suit reflète mon vécu et non pas la généralité des projets, néanmoins il n’est pas rare de se retrouver face à des projets (souvent de taille conséquente) ayant évolués afin de répondre à toutes les demandes et besoins centralisés dans une seule et même application.

De l’application simple à l’application à tout faire, il n’y a qu’un pas.

Au départ destinée à un besoin simple celle-ci s’est vue évoluer en quelque chose de monstrueux ou chaque nouvelle fonctionnalité engendre son lot de régressions et d’interdépendances dans le code. A mon sens, le principal problème des applications monolithiques sont qu’elles centralisent tous les besoins et qu’elles sont réalisées dans une seule technologie. Il est intéressant d’exploiter les capacités de différents langages pour des buts spécifiques, comme par exemple R pour faire du calcul statistique ou Nodejs pour du temps réel. Au fil du temps, cette application devient de plus en plus complexe et il est alors difficile de garder l’architecture modulaire prévue à l’origine.

Vous l’aurez compris je ne suis pas un fervent défenseur de l’application monolithique car le debugging me fait trop penser à un plat de spaghettis.

Micro-services et consommation d’APIs

Tous ces inconvénients nous ont conduit à penser autrement, à exploser ce bloc applicatif en services indépendants, écrit dans différents langages et maintenus par des équipes différentes. L’application devient alors une suite de services. Ces services autonomes sont amenés à communiquer entre eux par le biais d’un protocole simple tel que HTTP et une API REST. La complexité de l’application est alors décomposée en un ensemble de modules facile à maintenir.

monolithic vs micro services

Les retours d’expériences sur ce type d’architecture sont positifs et de plus en plus utilisés, à tel point que cela devient un standard pour les grosses applications. On peut citer Netflix et Amazon.

La componentisation ou le découpage en briques

La componentisation est une autre méthode pour sortir de l’application monolithique. Il s’agit d’atomiser (réduire) des ressources en packages ou librairies réutilisables de façon à ce qu’ils puissent être combinés entre eux.

Prenons un exemple avec un cas concret, Drupal Commerce. La prochaine version en cours de développement pour Drupal 8 a complètement été repensée et ne sera pas uniquement une suite de modules comme l’était la première version. Le choix a été fait de découper les besoins en librairies de bas niveaux ne réalisant qu’une seule chose et pouvant être réutilisées par n’importe quelle application ou framework PHP. Ces composants sont accessibles sur le dépôt Github de Commerce Guys afin que vous puissiez les intégrer dans vos applications. Pour le moment il y a 4 composants Intl, Addressing, Pricing et Tax. Toute la logique a ainsi été déportée dans des librairies externes et l’intégration avec Drupal sera minime. Il n’est pas impossible que ces composants soient utilisés par des projets E-commerce Symfony2.

Vers la fin des applications monolithiques ?

Il y a plein d’avantages à ces types d’architectures qu’elles soient sous forme de composants ou de services. Cela coûte moins cher à réaliser et c’est rapide à fabriquer car on réutilise beaucoup de composants qui existent déjà. C’est aussi plus maintenable et évolutif car chaque service ne réalise qu’un groupe d’actions dans un but unique. Du fait que chaque composant est séparé du reste de l’application et qu’il communique uniquement via une API, il est facile de le changer du moment que l’API n’est pas modifiée.

Bien sûr tout n’est pas rose, il y a quelques complexités qu’il est important de gérer au plus tôt telles que le découpage des composants, la résistance aux pannes et la maitrise de différentes technologies et langages. Comme évoqué, tout repose sur des échanges et sur la consommation d’APIs, il est essentiel de concevoir l’application afin qu’elle soit tolérante aux pannes et qu’elle puisse continuer de fonctionner lorsqu’un composant est hors d’usage. De ce fait loguer et analyser les erreurs de communication et le fonctionnement de chaque service est obligatoire pour assurer le bon fonctionnement de l’application.

A l’inverse d’une architecture monolithique il est important de découper le fonctionnement de chaque service ou composant. Simple à dire, il s’avère que cet exercice est en réalité plus compliqué à réaliser. Pour délimiter un service, la règle la plus simple est de découper selon le besoin fonctionnel, toutefois l’utilisation d’une technologie ou d’un langage de programmation peut être un bon motif pour identifier un service. Il n’y a pas de règle toute faite pour cela, néanmoins il faut créer des services les plus simples possibles faisant un minimum de choses.

De façon à tirer profit des forces de chaque langage il est donc important que l’équipe de développeurs maitrise plusieurs technologies front-end ou back-end. A l’heure actuelle les technologies qui ont le vent en poupe sont AngularJs, Nodejs, Go et Rust. Bien entendu il est impossible de maitriser tous ces langages en plus de langages courants tels que Ruby, PHP ou Java, néanmoins savoir comment ils fonctionnent et comment les utiliser est important.

Ainsi, que ce soit une architecture découpée en composants ou une architecture orientée services, cela semble être la solution pour éviter les applications inmaintenables. Ce concept n’a rien de neuf car il peut être rapproché de l’architecture SOA - Service Oriented Architecture, toutefois cela a été remis au goût du jour avec l’effervescence des SPA - Single Page Application. Il s’agit d’un Backend qui met à disposition des informations à un Frontend au travers d’une API REST, dans ce cas, l’architecture orientée services est idéale.

Références et articles sur le sujet :