Quelle est la taille adaptée pour un microservice ? Vous entendez souvent « ni trop gros, ni trop petit » et, bien que certainement correct, ce n’est pas très utile dans la pratique. Mais si vous partez d’un modèle de domaine bien conçu, il est beaucoup plus facile d’aborder les microservices.
Cet article utilise l'exemple d'un service de livraison par drone. Pour en savoir plus sur le scénario et l'implémentation de référence correspondante, cliquez ici.
Du modèle de domaine aux microservices
Dans l'article précédent, nous avons défini un ensemble de contextes limités pour une application de livraison par drone, Drone Delivery. Ensuite, nous avons examiné plus en détail un de ces contextes limités (celui de l’expédition) et identifié un ensemble d’entités, d’agrégats et de services de domaine pour ce contexte limité.
Nous sommes maintenant prêts à passer du modèle de domaine à la conception de l’application. Il s’agit d’une approche que vous pouvez utiliser pour dériver des microservices à partir du modèle de domaine.
Commencez avec un contexte limité. En général, la fonctionnalité dans un microservice ne doit pas s’étendre à plusieurs contextes limités. Par définition, un contexte limité marque la limite d’un modèle de domaine particulier. S’il s’avère qu’un microservice associe des modèles de domaines différents, vous devrez peut-être revenir en arrière et affiner votre analyse de domaine.
Ensuite, examinez les agrégats dans votre modèle de domaine. Les agrégats font souvent de bons candidats pour les microservices. Un agrégat bien conçu présente de nombreuses caractéristiques d’un microservice bien conçu. Entre autres :
- Un agrégat est dérivé des besoins de l’entreprise, plutôt que des problèmes techniques, tels que les accès aux données ou la messagerie.
- Un agrégat doit avoir une cohésion fonctionnelle élevée.
- Un agrégat est une limite de persistance.
- Les agrégats doivent être couplés en laissant une marge de manœuvre.
Les services de domaine font également de bons candidats pour les microservices. Les services de domaine sont des opérations sans état entre plusieurs agrégats. Un workflow impliquant plusieurs microservices en est un exemple type. Nous en verrons un exemple dans l’application Drone Delivery.
Enfin, tenez compte des exigences non fonctionnelles. Examinez les facteurs tels que la taille de l’équipe, les types de données, les technologies, ainsi que les exigences d’extensibilité, de disponibilité et de sécurité. Ces facteurs peuvent vous amener à décomposer un microservice en plusieurs services plus petits ou, à l’inverse, à combiner plusieurs microservices en un seul.
Après avoir identifié le microservices dans votre application, vérifiez la conception en vous aidant des critères suivants :
- Chaque service a une seule responsabilité.
- Il n’existe aucun appel bavard entre les services. Si le fractionnement des fonctionnalités entre deux services entraîne trop de bavardage, cela peut indiquer que ces fonctions appartiennent au même service.
- Chaque service est assez petit pour permettre à une petite équipe travaillant indépendamment de le générer.
- Il n’existe aucune interdépendance qui nécessite le déploiement de plusieurs services avec un verrouillage. Il doit toujours être possible de déployer un service sans avoir à redéployer les autres services.
- Les services ne sont pas strictement couplés et peuvent évoluer indépendamment.
- Les limites de service ne créeront pas de problèmes liés à l’intégrité ou à la cohérence des données. Parfois, il est important de maintenir la cohérence des données en plaçant des fonctionnalités dans un seul microservice. Ceci dit, déterminez si vous avez vraiment besoin d’une forte cohérence. Il existe des stratégies de résolution de la cohérence éventuelle dans un système distribué, et les avantages de la décomposition des services l’emportent souvent sur les défis de gestion de la cohérence éventuelle.
Avant tout, il est important d’être pragmatique et de ne pas oublier que la conception orientée domaine est un processus itératif. En cas de doute, commencez avec des microservices généraux. Il est plus facile de fractionner un microservice en deux services plus petits que de refactoriser une fonctionnalité entre plusieurs microservices existants.
Exemple : Définition de microservices pour l'application de livraison par drone (Drone Delivery)
Rappelez-vous que l’équipe de développement a identifié les quatre agrégats (Livraison, Colis, Drone et Compte) et deux services de domaine (planificateur et superviseur).
Les agrégats Livraison et Colis sont des candidats évidents pour les microservices. Le planificateur et le superviseur coordonnent les activités effectuées par les autres microservices. Il est donc judicieux de mettre en œuvre ces services de domaine en tant que microservices.
Les agrégats Drone et Compte sont intéressants, car ils appartiennent à d’autres contextes limités. Première option : le planificateur appelle directement les contextes limités Drone et Compte. Seconde option : créer des microservices Drone et Compte dans le contexte limité Expédition. Ces microservices serviraient de médiateurs entre les contextes limités, en exposant des API ou des schémas de données plus adaptés au contexte Expédition.
Les détails des contextes limités Drone et Compte dépassent le cadre de ce guide. Nous avons donc créé des services fictifs pour eux dans notre implémentation de référence. Mais voici quelques facteurs à prendre en compte dans cette situation :
Quelle charge réseau représente un appel direct dans l’autre contexte limité ?
Le schéma de données pour l’autre contexte limité est-il approprié pour ce contexte, ou vaut-il mieux avoir un schéma sur mesure pour ce contexte limité ?
L’autre contexte limité est-il un système hérité ? Dans ce cas, vous pouvez créer un service qui agit comme une couche anti-corruption pour traduire entre le système hérité et l’application moderne.
Quelle est la structure de l’équipe ? Est-il facile de communiquer avec l’équipe responsable de l’autre contexte limité ? Si ce n’est pas le cas, créez un service qui sert d’intermédiaire entre les deux contextes pour les frais de communication entre les équipes.
Jusqu'à présent, nous n’avons pas considéré les exigences non fonctionnelles. Avec à l’esprit les exigences de débit de l’application, l’équipe de développement décidé créer un microservice Ingestion distinct qui est chargé d’ingérer les requêtes des clients. Ce microservice implémentera le nivellement de charge en plaçant les requêtes entrantes dans une mémoire tampon en vue de leur traitement. Le planificateur lira les requêtes à partir de la mémoire tampon et exécutera le workflow.
Les exigences non fonctionnelles ont conduit l’équipe à créer un service supplémentaire. À ce stade, tous les services concernent le processus de planification et de livraison des colis en temps réel. Mais le système doit stocker l’historique de chaque livraison dans un emplacement de stockage à long terme pour l’analyse de données. L’équipe a envisagé d’en donner la responsabilité au service Livraison. Toutefois, les exigences de stockage de données sont très différentes pour une analyse d’historique et des opérations en cours (voir Considérations relatives aux données). Par conséquent, l’équipe a décidé de créer un service Historique des livraisons distinct, qui écoute les événements DeliveryTracking à partir du service Livraison et les écrit dans l’emplacement de stockage à long terme.
Le schéma suivant présente la conception à ce stade :
Téléchargez un fichier Visio de cette architecture.
Étapes suivantes
À ce stade, vous devez avoir une bonne compréhension de l'objectif et des fonctionnalités de chacun des microservices de votre conception. Vous pouvez maintenant concevoir le système.