Viele-zu-viele-Assoziationen in Microservices

13

Ich habe derzeit zwei Microservices. Wir werden sie anrufen Aund B.

Die Datenbank unter Microservice Aenthält die folgende Tabelle:

A
|-- users

Die Datenbank unter Microservice Benthält die folgende Tabelle:

B
|-- trackers

Die Anforderungen besagen dies usersund trackershaben eine Viele-zu-Viele-Beziehung.

Ich bin mir nicht sicher, wie ich das in einer Microservices-Architektur richtig handhaben soll.

Ich konnte sehen, dass dies auf drei Arten funktioniert:

  1. Dem user_trackersMicroservice wird eine Tabelle hinzugefügt A. Dies verhält sich ähnlich wie eine Join-Tabelle, die "Fremdschlüssel" für usersund enthält trackers.
  2. Dem ownersMicroservice wird eine Tabelle hinzugefügt B. Diese Tabelle verhält sich ähnlich wie eine polymorphe Verknüpfungstabelle. Dies würde es jedem Dienst ermöglichen, eine Zuordnung zu einem Tracker herzustellen. Dies könnte ungefähr so ​​aussehen: B |-- trackers |-- owners |-- owner_id |-- owner_type |-- tracker_id
  3. Führen Sie Aufzeichnungen für usersund trackersin jedem Microservice. Halten Sie sie mit einer Art Pubsub-System synchron.

Ich wollte ursprünglich Option 2 wählen, weil mir gefallen hat, dass die Transaktionsgrenzen erhalten bleiben. Ich kann einen Tracker erstellen und ihn atomar mit etwas verknüpfen. Es scheint jedoch nicht für den Mikroservice geeignet zu sein B. Warum sollte sich Microservice Bdarum kümmern, dass Microservice Aeine Assoziation erstellen möchte?

Ich habe das Gefühl, dass es hier wahrscheinlich ein gutes Muster gibt, das mir nicht bekannt ist. Ist eine der von mir festgelegten Optionen sinnvoll? Gibt es eine andere Option, die sinnvoller sein könnte?

Anthonator
quelle

Antworten:

12

Zunächst würde ich mit der Domainbeschreibung beginnen. Sie haben nicht erwähnt, worum es geht (ich kann es mir vorstellen, aber es wäre nur eine Vermutung). Danach würde ich versuchen, es mithilfe von Wertschöpfungskettenanalyse oder Business-Capability-Mapping zu zerlegen . Und erst danach würde ich über die Umsetzung nachdenken.

In Anbetracht Ihres Problems fällt mir als Erstes ein, dass Sie Ihre Servicegrenzen falsch identifiziert haben, einfach weil sie die Daten des anderen benötigen. Sie wollen doch nicht mit einem verteilten Monolithen enden, oder?

Die zweite Sache ist, dass Sie Ihre Domain wahrscheinlich nicht gut genug durchgearbeitet haben. Welches Konzept wird mit usersTabelle dargestellt? Ist es ein registered usermit allen Informationen und Verhaltensweisen, die für die Registrierung erforderlich sind? Sind Sie sicher, dass es das richtige Konzept für die Kommunikation ist trackers(was auch immer es ist)? Wenn ich es richtig verstanden habe, geht es bei Option 2 genau darum: Einführung des ownerKonzepts, das Ihrer Domain viel näher kommt. Wenn es wirklich so ist, bin ich auch für Option 2.

Für Microservice B scheint dies jedoch nicht möglich zu sein. Warum sollte sich Microservice B darum kümmern, dass Microservice A eine Assoziation erstellen möchte?

Es geht nur um Grenzen. Ich denke, Sie möchten Microservices um Entitäten herum bilden. Hier ist SOA mit seiner mehrschichtigen Servicearchitektur gescheitert . Der bessere Ansatz besteht darin, Dienste zu erstellen, die bestimmte Geschäftsfunktionen darstellen, sodass sowohl Daten als auch Verhalten erfasst werden. Aus praktischer Sicht geht es darum, Services für Geschäftsprozesse oder Anwendungsfälle zu erstellen. Beispielsweise könnten Sie einen Dienst für die Benutzerregistrierung haben. Es enthält die Daten und das Verhalten des Benutzers, die zum Registrieren eines Benutzers erforderlich sind. Das Konzept von userwird also auf natürliche Weise gebildet und gehört nur zu Dienst A. Und dies bringt mich zum nächsten Punkt: Die andere Art, über Dienste nachzudenken, ist ein begrenzter Kontext . Es ist eine gute Praxis, Dienste und begrenzte Kontexte aufeinander abzustimmen.

Wenn der Benutzer registriert ist, kann ein UserCreatedEreignis ausgegeben werden. Ihr zweiter Service interessiert sich wohl dafür. Nach Erhalt könnte also eine völlig andere Entität geschaffen werden, beispielsweise eine OwnerEntität (was auch immer das ist). Ich bin mir ziemlich sicher, dass es viele interessante Kooperationen zwischen ihm und dem trackerUnternehmen gibt - halten Sie sie in einem einzigen Dienst.

Seien Sie bei Option 3 äußerst vorsichtig. Wenn Sie Daten kopieren, folgt die Funktionalität. Dies führt zu einer engen Kopplung. Und nicht mit dem CQRS- Begriff abdecken , es geht nicht um die Datensynchronisation zwischen Diensten über Ereignisse.

Zapadlo
quelle
Ich liebe den Begriff "verteilter Monolith", aber die Art und Weise, wie er in dem von Ihnen angegebenen Link definiert ist, scheint nicht direkt mit der Frage hier in Zusammenhang zu stehen. Die Art und Weise, wie Sie es verwenden, hängt mit der Kopplung zwischen Diensten zusammen, und der Artikel konzentriert sich auf binäre Abhängigkeiten. Ich denke, die Art und Weise, wie Sie sie verwenden, ist überlegen, aber ich habe Mühe, eine Referenz zu finden, die sie auf diese Weise klar definiert.
JimmyJames
Ich habe immer gesprächige Dienste in die Kategorie "verteilter Monolith" aufgenommen, die nicht weit verbreitet ist.
Zapadlo
6

Zapadlos Antwort enthält viele gute Informationen und Argumente. Ich werde hier ein paar praktische Ratschläge hinzufügen, die es möglicherweise einfacher machen, Ihre Probleme und die Ratschläge in dieser Antwort zu bearbeiten.

Die Art und Weise, wie Sie Ihre Entwurfsfrage formuliert haben, bezieht sich auf Datenbankstrukturen und darauf, wie Sie eine neue Anforderung für Ihre Strukturen in diese einfügen können. Dies bedeutet, dass Sie das Service-Design aus Ihrem Datenmodell erstellen. Was ich zum Beispiel nicht sehe, ist, wie auf die Beziehung zwischen Benutzern und Trackern zugegriffen oder diese verwendet werden soll.

Beim Service-Design ist die Struktur der Schnittstelle das Wichtigste am Design. Tatsächlich ist die Implementierung im Vergleich insbesondere bei Mikrodiensten nahezu irrelevant. Der Grund dafür ist, dass nach dem Einrichten Ihres Dienstes alle Abhängigkeiten von Ihrem Dienst nur auf der Schnittstelle bestehen sollten. Wenn Sie es richtig machen, sollten Sie in der Lage sein, die Implementierung ohne Verbraucher vollständig neu zu schreiben. Und das ist der Hauptvorteil der Autonomie. Es interessiert niemanden, wie du es gebaut hast. Sie brauchen es nur, um so zu funktionieren, wie Sie es kommuniziert haben.

Bevor jemand bestimmen kann, wie dies in der Datenbank aussieht oder wo Sie dies möchten, müssen Sie wirklich erklären, wie diese Informationen verwendet werden. Ist dies etwas, das durch einen Dienst verfügbar gemacht wird, oder handelt es sich um eine Art von Daten, die Sie für die Analyse mischen möchten?

Nebenbei bemerkt würde ich bidirektionale Abhängigkeiten um fast jeden Preis vermeiden. Wenn Sie Abhängigkeiten haben, möchten Sie wirklich, dass nur eine Seite über die andere Bescheid weiß. Sobald die Abhängigkeiten in beide Richtungen verlaufen, werden sie im Wesentlichen zu einer atomaren Einheit.

JimmyJames
quelle
0

Vieles davon hängt von der Domain selbst ab. Wenn ein Benutzer mit Null-Trackern keinen Sinn ergibt, muss der Benutzerdienst über Tracker Bescheid wissen. Wenn ein Tracker einen Benutzer haben muss, müssen Tracker über Benutzer Bescheid wissen. Wenn etwas wie ein Tracker mit mehreren Eigentümern oder die Möglichkeit, einen Tracker von einem Benutzer auf einen anderen zu übertragen, sinnvoll ist, gehören diese Informationen möglicherweise zu einem anderen Dienst.

Zeichen
quelle
0

Frage: Warum werden Ihre Daten entlang der Datentabellen getrennt?

Ich würde eher zu Option 3 gehen: Die Dienste sind völlig getrennt und können die jeweiligen Fragen beantworten, die sie möglicherweise beantworten müssen. Darüber hinaus sind sie viel widerstandsfähiger. Seien Sie jedoch vorsichtig, Ihre Dienste können die Synchronisierung aufheben, wenn sie Ereignisse verpassen. Dies kann jedoch durch eventuelle Konsistenz behoben werden.

Sie könnten auch in Betracht ziehen, beide Dienste zusammenzuführen. Wenn beide nicht antworten können, ohne sich gegenseitig zu kennen, würde ich sie einfach zusammenführen, da sie wahrscheinlich Teil einer einzelnen Domain sind.

Christian Sauer
quelle
Dies ist Teil der Religion der Mikrodienste, dass jeder Dienst volle Autonomie benötigt. Thomas Erl beschreibt es als eines der Prinzipien der Serviceorientierung in "Principles of Service Design" c. 2008.
JimmyJames
@JimmyJames Als jemand, der selbst eine MS-Architektur schreibt: Es gibt viele Debatten über die Frage, wie groß eine MS sein sollte. In diesem Fall spielt die Größe möglicherweise keine Rolle, da die Dienste möglicherweise nicht richtig getrennt sind - z. B. nicht entlang von Tabellen oder Geschäftsdomänen.
Christian Sauer
Richtig. Das Problem ist, dass es derzeit einen großen Frachtkult um Microservices gibt. Ich sehe viele Leute, die Microservices implementieren, weil die coolen Kids das tun und die Kompromisse nicht berücksichtigen oder verstehen. Ich habe zum Beispiel das Gefühl, dass viele Leute denken, dass es bei der MS-Autonomie um Technologie und „die Cloud“ geht. Ich sehe es eher als Lösung für ein organisatorisches Problem. Das Dereferenzieren von Handelszeigern für Netzwerk-E / A ist äußerst kostspielig. Sie können dies nicht einfach gedankenlos anwenden und erwarten, dass die Dinge gut laufen.
JimmyJames
@JimmyJames Ich denke, es kann auch um Technologie gehen - besonders wenn bestimmte Technologien für einige Domänen gut geeignet sind, für andere jedoch nicht. Wir verwenden C # und Python für unsere MSs. Einiges davon ist auf organisatorische Probleme zurückzuführen ("Ich habe c # seit 20 Jahren programmiert, ich muss keine neuen untypisierten Sprachen lernen!"). - aber auch aufgrund der Natur unseres Systems. Die Data Science-Teile werden am besten in Python erstellt, während einige Infrastruktur- und Webaufgaben am besten in C # ausgeführt werden.
Christian Sauer
Klar, das ist ein ziemlich triftiger Grund dafür. Das Problem, das ich sehe, ist, dass die Leute jeden Dienst in einen separaten Knoten aufteilen wollen, einfach weil "wir Microservices durchführen", selbst wenn alles mit demselben Code auf derselben Plattform geschrieben ist und es eine Menge Abhängigkeiten zwischen Diensten gibt. In diesem Fall haben Microservices wirklich keinen großen Nutzen, und Sie haben eine ganze Reihe neuer Probleme hinzugefügt.
JimmyJames