Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Les microservices sont un style architectural répandu pour générer des applications résilientes, hautement scalables, capables d’évoluer rapidement et pouvant être déployées indépendamment. La création d’une architecture de microservices réussie nécessite un changement fondamental dans l’esprit. Il va au-delà de la décomposition d’une application en services plus petits. Vous devez également repenser la façon dont les systèmes sont conçus, déployés et exploités.
Une architecture de microservices se compose d’un ensemble de petits services autonomes. Chaque service est autonome et doit implémenter une fonctionnalité unique dans un contexte borné. Un contexte borné est une division naturelle au sein d’une entreprise qui fournit une délimitation explicite dans laquelle un modèle de domaine existe.
Que sont les microservices ?
Les microservices sont des composants petits, indépendants et faiblement couplés qu’une seule petite équipe de développeurs peut écrire et gérer. Chaque service est géré sous la forme d’une base de code distincte, ce qui permet à une petite équipe de le gérer efficacement. Étant donné que les services peuvent être déployés indépendamment, les équipes peuvent mettre à jour les services existants sans regénérer ou redéployer l’ensemble de l’application. Contrairement aux modèles traditionnels qui ont une couche de données centralisée, les microservices sont responsables de la persistance de leurs propres données ou de leur état externe. Ils communiquent via des API bien définies, qui conservent les implémentations internes masquées d’autres services. Cette architecture prend également en charge la programmation polyglotte, ce qui signifie que les services n’ont pas besoin de partager la même pile technologique, bibliothèques ou frameworks.
Composants
En plus des services eux-mêmes, d’autres composants apparaissent dans une architecture de microservices classique :
Gestion ou orchestration : Ce composant de gestion gère l’orchestration des microservices. Il planifie et déploie des services sur plusieurs nœuds, détecte les défaillances, récupère des défaillances et active la mise à l’échelle automatique en fonction de la demande. Une plateforme d’orchestration de conteneurs telle que Kubernetes fournit généralement cette fonctionnalité. Dans les environnements natifs cloud, les solutions telles qu’Azure Container Apps fournissent une orchestration managée et une mise à l’échelle intégrée. Ces outils réduisent la complexité du déploiement et la surcharge opérationnelle.
Passerelle d’API : La passerelle API sert de point d’entrée pour les clients. Les clients envoient des demandes à la passerelle API au lieu d’appeler directement des services. La passerelle transfère ces demandes aux services principaux appropriés. Il gère également les préoccupations croisées telles que l’authentification, la journalisation et l’équilibrage de charge. Dans les architectures de microservices natives dans le cloud, les proxys de service légers tels que Envoy et Nginx prennent en charge la communication interne de service à service. Ce type de trafic interne, appelé trafic est-ouest, permet un routage et un contrôle de trafic avancés.
Middleware orienté message : Les plateformes de messagerie telles qu’Apache Kafka et Azure Service Bus permettent une communication asynchrone dans les microservices en favorisant le couplage libre et la prise en charge d’une scalabilité élevée. Ils constituent la base des architectures pilotées par les événements. Cette approche permet aux services de réagir aux événements en temps réel et de communiquer via la messagerie asynchrone.
Observabilité: Une stratégie d’observabilité efficace aide les équipes à maintenir la fiabilité du système et à résoudre rapidement les problèmes. La journalisation centralisée regroupe les logs pour faciliter le diagnostic. La surveillance en temps réel avec les agents et infrastructures de surveillance des performances des applications, comme OpenTelemetry, offre une visibilité sur l’intégrité et les performances du système. Le traçage distribué suit les requêtes à travers les frontières des services. Elle permet aux équipes de trouver des goulots d’étranglement et d’améliorer les performances.
Gestion des données : Une architecture de base de données bien conçue prend en charge l’autonomie et la scalabilité. Les microservices utilisent souvent la persistance polyglotte en choisissant différents types de base de données, tels que SQL ou NoSQL, en fonction des besoins spécifiques de chaque service. Cette approche s’aligne sur la conception pilotée par le domaine (DDD) et l’idée du contexte limité. Chaque service possède ses données et son schéma. Cette propriété réduit les dépendances interservices et permet aux services d’évoluer indépendamment. Ce modèle décentralisé améliore la flexibilité, les performances et la résilience du système.
Avantages
Agilité: Étant donné que les microservices sont déployés indépendamment, il est plus facile de gérer les correctifs de bogues et les versions des fonctionnalités. Vous pouvez mettre à jour un service sans redéployer l’ensemble de l’application et restaurer une mise à jour en cas de problème. Dans de nombreuses applications traditionnelles, si vous trouvez un bogue dans une partie de l’application, il peut bloquer l’ensemble du processus de mise en production. Par exemple, un bogue peut bloquer de nouvelles fonctionnalités si vous devez intégrer, tester et publier un correctif de bogue.
Petites équipes ciblées : Un microservice doit être suffisamment petit pour qu’une seule équipe de fonctionnalités puisse générer, tester et déployer celle-ci. Les petites équipes favorisent une plus grande souplesse. Les grandes équipes ont tendance à être moins productives, car la communication est plus lente, la surcharge de gestion augmente et l’agilité diminue.
Base de code de petite taille : Dans une application monolithique, les dépendances de code deviennent souvent enchevêtrées au fil du temps. L’ajout d’une nouvelle fonctionnalité peut nécessiter des modifications dans de nombreuses parties du codebase. Une architecture de microservices évite ce problème en ne partageant pas de code ou de magasins de données. Cette approche réduit les dépendances et facilite l’introduction de nouvelles fonctionnalités.
Combinaison de technologies : Les équipes peuvent choisir la technologie qui convient le mieux à leur service à l’aide d’un mélange d'ensembles technologiques selon les besoins.
Isolation des erreurs : Si un microservice individuel devient indisponible, il n’interrompt pas l’ensemble de l’application tant que les microservices en amont sont conçus pour gérer correctement les erreurs. Par exemple, vous pouvez implémenter le modèle Disjoncteur ou concevoir votre solution afin que les microservices communiquent entre eux à l’aide de modèles de messagerie asynchrones.
Scalabilité : Les services peuvent être mis à l’échelle indépendamment. Cette approche vous permet d’effectuer un scale-out des sous-systèmes qui nécessitent plus de ressources sans effectuer un scale-out de l’application entière. Utilisez un orchestrateur tel que Kubernetes pour ajouter une densité plus élevée de services sur un seul hôte, ce qui permet une utilisation plus efficace des ressources.
Isolation des données : La mise à jour d’un schéma est plus simple dans une architecture de microservices, car un seul microservice est affecté. En revanche, les applications monolithiques peuvent compliquer les modifications de schéma, car plusieurs composants interagissent souvent avec les mêmes données. Cet accès partagé rend toute modification potentiellement risquée.
Défis
Les avantages des microservices viennent avec des compromis. Tenez compte des défis suivants avant de créer une architecture de microservices :
Complexité: Une application de microservices a plus de composants mobiles que l’application monolithique équivalente. Si chaque service est plus simple, le système dans son ensemble est plus complexe. Veillez à prendre en compte les défis tels que la découverte de services, la cohérence des données, la gestion des transactions et la communication interservice lorsque vous concevez votre application.
Développement et test : L’écriture d’un petit service qui s’appuie sur d’autres services dépendants nécessite une approche différente de l’écriture d’une application monolithique ou en couches traditionnelle. Les outils existants ne sont pas toujours conçus pour fonctionner avec les dépendances de service. Refactoriser au-delà des limites des services peut s’avérer difficile. Il est également difficile de tester les dépendances de service, en particulier lorsque l’application évolue rapidement.
Manque de gouvernance : L’approche décentralisée de la création de microservices présente des avantages, mais elle peut également entraîner des problèmes. Vous pouvez en effet vous trouver face à une diversité de langages et de frameworks telle que l’application devient difficile à gérer. Il peut être utile de mettre en place certains standards à l’échelle du projet, sans trop limiter la flexibilité des équipes. Cette méthode s’applique particulièrement aux fonctionnalités croisées telles que la journalisation.
Congestion et latence du réseau : L’utilisation de nombreux services petits et granulaires peut entraîner une communication plus interservice. En outre, si la chaîne de dépendances de service est trop longue (le service A appelle B, ce qui appelle C...), la latence supplémentaire peut devenir un problème. Vous devez concevoir soigneusement des API. Évitez les API trop bavardantes, réfléchissez aux formats de sérialisation et recherchez des endroits où utiliser des modèles de communication asynchrones comme le modèle de niveau de chargeQueue-Based.
Intégrité des données: Chaque microservice est responsable de sa propre persistance des données. Par conséquent, la cohérence des données entre plusieurs services peut constituer un défi. Différents services conservent les données à différents moments, en utilisant différentes technologies et avec des niveaux de réussite potentiellement différents. Lorsque plusieurs microservice sont impliqués dans la persistance de données nouvelles ou modifiées, il est peu probable que la modification complète des données puisse être considérée comme une transaction atomique, cohérente, isolée et durable (ACID). Au lieu de cela, la technique est plus alignée sur Basically Available, Soft State, Eventual Consistency (BASE). Adoptez la cohérence éventuelle dans la mesure du possible.
Gestion: Une architecture de microservice réussie nécessite une culture DevOps mature. La mise en place d’une journalisation corrélée entre les services peut poser des problèmes. En règle générale, la journalisation doit mettre en corrélation plusieurs appels de services pour une même opération utilisateur.
Contrôle de version : Les mises à jour d’un service ne doivent pas interrompre les services qui en dépendent. Plusieurs services pouvant être mis à jour à tout moment, sans une conception minutieuse, vous risquez de rencontrer des problèmes de compatibilité descendante ou ascendante.
Ensemble de compétences : Les microservices sont des systèmes hautement distribués. Évaluez avec soin les chances de réussite en tenant compte des compétences et de l’expérience de l’équipe.
Meilleures pratiques
Modélisez les services autour du domaine de l’entreprise. Utilisez DDD pour identifier les contextes délimités et définir des limites de service claires. Évitez de créer des services trop granulaires, ce qui peut augmenter la complexité et réduire les performances.
Décentralisez tout. Les équipes individuelles sont responsables de la conception et de la création de services de bout en bout. Évitez de partager du code ou des schémas de données.
Normalisez vos choix technologiques en limitant le nombre de langages et de frameworks que vous utilisez. Établissez des normes à l’échelle de la plateforme pour la journalisation, la surveillance et le déploiement.
Le stockage de données doit être privé par rapport au service qui détient les données. Utilisez le stockage le mieux adapté à chaque service et type de données.
Les services communiquent via des API bien conçues. Évitez de divulguer les détails d’une implémentation. Les API doivent modéliser le domaine, et non l’implémentation interne du service.
Évitez le couplage entre les services. Le couplage trouve souvent son origine dans les schémas de base de données partagés et les protocoles de communication rigides.
Utilisez des frameworks de messagerie pour la communication asynchrone. Adoptez des outils tels que MassTransit ou NServiceBus pour gérer le routage, les nouvelles tentatives, la durabilité et les modèles de flux de travail au lieu de créer une logique de messagerie personnalisée. Les infrastructures permettent de réduire la complexité du système distribué, d’améliorer la fiabilité et d’éviter les pièges courants lors de l’implémentation de microservices pilotés par les messages.
Améliorez la sécurité à l’aide de mTLS (mutual Transport Layer Security) pour le chiffrement de service à service. Implémentez le contrôle d’accès en fonction du rôle et utilisez des passerelles d’API pour appliquer des stratégies.
Déchargez les préoccupations transversales, telles que l'authentification et la terminaison SSL, sur la passerelle. Les maillages de service et les frameworks tels que Dapr peuvent également aider à résoudre des problèmes communs tels que l’authentification mTLS et la résilience.
Maintenez la connaissance du domaine à l’extérieur de la passerelle. La passerelle doit traiter et acheminer les demandes des clients sans connaître les règles d’entreprise ou la logique du domaine. Sinon, la passerelle devient une dépendance et peut provoquer un couplage entre les services.
Le couplage entre les services doit être faible et leur cohésion fonctionnelle élevée. Les fonctions susceptibles de changer en même temps doivent être empaquetées et déployées ensemble. S’ils résident dans des services distincts, ces services finissent par être étroitement couplés, car un changement dans un service nécessite la mise à jour de l’autre service. La communication excessive entre deux services peut être un symptôme d’un couplage trop étroit et d’une cohésion réduite.
Utilisez des pipelines d’intégration continue et de déploiement continu (CI/CD) pour automatiser les tests et le déploiement. Déployez des services indépendamment et surveillez la santé du déploiement.
Isolez les défaillances. Utilisez des stratégies de résilience pour empêcher que les défaillances au sein d’un service se répercutent en cascade. Pour plus d’informations, consultez Modèles de résilience et Conception d’applications fiables.
Utilisez l’ingénierie du chaos pour tester la résilience de votre architecture de microservice et ses dépendances. Évaluez et améliorez la façon dont le système gère les défaillances partielles.
Implémentez la journalisation centralisée, le suivi distribué (OpenTelemetry) et la collecte de métriques pour garantir l’observabilité.
Antimodèles pour les microservices
Lorsque vous concevez et implémentez des microservices, des pièges spécifiques peuvent fréquemment compromettre les avantages de ce style architectural. La reconnaissance de ces antimodèles aide les équipes à éviter les erreurs coûteuses et à créer des systèmes plus résilients et durables. Évitez les antimodèles suivants :
L’implémentation de microservices sans une compréhension approfondie du domaine métier entraîne des limites de service mal alignées et sape les avantages prévus.
La conception d’événements qui dépendent des événements passés ou futurs enfreint le principe de la messagerie atomique et autonome. Cette dépendance force les consommateurs à attendre et à réduire la fiabilité du système.
L’utilisation d’entités de base de données en tant qu’événements expose les détails du service interne et ne parvient souvent pas à transmettre l’intention métier correcte, ce qui conduit à des intégrations étroitement couplées et peu claires.
Éviter la duplication des données à tous les coûts est un antimodèle. L’utilisation de modèles tels que des vues matérialisées pour maintenir des copies locales améliore l’autonomie du service et réduit les dépendances interservices.
L’utilisation d’événements génériques force les consommateurs à interpréter et filtrer les messages. Cette approche ajoute une complexité inutile et réduit la clarté de la communication basée sur les événements.
Le partage de bibliothèques ou de dépendances communes entre les microservices crée un couplage étroit, ce qui rend les modifications risquées et répandues et s’oppose au principe des services autonomes.
L’exposition de microservices directement aux consommateurs entraîne un couplage étroit, des problèmes d’extensibilité et des risques de sécurité. L’utilisation d’une passerelle d’API fournit un point d’entrée propre, gérable et sécurisé.
La conservation des valeurs de configuration à l’intérieur des microservices les associe étroitement à des environnements spécifiques, ce qui rend les déploiements plus difficiles. Toutefois, l'externalisation de la configuration favorise la flexibilité et la portabilité de l'environnement.
L’incorporation d’une logique de sécurité comme la validation de jetons directement à l’intérieur des microservices complique leur code et leur maintenance. Vous pouvez également décharger la sécurité sur les composants dédiés pour que les services soient concentrés et plus propres.
L’échec de l’abstraction des tâches courantes de microservices entraîne un code répétitif, sujet aux erreurs, et limite la flexibilité. Sinon, l’utilisation de frameworks d’abstraction comme Dapr simplifie le développement en découplant la logique métier des problèmes d’infrastructure.
Créer une architecture de microservices
Les articles suivants présentent une approche structurée pour la conception, la création et l’exploitation d’une architecture de microservices.
Utilisez l’analyse de domaine : Pour éviter les pièges courants lorsque vous concevez des microservices, utilisez l’analyse de domaine pour définir vos limites de microservice. Effectuez les étapes suivantes :
- Utilisez l’analyse de domaine pour modéliser les microservices.
- Utilisez la tactique de la conception basée sur le domaine pour concevoir des microservices.
- Identifiez les limites des microservices.
Concevez les services : Les microservices nécessitent une approche décentralisée et agile pour la conception et la création d’applications. Pour plus d’informations, consultez Concevoir une architecture de microservices.
Opérer en production : Étant donné que les architectures de microservices sont distribuées, vous devez disposer d’opérations robustes pour le déploiement et la surveillance.