Möglichkeiten zur gemeinsamen Nutzung von DTO über Microservices hinweg?

33

Mein Szenario ist wie folgt.

Ich entwerfe ein System, mit dem Daten von verschiedenen Sensortypen empfangen und konvertiert und anschließend für die spätere Verwendung durch verschiedene Front-End- und Analysedienste beibehalten werden können.

Ich versuche, jeden Dienst so unabhängig wie möglich zu gestalten, aber ich habe einige Probleme. Das Team hat sich für einen DTO entschieden, den wir verwenden möchten. Die nach außen gerichteten Dienste (Empfänger von Sensordaten) empfangen die Daten auf eigene Weise, konvertieren sie dann in ein JSON-Objekt (das DTO) und senden sie an den Message Broker. Die Verbraucher der Nachrichten wissen dann genau, wie sie die Sensordatennachrichten lesen sollen.

Das Problem ist, dass ich das gleiche DTO in ein paar verschiedenen Diensten verwende. Ein Update muss an mehreren Stellen durchgeführt werden. Offensichtlich haben wir es so gestaltet, dass ein paar zusätzliche oder fehlende Felder im DTO vorhanden sind und es kaum Probleme gibt, bis die Dienste aktualisiert wurden, aber es nervt mich immer noch und ich fühle mich wie ich bin einen Fehler machen. Es könnte leicht zu Kopfschmerzen werden.

Mache ich eine falsche Systemarchitektur? Wenn nicht, wie kann ich das umgehen oder zumindest meine Sorgen lindern?

Nbaughman
quelle
Welche Art von DTOs teilen Sie und welches Protokoll verwenden Sie zwischen Diensten? Es ist in Ordnung, beispielsweise die protoDatei für gRPC oder das avroSchema für Kafka freizugeben und die DTOs in beiden Diensten zu generieren, aber ich würde keine gemeinsam genutzte Bibliothek zwischen zwei Projekten freigeben.
Vincent Savard
Codierte JSON-Zeichenfolgen und AMQP. Ich würde es vorziehen, nichts sprachspezifisches zu verwenden.
Nbaughman

Antworten:

38

Mein Rat? Teilen Sie diese DTOs nicht mit den Anwendungen in einer Bibliothek. Oder zumindest jetzt nicht.

Ich weiß, scheint sehr kontraintuitiv. Du duplizierst Code, richtig? Dies ist jedoch keine Geschäftsregel, sodass Sie flexibler sein können.

Der Dienst, der das DTO sendet, muss in seinem Nachrichtenvertrag genau wie eine Rest-API festgelegt sein. Der Dienst kann das DTO nicht so ändern, dass die anderen Dienste, die bereits Informationen aus dem DTO verbrauchen, beschädigt werden.

Wenn ein neues Feld für DTO hinzugefügt wird, aktualisieren Sie die anderen Dienste, die dieses DTO verwenden, nur, wenn sie das neue Feld benötigen. Ansonsten vergiss es. Wenn Sie JSON als Inhaltstyp verwenden, haben Sie die Flexibilität, neue Attribute zu erstellen und zu senden, ohne den Code der Dienste zu unterbrechen, die diese neuen Felder in seinen aktuellen Versionen von DTO nicht abbilden.

Aber wenn Sie diese Situation wirklich stört, können Sie der Dreierregel folgen :

Bei der Wiederverwendung gibt es zwei "Dreierregeln": (a) Es ist dreimal so schwierig, wiederverwendbare Komponenten zu erstellen wie Einwegkomponenten, und (b) eine wiederverwendbare Komponente sollte in drei verschiedenen Anwendungen ausprobiert werden, bevor sie allgemein genug ist in eine Wiederverwendungsbibliothek aufnehmen.

Warten Sie also etwas länger, bevor Sie dieses DTO für die Dienste freigeben.

Dherik
quelle
1
Sehr geschätzt. Dies ist wirklich eines der wenigen großen Anliegen, die ich vor mir habe. Nicht genug, um mich nachts wach zu halten, aber genug, um mir Sorgen zu machen.
Nbaughman
4
Doppelte DTOs (in verschiedenen und sehr unabhängigen Diensten) verletzen DRY nicht. Das ist es.
Laiv
3
Vermutlich gibt es dann keinen Grund, den DTO-Quellcode nicht als einmalige Operation direkt von einem Projekt in ein anderes zu kopieren, obwohl dann alle Teile, die im neuen Projekt nicht benötigt werden, wahrscheinlich gelöscht werden sollten.
BDSL
1
Sogar ein ganzer Dienst kann gelöscht werden, was keine größeren Probleme für das gesamte System verursacht. Im Idealfall.
Laiv
4
Um das Wesentliche der Antwort zu verdeutlichen, sollte bei der Entwicklung von Mikrodiensten jeder Dienst so entwickelt werden, als wüsste er nichts über die anderen Dienste, mit Ausnahme der tatsächlich erforderlichen Verträge.
Jonathan van de Veen
12

Auch bei Microservices sollten die Entwicklungszyklen der Services unabhängig sein. *

Verschiedene SLDC und verschiedene Entwicklerteams

In einem echten MS-System könnten mehrere Teams an der Entwicklung des Ökosystems beteiligt sein, die jeweils für einen oder mehrere Dienste zuständig sind. Diese Teams wiederum befinden sich möglicherweise in verschiedenen Büros, Städten, Ländern, Plänen ... Vielleicht kennen sie sich nicht einmal, was den Austausch von Wissen oder Code (wenn möglich) sehr schwierig macht. Dies kann jedoch sehr praktisch sein, da gemeinsam genutzter Code auch eine Art Argumentation für die gemeinsame Nutzung impliziert. Was auch immer für ein bestimmtes Team sinnvoll ist, muss es nicht für ein anderes Team sein. Beispielsweise kann es für den DTO- Kunden in Abhängigkeit vom jeweiligen Dienst unterschiedlich sein , da Kunden von jedem Dienst unterschiedlich interpretiert (oder gesehen) werden.

Unterschiedliche Bedürfnisse, unterschiedliche Technologien

Mit isolierten SLDCs können Teams auch den Stapel auswählen, der ihren Anforderungen am besten entspricht. Das Auferlegen von DTOs, die in einer bestimmten Technologie implementiert sind, schränkt die Auswahlmöglichkeiten der Teams ein.

DTOs sind weder Geschäftsregeln noch Dienstleistungsverträge

Was sind eigentlich DTOs? Einfache Objekte mit keinem anderen Ziel als dem Verschieben von Daten von einer Seite zur anderen. Taschen von Gettern und Setzern. Es ist nicht die Art von "Wissen", das es wert ist, wiederverwendet zu werden, insgesamt, weil es überhaupt kein Wissen gibt. Ihre Volatilität macht sie auch zu schlechten Kandidaten für eine Kopplung.

Entgegen der Aussage von Dherik muss es einem Dienst möglich sein, seine DTOs zu ändern, ohne dass andere Dienste gleichzeitig geändert werden müssen. Dienstleistungen sollten seine tolerant Leser, tolerant Schriftsteller und tolerant scheitern . Andernfalls verursachen sie eine Kopplung auf eine Weise, die die Dienstarchitektur sinnlos macht. Noch einmal, und im Gegensatz zu Dheriks Antwort, ist es wahrscheinlich, dass während der Zerlegung der Dienste etwas schief gelaufen ist, wenn drei Dienste genau dieselben DTOs benötigen.

Unterschiedliches Geschäft, unterschiedliche Interpretationen

Es könnte (und wird) Querschnittskonzepte zwischen den Diensten geben, aber das bedeutet nicht, dass wir ein kanonisches Modell auferlegen müssen, um alle Dienste zu zwingen, diese auf die gleiche Weise zu interpretieren.

Fallstudie

Nehmen wir an, unser Unternehmen hat drei Abteilungen: Kundendienst , Verkauf und Versand . Angenommen, jede dieser Versionen gibt einen oder mehrere Dienste frei.

Kundendienst aufgrund seiner Domain Sprache , implementiert Dienstleistungen rund um das Konzept der Kunden, wo die Kunden sind Personen . Beispielsweise werden Kunden als Name , Nachname , Alter , Geschlecht , E-Mail , Telefon usw. modelliert .

Angenommen, Vertrieb und Versand modellieren ihre Dienste auch entsprechend ihrer jeweiligen Domänensprache. In dieser Sprache ist der Begriff Kunde erscheint auch , aber mit einem feinen Unterschied. Für sie Kunden sind nicht (unbedingt) Personen . Für den Verkauf sind Kunden eine Belegnummer, eine Kreditkarte und eine Rechnungsadresse , für den Versand auch ein vollständiger Name und eine Lieferadresse .

Wenn wir Vertrieb und Versand dazu zwingen, das kanonische Datenmodell des Kundenservice zu übernehmen , zwingen wir sie dazu, mit unnötigen Daten umzugehen, was zu unnötiger Komplexität führen kann, wenn sie die gesamte Darstellung beibehalten und die Kundendaten mit dem Kundenservice synchron halten müssen .

Ähnliche Links


* Hier liegen die Stärken dieser Architektur

Laiv
quelle
Vielen Dank! Die Fallstudien haben mir tatsächlich dabei geholfen, festzustellen, ob ich DTOs teilen soll oder nicht. Jetzt bin ich mir sicher, warum ich sie nicht teilen wollte.
Igor
8

Ich versuche, jeden Dienst so unabhängig wie möglich zu gestalten

Sie sollten Ereignisse veröffentlichen . Ereignisse sind bestimmte Arten von Nachrichten, die eine solide Tatsache über etwas darstellen, das zu einem bestimmten Zeitpunkt passiert ist.

Jeder Dienst sollte eine genau definierte Verantwortung haben und die Verantwortung für die Veröffentlichung der Ereignisse im Zusammenhang mit dieser Verantwortung haben.

Darüber hinaus möchten Sie, dass Ihre Ereignisse geschäftsbezogene Ereignisse und keine technischen Ereignisse darstellen. ZB lieber OrderCancelledEvent als OrderUpdatedmit status: "CANCELLED".

Auf diese Weise muss ein Service, der auf eine stornierte Bestellung reagieren muss, nur einen bestimmten Nachrichtentyp abhören, der nur für dieses Ereignis relevante Daten enthält. ZB OrderCancelledbraucht ein wahrscheinlich nur ein order_id. Welcher Dienst, der darauf reagieren muss, hat bereits alles, was er über die Bestellung wissen muss, in einem eigenen Datenspeicher abgelegt.

Hätte der Dienst jedoch nur OrderUpdatedEreignisse zum Abhören, müsste er den Ereignisfluss interpretieren, und es sei nun abhängig, dass der Lieferauftrag korrekt abgeschlossen wird, wenn ein Auftrag storniert wird.

In Ihrem Fall jedoch als Sensordaten veröffentlichen, es Sinn machen könnte einen Dienst haben, hört auf die Ereignisse und veröffentlicht einen neuen Strom von „Business - Event“, zum Beispiel TemperatureThresholdExceeded, TemperatureStabilised.

Und seien Sie vorsichtig, wenn Sie zu viele Microservices erstellen. Microservices können eine großartige Möglichkeit sein, Komplexität zu verkapseln. Wenn Sie jedoch keine geeigneten Servicegrenzen entdecken, liegt Ihre Komplexität in der Serviceintegration. Und das ist ein Albtraum.

Es ist besser, zu wenige, zu große Dienste zu haben, als zu viele, zu kleine Dienste zu haben.

Pete
quelle
Ich stimme definitiv zu. Die Sensordaten werden direkt in einen Mikrodienst übertragen, der die Nachricht analysiert und in ein Format umwandelt, das für die gesamte Organisation vereinbart wurde, bevor sie an den Broker gesendet werden. Wir werden einige Dienste haben, die die Nachricht lesen und in einer Datenbank speichern, und andere, die eine Analyse der Nachricht durchführen und ihre eigene Sache damit machen. Jeder Dienst hat von Natur aus nicht viel zu tun, was (hoffentlich) zu recht einfachen Diensten führt.
Nbaughman
2
@ Nickdb93 - Wenn Sie Sensordaten veröffentlichen, kann es in Ihrem Fall sinnvoll sein, einen Service zu haben, die Ereignisse zu verfolgen und einen neuen Stream von "Geschäftsereignissen" zu veröffentlichen, z. B. TemperatureThresholdExceeded, TemperatureStabilised. (zur Antwort hinzugefügt)
Pete