Les Architectures Microservices
Le terme "Microservice" est apparu ces dernières années pour décrire une manière particulière de concevoir des applications logicielles sous la forme de suites de services déployables de manière indépendante. Le style architectural des microservices est une approche qui consiste à développer une application unique sous la forme d'une suite de petits services, chacun fonctionnant dans son propre processus et communiquant à l'aide de mécanismes légers, souvent des APIs. Ces services sont construits autour des besoins de l'entreprise ou en fonction des fonctionnalités d'une application monolithique (application de type tout-en-un, dans un bloc unique) et peuvent être déployés indépendamment par des machines de déploiement entièrement automatisées. Ces services peuvent être écrits dans différents langages de programmation et utiliser différentes technologies de stockage de données.
Pour mieux expliquer ce concept de microservice, il est utile de le comparer à un système monolithique. Les applications d'entreprise sont souvent construites en trois parties principales : une interface utilisateur côté client, une base de données et une application côté serveur. Une application monolithique est construite comme une unité unique. Toute modification du système monolithique implique la création et le déploiement d'une nouvelle version de l'application côté serveur. Les applications monolithiques peuvent être une réussite, mais elles suscitent de plus en plus de frustrations, d'autant plus que, de plus en plus d'applications sont déployées dans le cloud. Les cycles de changement sont très liés car une modification de l'application, aussi petite qu'elle soit, nécessite de reconstruire et de déployer l'ensemble du monolithe. Au fil du temps, il est souvent difficile de conserver une bonne structure modulaire, ce qui complique le maintien des modifications qui ne devraient affecter qu'un seul module. La mise à l'échelle nécessite une mise à l'échelle de l'ensemble de l'application plutôt que des parties de celle-ci qui requièrent des ressources plus importantes.
Ces difficultés autour des monolithiques ont donné naissance au style architectural des microservices.
Les caractéristiques d'une architecture microservice
Voici quelques caractéristiques non-exhaustives d'une architecture microservice.
L'industrie du logiciel a toujours voulu concevoir des systèmes en se basant sur les principes des legos, c'est à dire en assemblant des composants. Lorsque nous parlons de composants, il s'agit d'une unité de logiciel qui peut être remplacée et mise à jour de manière indépendante.
L'une des principales raisons d'utiliser les services comme composants est que les services peuvent être déployés indépendamment les uns des autres. Un service peut être constitué de plusieurs processus qui seront toujours développés et déployés ensemble, tels qu'un processus d'application et une base de données qui n'est utilisée que par ce service.
Toute organisation qui conçoit un système produira une conception dont la structure est une copie de la structure de communication de l'organisation.
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure.
-- Melvin Conway, 1968
L'approche de la division par microservices est différente, puisqu'elle se divise en services organisés autour des besoins de l'entreprise. Ces services s'articulent autour des différentes composants techniques et fonctionnels du logiciel, entre autres l'interface utilisateur, le stockage, le mode de communication. Par conséquent, les équipes sont inter fonctionnelles et comprennent l'ensemble des compétences requises pour le développement d'une application. Une entreprise organisée de cette manière permet aux équipes inter fonctionnelles d'assurer la construction et l'exploitation de chaque produit et chaque produit est divisé en un certain nombre de services individuels qui communiquent par l'intermédiaire d'un bus de messages.
Dans un modèle classique, la plupart des efforts de développement d'applications que nous voyons utilisent un modèle de projet : l'objectif est de fournir un logiciel qui est ensuite considéré comme achevé. Une fois terminé, le logiciel est remis à une organisation de maintenance responsable de la Mise en Conditions Opérationnelles (MCO) et l'équipe projet est dissoute par la suite.
Depuis un moment, les partisans des microservices essayent d'éviter cette méthode de travail, approuvant l'idée qu'une équipe doit être propriétaire d'un produit pendant toute sa durée de vie. L'une des sources d'inspiration les plus courantes est la notion d'Amazon "you build, you run it", selon laquelle une équipe de développement assume l'entière responsabilité du logiciel en production. Cela permet aux développeurs d'être en contact quotidien avec le comportement de leur logiciel en production et d'accroître le contact avec leurs utilisateurs, puisqu'ils doivent assumer au moins une partie de la charge d'assistance et du MCO.
La mentalité du produit est aussi en lien avec les besoins de l'entreprise. Plutôt que de considérer le logiciel comme un ensemble de fonctionnalités à réaliser, il existe une relation permanente où la question est de savoir comment le logiciel peut aider ses utilisateurs à répondre aux besoins de l'entreprise.
Lors de l'établissement des communications entre différents processus, le bus de service d'entreprise (ESB) en est un bon exemple. Les produits ESB comprennent souvent des fonctions comme le routage ou la transformation des messages, etc.
Les partisans des microservices privilégient une autre approche différente sur les principes de communication : il s'agit des points de terminaison intelligents et les tubes ou tuyaux muets. Les applications construites à partir de microservices visent à être aussi découplées et cohésives que possible - elles possèdent leur propre logique en recevant une requête, appliquant la logique appropriée et produisant une réponse. Ils sont gérés à l'aide de protocoles REST simples plutôt que de protocoles complexes tels que WS-Choreography ou BPEL par exemple.
Les deux protocoles les plus couramment utilisés sont les requêtes-réponses HTTP et les API.
Une autre approche couramment utilisée est la messagerie via un bus de messages léger. L'infrastructure choisie est "dumb" (dumb, c'est-à-dire qu'elle agit uniquement comme un routeur de transfert de messages). On a des implémentations simples telles que RabbitMQ ou ZeroMQ qui ne font pas beaucoup plus que de fournir un tissu de messages asynchrone fiable cependant l'intelligence réside toujours dans les points finaux qui produisent et/ou consomment les messages dans les services.
Dans un monolithe, les composants s'exécutent en cours de processus et la communication entre eux se fait par l'invocation de méthodes ou l'appel de fonctions. Un des plus gros problèmes de la transformation d'un monolithe en microservices réside dans le changement du modèle de communication.
L'une des conséquences de la gouvernance centralisée est la tendance à la standardisation sur des plateformes technologiques uniques. L'expérience montre que cette approche est restrictive.
En divisant les composants du monolithe en services, nous avons donc le choix lors de la construction de chacun d'entre eux. Vous voulez utiliser Vue.js pour créer une simple page de rapport ? Allez-y. Du C# pour un composant en temps quasi réel particulièrement complexe ? C'est parfait. Vous voulez remplacer une base de données de lecture en ligne par une base de données orientée colonne ? C'est bien possible ! Bien sûr, ce n'est pas parce que vous pouvez faire quelque chose que vous devez le faire, mais en partitionnant votre système de cette manière, vous avez la possibilité de faire comme vous le sentez.
Les équipes qui construisent des microservices préfèrent également une approche différente des normes. Elles préfèrent l'idée de produire des outils utiles que d'autres développeurs peuvent utiliser pour résoudre des problèmes similaires à ceux qu'ils rencontrent. Ces outils sont généralement issus de la mise en œuvre et partagés avec un groupe plus large, parfois, mais pas exclusivement, en utilisant un modèle interne de source ouverte. Par exemple, maintenant que git et github sont devenus le système de contrôle de version de facto, les pratiques open source deviennent de plus en plus courantes en interne.
Netflix est un bon exemple d'organisation qui suit cette philosophie. Le partage de codes utiles et surtout éprouvés sous forme de bibliothèques encourage les autres développeurs à résoudre des problèmes similaires de la même manière, tout en laissant la porte ouverte à une approche différente si nécessaire. Les bibliothèques partagées ont tendance à se concentrer sur les problèmes communs de stockage de données, de communication inter-processus et, comme nous le verrons plus loin, d'automatisation de l'infrastructure.
En conséquence, on peut dire que l'apogée de la gouvernance décentralisée est peut-être l'éthique "build it / run it" popularisée par Amazon. Les équipes sont responsables de tous les aspects du logiciel qu'elles construisent, y compris de son exploitation 24/7. Le transfert de ce niveau de responsabilité n'est certainement pas la norme, mais nous voyons de plus en plus d'entreprises confier la responsabilité aux équipes de développement. Netflix est une autre organisation qui a adopté cette philosophie et c'est totalement bénéfique pour eux selon leurs retours. Ces idées sont donc aussi bien loin du modèle traditionnel de gouvernance centralisée.
Recommandé par LinkedIn
La décentralisation de la gestion des données se présente sous différentes formes. Au niveau le plus abstrait, cela signifie que les modèles conceptuels diffèrent d'un système à l'autre (la vision commerciale d'un client diffère de la vision du service d'assistance). Ce problème est courant "entre" les applications, mais il peut également se poser "au sein" des applications, en particulier lorsque l'application est divisée en composants distincts. La notion de contexte délimité (Bounded Context) de la conception pilotée par les domaines (Domain-Driven Design) est un moyen utile de réfléchir à cette question. La DDD divise un domaine complexe en plusieurs contextes délimités et établit les relations entre eux. Ce processus est utile pour les architectures monolithiques et microservices, mais il existe une corrélation naturelle entre les limites des services et du contexte qui aide à clarifier.
Au-delà de la décentralisation des modèles conceptuels, les microservices décentralisent également les décisions relatives au stockage des données. Alors que les applications monolithiques préfèrent une base de données logique unique pour les données persistantes, les microservices préfèrent laisser chaque service gérer sa propre base de données, soit différentes instances de la même technologie de base de données, soit des systèmes de base de données entièrement différents - une approche appelée persistance polyglotte (Polyglot Persistence).
Les techniques d'automatisation de l'infrastructure ont énormément évolué ces dernières années surtout avec l'évolution du cloud et d'AWS en particulier a réduit la complexité opérationnelle de la construction, du déploiement et de l'exploitation des architectures microservices.
(On doit être aussi sûrs que possible que notre logiciel fonctionne, c'est pourquoi les entreprises effectuent des tests automatisés.)
Au-delà des tests, aujourd'hui, les équipes utilisent une automatisation poussée de l'infrastructure autour de la gestion des microservices et des mises en production. On retrouve cela au travers l'utilisation d'outils comme Ansible ou Terraform.
L'utilisation de services en tant que composants a pour conséquence que les applications doivent être conçues de manière à pouvoir tolérer la défaillance des services. Tout appel de service peut échouer en raison de l'indisponibilité du fournisseur, et le client doit y répondre de la manière la plus gracieuse possible. Il s'agit d'un inconvénient par rapport à une conception monolithique, car cela introduit une complexité supplémentaire pour y faire face. La conséquence est que les équipes de microservices réfléchissent constamment à la manière dont les défaillances de service affectent l'expérience de l'utilisateur. Chez Netflix, on provoque des pannes de services et même de centres de données pendant la journée de travail pour tester la résilience et la surveillance de l'application avec un outil appelé Chaos Monkey. Les services pouvant tomber en panne à tout moment, il est important de pouvoir les détecter rapidement et, si possible, de les rétablir automatiquement. Les applications microservices mettent l'accent sur la surveillance en temps réel de l'application, en vérifiant à la fois les éléments architecturaux (combien de requêtes par seconde la base de données reçoit-elle) et les mesures pertinentes pour l'entreprise (telles que le nombre de commandes reçues par minute). Ceci est particulièrement important pour une architecture de microservices car la surveillance est essentielle pour repérer rapidement les mauvais comportements émergents afin de pouvoir les corriger.
Chaque fois que vous essayez de décomposer un système logiciel en composants, vous êtes confronté à la décision de savoir comment diviser les modules. Généralement on se demande quels sont les principes sur lesquels nous décidons de découper notre application ? La propriété clé d'un composant est la notion de remplacement indépendant et d'évolutivité ce qui implique que nous recherchons des points où nous pouvons imaginer réécrire un composant sans affecter ses collaborateurs. En effet, de nombreux groupes de microservices vont plus loin en s'attendant explicitement à ce que de nombreux services soient supprimés plutôt qu'évolués à long terme.
Le site web de The Guardian est un bon exemple d'application conçue et construite comme un monolithe, mais qui a évolué dans le sens des microservices. Le monolithe constitue toujours le cœur du site web, mais l'entreprise préfère ajouter de nouvelles fonctionnalités en construisant des microservices qui utilisent l'API du monolithe. Cette approche est particulièrement pratique pour les fonctionnalités qui sont par nature temporaires, telles que les pages spécialisées pour gérer un événement sportif. Une telle partie du site web peut être rapidement mise en place à l'aide de langages de développement rapide, et supprimée une fois l'événement terminé.
Les microservices représentent-ils l'avenir ?
Les entreprises que nous connaissons et qui sont en quelque sorte les pionnières de ce style architectural sont Amazon, Netflix, The Guardian, etc. Mais, il existe de nombreuses organisations qui font depuis longtemps ce que nous classerions comme des microservices, mais sans jamais utiliser ce nom. Ces pratiques sont généralement qualifiées de SOA (bien que la SOA se présente sous une autre forme).
Malgré plusieurs expériences positives, je ne peux prétendre être certains que les microservices constituent l'orientation future des architectures logicielles.
Souvent, les véritables conséquences des décisions architecturales ne sont visibles que plusieurs années après les avoir prises. Il y a certainement des raisons pour lesquelles on pourrait s’attendre à une mauvaise maturité des microservices mais généralement l'une d'entre elle c'est qu'il est difficile de déterminer exactement où doivent se situer les limites des composants. Microsoft en parle dans une de ses revues Learn.
J'espère que cet article vous aura éclairé un peu plus autour des architectures microservices.