web-dev-qa-db-fra.com

Les microservices doivent-ils se parler?

Je conçois une application à l'aide de Micro-Services et je ne suis pas sûr du meilleur mécanisme à utiliser pour collecter des données à partir de plusieurs services.

Je pense qu'il y a deux options:

  • Intégrer un mécanisme de communication "inter-services" qui permet aux services de parler directement. La passerelle API appelle un service individuel, qui appelle ensuite d'autres services pour collecter des données, avant de renvoyer la réponse consolidée à la passerelle API. L'API renvoie ensuite la réponse à l'appelant. (Il devrait s'agir d'appels synchrones lorsque l'appel à serviceB nécessite la réponse du serviceA. I.E Services de personne et d'adresse séparés.)
  • Demandez à la passerelle API d'appeler directement chaque service et de consolider les données dans l'API avant de renvoyer la réponse.

Je penche vers la deuxième option, car le fait que les services se parlent introduirait un couplage, auquel cas je pourrais tout aussi bien concevoir une application monolithique. Cependant, il y a quelques inconvénients sérieux que je peux penser au large de ma tête avec cette option:

  • Le fait que l'API exécute plusieurs appels vers plusieurs services augmente la charge sur le serveur d'API, en particulier lorsque certains de ces appels bloquent.

  • Cette méthode signifierait que l'API doit être "consciente" de ce que l'application essaie de faire (IE Logic devrait être programmé dans l'API pour gérer l'appel des services à son tour, puis consolider les données), plutôt que simplement agir comme un "point final" stupide pour les micro-services.

Je voudrais savoir quelle est l'approche standard de ce problème et s'il y a une autre troisième option qui me manque?

35
KidCode

Je déconseille généralement que les microservices établissent une communication synchrone les uns avec les autres, le gros problème est le couplage, cela signifie que les services sont désormais couplés les uns aux autres, si l'un d'entre eux échoue, le second est maintenant totalement ou partiellement dysfonctionnel.

Je ferais une distinction claire entre les opérations de changement d'état et les opérations de lecture (CQS Command Query Separation ). Pour les opérations de changement d'état, j'utiliserais une sorte d'infrastructure de messagerie et j'irais au feu et j'oublierais. Pour les requêtes, vous utiliseriez une communication de réponse de demande synchrone et pourriez utiliser une API http ou simplement aller directement à votre magasin de données.

Si vous utilisez la messagerie, vous pouvez également consulter la publication d'abonnement pour déclencher des événements entre les services.

Un autre point à considérer est le partage de données (transactionnel) (par opposition aux vues en lecture seule) si vous exposez votre état interne, le lecteur pourrait obtenir le mauvais état de vos données, ou la mauvaise version, et pourrait également verrouiller vos données?

Enfin et surtout, essayez de faire tout votre possible pour garder vos services autonomes (au moins au niveau logique).

J'espère que cela a du sens.

25
Sean Farmar

Cela dépend de la raison pour laquelle vous avez besoin de ces données. Si c'est pour l'interface utilisateur, c'est parfaitement bien. De plus, c'est comme ça que ça devrait être. Chris Richardson a une belle explication à ce sujet concept , et Sam Newman a un excellent article sur un concept très similaire appelé Backends for Frontends .

Mais si vous en avez besoin pour une certaine logique, il est probable que vos limites de service soient erronées.

Il y a plusieurs caractéristiques que le bon sens nous dit nos services devraient posséder . Elles sont:

  1. Couplage bas. Si vous apportez des modifications au service A, vous ne voulez pas qu'elles affectent le service B.
  2. Haute cohésion. Si vous devez implémenter une fonctionnalité, vous souhaitez que le moins de services possible soit affecté.
  3. Grande autonomie. Si un service échoue, vous ne voulez pas que tout le système soit arrêté.
  4. Granularité correcte. Vous ne voulez pas que vos services soient trop bavards, car votre le réseau est plus une chose complexe que vous ne le pensez.
  5. Les services doivent communiquer via des événements. Vous ne voulez pas que votre service soit au courant les uns des autres car il réduit la maintenabilité. Réfléchissez à ce qui se passe si vous devez ajouter un nouveau service.
  6. Données décentralisées. Un service ne doit pas partager la façon dont les informations sont stockées. Tout comme un bon objet, il expose le comportement, pas les données.
  7. Chorégraphie de service sur orchestration.

Pour ce faire, traitez vos frontières de services comme des capacités commerciales . Un processus formel d'identification des limites de service ressemble à ceci:

  1. Identifiez les limites de niveau supérieur. J'aime les considérer comme des étapes que votre organisation doit suivre pour atteindre son objectif commercial, obtenir sa valeur commerciale. Vous pouvez l'idée d'étapes de base en jetant un oeil à chaîne de valeur de Porter .
  2. Au sein de chaque service, approfondissez. Identifier les unités autonomes des enfants avec leurs propres responsabilités.
  3. Attention à la façon dont ils communiquent. Les services corrects communiquent principalement via des événements. Pensez à votre structure organisationnelle. La communication à l'intérieur d'eux est assez intensive, bien que généralement quelques événements externes soient exposés.

Un exemple d'application de cette approche pourrait être intéressant.

13
Zapadlo

Je pencherais également pour la deuxième approche par défaut, mais peut-être pas dans votre "passerelle API", mais je considérerais qu'il est tout à fait raisonnable de créer un micro-service nouveau dont le seul but était de orchestrez les demandes vers d'autres micro-services et représentez les données sous une forme de niveau supérieur. Dans une architecture de micro-services, je serais opposé à ce que les micro-services "de base" communiquent directement entre eux.

Pour rendre cela un peu moins subjectif, disons qu'un service dépend de un autre si le premier nécessite des données ou des services du second, directement ou indirectement. En termes mathématiques, nous voulons que cette relation soit un ordre partiel et non un précommande . Sous forme de diagramme, si vous avez tracé votre diagramme de dépendance, vous devriez obtenir un diagramme de Hasse et ne pas avoir de cycles (dirigés). (Dans un diagramme de Hasse, les bords sont implicitement dirigés du bas vers le haut.) À titre indicatif, vous souhaitez que les trajets de haut en bas soient généralement plus courts. Cela signifie que vous voulez dépendre plus directement des choses par défaut. Les raisons en sont que cela minimise le nombre de problèmes pouvant survenir pour une demande particulière, minimise les frais généraux et réduit la complexité. Ainsi, dans le cas "idéal" de cette métrique, le diagramme de Hasse n'aurait que deux niveaux. Bien sûr, il existe de nombreuses raisons pour lesquelles vous souhaiterez peut-être introduire des services intermédiaires tels que la mise en cache, la consolidation, l'équilibrage de charge, la gestion des pannes.

Pour approfondir votre deuxième préoccupation d'avoir l'API Gateway "intelligente", un modèle qui gagne du terrain maintenant avec des cadres comme Falcor et Relay / GraphQL est de faire des requêtes plus de spécifications sur ce qu'il faut faire pour que la "passerelle API" puisse exécuter ces spécifications de manière générique sans avoir à savoir ce que GetTimeline implique. Au lieu de cela, il obtiendrait une demande telle que "demander ces informations utilisateur au service utilisateur et obtenir ces messages à partir du service postal" ou autre chose.

1

Je soupçonne que votre besoin de services de "s'appeler" les uns les autres indique que vous opérez avec un système qui n'a pas été bien architecturé, car ce besoin de microservices de "s'appeler" les uns les autres est une forme de couplage qui apparaît rarement lorsque les microservices sont conçus de manière appropriée.

Pouvez-vous expliquer davantage le problème que vous essayez de résoudre? En anglais simple?

0
Ben