Dans une architecture de microservices faiblement couplée, comment gardez-vous une trace de vos dépendances?

9

Un choix d'architecture de haut niveau populaire dans les programmes modernes est un système de microservices basé sur REST. Cela présente plusieurs avantages tels qu'un couplage lâche, une réutilisation facile, une restriction limitée sur les technologies pouvant être utilisées, une grande évolutivité, etc.

Mais l'un des problèmes que je prévois dans une telle architecture est la mauvaise visibilité sur les dépendances d'une application. Par exemple, supposons que j'ai une application qui utilise quotidiennement un ensemble d'appels REST. Cette application utilise également un deuxième ensemble d'appels REST, mais seulement une fois par trimestre. Si je devais analyser les journaux de la semaine dernière, je verrais tous les cals quotidiens, mais je ne verrais probablement pas les appels trimestriels. Quand vient le temps de refactoriser, les appels trimestriels sont à haut risque de rupture.

Quels modèles ou outils peuvent être utilisés pour réduire ce risque et fournir une plus grande visibilité sur les dépendances d'une architecture à couplage lâche?

David dit de réintégrer Monica
la source
1
C'est exactement pourquoi le couplage lâche peut être mauvais. Lorsqu'il n'y a pas de dépendances de temps de compilation, le seul moyen de détecter les erreurs, et vous ne les détectez jamais toutes, est d'utiliser des tests automatisés. La solution est un certain type de test automatisé, qui comprend probablement des tests unitaires ainsi que des tests d'intégration.
Frank Hileman
@FrankHileman Testing aide évidemment, mais j'ai du mal à croire que c'est la seule solution qui existe. De plus, il existe de nombreux langages qui n'ont pas de vérifications au moment de la compilation (c'est-à-dire JS ou Python), donc même avec un couplage étroit, vous auriez toujours des problèmes.
David dit de réintégrer Monica le
1
Les systèmes de type statique peuvent détecter un grand nombre d'erreurs pendant la phase de compilation. La seule compensation pour l'absence d'un tel système est le test automatisé, à ma connaissance. La détection d'erreurs statiques via des preuves automatisées ou simplement la compilation sera toujours plus fiable que les tests.
Frank Hileman
Une façon possible pourrait être d'implémenter le client API de chaque service séparément et, en incluant ces clients comme dépendances du projet. Avec l'API, les clients auraient également plus de facilité à retracer la version du service que nous consommons.
Laiv
@Laiv Je suis particulièrement curieux des services RESTful, donc ce n'est pas vraiment une option car n'importe qui peut envoyer des requêtes HTTP plus ou moins.
David dit de rétablir Monica le

Réponses:

4

Quels modèles ou outils peuvent être utilisés pour réduire ce risque

Garder vos API et vos capacités commerciales rétrocompatibles.

fournir une meilleure visibilité sur les dépendances d'une architecture à couplage lâche

Contrôles de santé.

Mon service est un client pour votre capacité API mensuelle. Mais mon service est le client de votre API à chaque fois que mon service est en cours d'exécution. Mon service se réveille donc toutes les 10 minutes, ou autre, se connecte à votre API mensuelle et exécute le protocole pour s'assurer que la capacité dont mon service a besoin est toujours disponible.

Ainsi, vos journaux vous montreront à quelle fréquence un autre service vérifie que chaque service particulier que vous proposez est toujours disponible, tout comme il vous montre à quelle fréquence chaque service particulier que vous proposez est réellement utilisé.

VoiceOfUnreason
la source
1

Il existe au moins deux emplacements où vous pouvez trouver les dépendances:

  • Configuration. L'accès aux API externes nécessite de connaître un tas d'informations sur chacune de ces API. ID d'accès, clés secrètes, points de terminaison. Tout cela ne peut pas être dans le code, car ces informations vont changer. Par exemple, j'ai récemment commencé à migrer tous mes microservices vers SSL. Cela signifie que chaque service qui s'appuie sur celui en cours de migration doit être reconfiguré pour pointer vers la https://version au lieu de http://. Je suis content que les points d'extrémité soient dans la configuration au lieu d'être codés en dur.

  • Interfaces. Vous n'accédez pas à un service directement à partir de votre code, car la version de l'API va changer et vous pouvez même décider de passer à une autre API. Au lieu de cela, vous créez une couche d'abstraction et utilisez la dépendance via une interface. En suivant une logique commune lors de la création de ces interfaces, vous pouvez vous faciliter la vie plus tard lors de la recherche des dépendances.

Quand vient le temps de refactoriser, les appels trimestriels sont à haut risque de rupture.

C'est à cela que servent les tests de régression.

Vous ne pouvez pas simplement regarder le code, le changer et vous assurer que rien n'a été cassé. Cela ne fonctionnera pas dans une architecture de microservices. Cela ne fonctionnera pas non plus dans une application monolithique. Un compilateur peut détecter certaines des erreurs que vous introduirez lors de la modification du code. Dans certaines langues, comme Haskell, le compilateur peut être très performant et détecter la plupart des erreurs; Cependant, les compilateurs pour les langues traditionnelles ne feront pas grand-chose pour vous. Si vous n'avez pas de tests, vous êtes foutu. La présence de microservices n'est pas pertinente.

Arseni Mourzenko
la source
-2

Les API REST sont spécifiées de manière lâche, donc à un moment donné, il peut être utile de passer à gRPC, google protobufs ou Thrift pour définir une interface RPC, puis la version.

Patrick
la source
2
Cela pourrait être mieux en tant que commentaire ... mais honnêtement, cela n'explique pas grand-chose.
David dit de réintégrer Monica le
C'est suffisant. Une API de repos n'a pas de dépendance de temps de compilation spécifique sur un autre service car le lien entre les deux n'est qu'un appel de repos HTTP, quelque chose comme un hôte et un chemin. Avec gRPC, ou Protobuf ou Thrift, une interface est définie qui est utilisée pour générer du code. Le code généré est compilé et versionné, puis vos services sont construits sur ces interfaces. Le résultat étant que chaque service dépend clairement d'une ou plusieurs de vos autres interfaces de service. J'espère que cela clarifie ma réponse!
Patrick