Comment partager le DTO entre les microservices?

33

Mon scénario est le suivant.

Je suis en train de concevoir un système conçu pour recevoir des données de différents types de capteurs, puis les convertir et les conserver pour les utiliser ultérieurement par divers services frontaux et d'analyse.

J'essaie de concevoir chaque service pour qu'il soit aussi indépendant que possible, mais j'ai des problèmes. L'équipe a décidé d'un DTO que nous aimerions utiliser. Les services tournés vers l'extérieur (destinataires des données des capteurs) recevront les données à leur manière, puis les convertiront en un objet JSON (le DTO) et les enverront au Message Broker. Les consommateurs des messages sauront alors exactement comment lire les messages de données du capteur.

Le problème est que j'utilise le même DTO dans quelques services différents. Une mise à jour doit être implémentée dans plusieurs emplacements. De toute évidence, nous l'avons conçu de telle manière que quelques champs supplémentaires ou manquants dans le DTO ici et il n'y a pas beaucoup de problème jusqu'à ce que les services aient été mis à jour, mais cela me dérange toujours et me donne l'impression que je suis commettre une erreur. Cela pourrait facilement devenir un mal de tête.

Suis-je en train de mal architecturer le système? Sinon, quels sont les moyens de contourner ce problème, ou du moins de soulager mes inquiétudes?

nbaughman
la source
Quel type de DTO partagez-vous et quel protocole utilisez-vous entre les services? C'est correct de partager, par exemple, le protofichier pour gRPC ou le avroschéma pour Kafka et de générer les DTO dans les deux services, mais je ne partagerais pas une bibliothèque partagée entre deux projets.
Vincent Savard
Chaînes JSON codées et AMQP. Je préférerais ne rien utiliser de spécifique à la langue.
nbaughman

Réponses:

38

Mon conseil? Ne partagez pas ces DTO entre les applications de tout type de bibliothèque. Ou du moins, ne faites pas ça maintenant.

Je sais, cela semble très contre-intuitif. Vous dupliquez du code, non? Mais ce n'est pas une règle commerciale, vous pouvez donc être plus flexible.

Le service qui envoie le DTO doit être rigide dans son contrat de message, comme une API Rest. Le service ne peut pas modifier le DTO d'une manière qui pourrait casser les autres services qui consomment déjà les informations du DTO.

Lorsqu'un nouveau champ est ajouté lors du DTO, vous ne mettez à jour les autres services qui consomment ce DTO que s'ils ont besoin du nouveau champ. Sinon, oubliez ça. En utilisant JSON comme type de contenu, vous avez la possibilité de créer et d'envoyer de nouveaux attributs sans casser le code des services qui ne mappent pas ces nouveaux champs sur ses versions réelles de DTO.

Mais si cette situation vous dérange vraiment, vous pouvez suivre la règle des trois :

Il y a deux "règles de trois" dans la réutilisation: (a) il est trois fois plus difficile de construire des composants réutilisables que les composants à usage unique, et (b) un composant réutilisable doit être testé dans trois applications différentes avant qu'il ne soit suffisamment général à accepter dans une bibliothèque de réutilisation.

Essayez donc d'attendre un peu plus avant de partager ce DTO entre les services.

Dherik
la source
1
Très apprécié. C'est vraiment l'une des très rares préoccupations majeures que j'ai à l'avenir. Pas assez pour me tenir éveillé la nuit, mais assez pour m'inquiéter.
nbaughman
4
Les DTO dupliqués (dans des services différents et très indépendants) ne violent pas DRY. C'est ça.
Laiv
3
Vraisemblablement, il n'y a aucune raison de ne pas copier le code source DTO directement d'un projet à un autre, en tant qu'opération unique, bien que toutes les parties non requises dans le nouveau projet devraient probablement être supprimées.
bdsl
1
Même un service entier peut être supprimé, ce qui ne cause aucun problème majeur à l'ensemble du système. Idéalement.
Laiv
4
Pour clarifier l'essence de la réponse, lors du développement de microservices, chaque service doit être développé comme s'il ne connaissait pas les autres services, à l'exception des contrats réels qu'il pourrait nécessiter.
Jonathan van de Veen
12

En ce qui concerne les microservices, les cycles de vie de développement des services doivent également être indépendants. *

Différents SLDC et différentes équipes de développement

dans un véritable système MS, il pourrait y avoir plusieurs équipes impliquées dans le développement de l'écosystème, chacune en charge d'un ou plusieurs services. À leur tour, ces équipes peuvent être situées dans différents bureaux, villes, pays, plan ... Peut-être, elles ne se connaissent même pas, ce qui rend le partage des connaissances ou du code très difficile (si possible). Mais cela pourrait être très pratique car le code partagé implique également une sorte de raisonnement de partage et quelque chose d'important à rappeler est que, tout ce qui a du sens pour une équipe spécifique, n'a pas à le faire pour une autre équipe. Par exemple, étant donné le client DTO , cela peut être différent selon le service en jeu, car les clients sont interprétés (ou vus) différemment de chaque service.

Différents besoins, différentes technologies

Les SLDC isolés permettent également aux équipes de choisir la pile qui convient le mieux à leurs besoins. L'imposition de DTO implémentés dans une technologie spécifique limite la capacité de choix des équipes.

Les DTO ne sont ni des règles commerciales ni des contrats de services

Que sont vraiment les DTO? Objets simples sans autre objectif que de déplacer des données d'un côté à l'autre. Sacs de getters et setters. Ce n'est pas le genre de «connaissances» qui mérite d'être réutilisé, dans l'ensemble parce qu'il n'y a aucune connaissance du tout. Leur volatilité en fait également de mauvais candidats au couplage.

Contrairement à ce que Dherik a déclaré, il doit être possible pour un service de changer ses DTO sans avoir à effectuer d'autres services en même temps. Les services doivent être des lecteurs tolérants, des écrivains tolérants et tolérants aux défaillances . Sinon, ils provoquent le couplage de telle manière que l'architecture de service n'a aucun sens. Encore une fois, et contrairement à la réponse de Dherik, si trois services nécessitent exactement les mêmes DTO, il est probable que quelque chose s'est mal passé lors de la décomposition des services.

Différentes affaires, différentes interprétations

Bien qu'il puisse y avoir (et il y aura) des concepts transversaux entre les services, cela ne signifie pas que nous devons imposer un modèle canonique pour forcer tous les services à les interpréter de la même manière.

Étude de cas

Supposons que notre entreprise dispose de trois départements: service client , ventes et expédition . Supposons que chacune de ces versions libère un ou plusieurs services.

Le service client, en raison de sa langue de domaine , met en œuvre des services autour du concept de clients, où les clients sont des personnes . Par exemple, les clients sont modélisés comme nom , prénom , âge , sexe , e - mail , téléphone , etc.

Supposons maintenant que les services de vente et d' expédition modélisent également leurs services en fonction de la langue de leur domaine respectif. Dans ces langues, le concept client apparaît lui aussi mais avec une subtile différence. Pour eux, les clients ne sont pas (nécessairement) des personnes . Pour les ventes , les clients sont un numéro de document, une carte de crédit et une adresse de facturation , pour l' expédition un nom complet et une adresse de livraison aussi.

Si nous forçons Sales and Shipping à adopter le modèle canonique de données du service client , nous les forçons à traiter les données inutiles qui pourraient finir par introduire une complexité inutile si elles doivent maintenir la représentation entière et maintenir les données client en synchronisation avec le service client. .

Liens connexes


* Voici où réside la force de cette architecture

Laiv
la source
Merci! Les études de cas sont en fait ce qui m'a aidé à décider de partager ou non les DTO. Maintenant, je suis sûr de savoir pourquoi je ne voulais pas les partager.
Igor
8

J'essaie de concevoir chaque service pour qu'il soit le plus indépendant possible

Vous devriez publier des événements . Les événements sont certains types de messages qui représentent un fait solide sur quelque chose qui s'est produit à un moment donné.

Chaque service devrait avoir une responsabilité très bien définie et devrait avoir la responsabilité de publier les événements liés à cette responsabilité.

De plus, vous souhaitez que vos événements soient des événements liés à l'entreprise, et non des événements techniques. Par exemple, préférez un OrderCancelledévénement à un OrderUpdatedavec status: "CANCELLED".

De cette façon, lorsqu'un service doit réagir à une commande annulée, il a juste besoin d'écouter un type de message particulier, qui ne transporte que des données pertinentes pour cet événement. Par exemple, un a OrderCancelledprobablement juste besoin d'un order_id. Quel que soit le service qui doit réagir à cela, il a déjà stocké tout ce qu'il doit savoir sur la commande dans son propre magasin de données.

Mais si le service n'avait que des OrderUpdatedévénements à écouter, il devrait alors interpréter le flux des événements, et il dépendait désormais du bon de livraison pour se terminer correctement lorsqu'une commande était annulée.

Dans votre cas, cependant, comme la publication des données sont des capteurs, il serait logique d'avoir un service, écouter les événements et publier un nouveau flux de « événements d'affaires », par exemple TemperatureThresholdExceeded, TemperatureStabilised.

Et faites attention à ne pas créer trop de microservices. Les microservices peuvent être un excellent moyen d'encapsuler la complexité, mais si vous ne découvrez pas de limites de service appropriées, votre complexité réside dans l'intégration de service. Et c'est un cauchemar à entretenir.

Il vaut mieux avoir trop peu, trop de services, que d'avoir trop, trop petits services.

Pete
la source
Je suis définitivement d'accord. Les données du capteur entrent directement dans un microservice qui analyse le message et le transforme en un format convenu à l'échelle de l'organisation avant de le publier au courtier. Nous aurons certains services qui liront le message et le conserveront dans une base de données, et d'autres qui effectueront l'analyse du message et feront leur propre chose avec. Chaque service, par nature de l'entreprise, n'a pas grand-chose à faire, ce qui conduit (espérons-le) à des services assez simples.
nbaughman
2
@ Nickdb93 - Dans votre cas, comme vous publiez des données de capteur, il peut être judicieux d'avoir un service, d'écouter les événements et de publier un nouveau flux "d'événements commerciaux", par exemple TemperatureThresholdExceeded, TemperatureStabilised. (ajouté à la réponse)
Pete