Shared Domain-Modell zwischen verschiedenen Microservices

61

Stellen Sie sich ein Szenario mit zwei verschiedenen Mikrodiensten vor. Der eine kümmert sich um die Authentifizierung innerhalb des Dienstes, der andere um die Benutzerverwaltung. Sie haben beide das Konzept eines Benutzers und werden durch gegenseitige Anrufe über Benutzer sprechen.

Wohin würde das Domain-Modell eines "Users" gehören? Würden beide eine unterschiedliche Darstellung dessen haben, was ein Benutzer auf der Ebene der Datenbank ist? Was ist, wenn wir ein UserDTO zur Verwendung in API-Aufrufen haben, würden beide eines für ihre jeweiligen APIs haben?

Was ist die allgemein akzeptierte Lösung für diese Art von Architekturproblemen?

Kristof
quelle

Antworten:

36

In einer Microservices-Architektur ist jede absolut unabhängig von den anderen und muss die Details der internen Implementierung verbergen.

Wenn Sie das Modell teilen, verbinden Sie Microservices und verlieren einen der größten Vorteile, bei dem jedes Team seinen Microservice ohne Einschränkungen entwickeln kann und wissen muss, wie sich andere Microservices weiterentwickeln. Denken Sie daran, dass Sie sogar unterschiedliche Sprachen in jeder Sprache verwenden können. Dies wäre schwierig, wenn Sie mit der Kopplung von Microservices beginnen.

Wenn sie zu verwandt sind, sind sie vielleicht wirklich eins, wie @soru sagt.

Verwandte Fragen:

gabrielgiussi
quelle
21
Ich kann nicht vollständig zustimmen, wenn sie vollständig unabhängig sind, dann haben Sie 2 Monolithen. Die Idee ist, intelligente Endpunkte und dumme Leitungen zu haben. Im Unternehmenskontext stoßen Sie (derzeit mein Albtraum) an die Wand, weil es ein implizites gemeinsames Domänenmodell gibt (implizit, weil wir es nicht vorausgesehen haben) und jeder Dienst ein Prozent des Rads neu erfindet. Und das Ökosystem der Mikrodienste wächst mit einem Fokus, der zu 100% auf Funktionalität und Team-Ownership ausgerichtet ist und das Domänenmodell durcheinanderbringt. Wir haben Teams, die neue Dienste erstellen, andere verbrauchen und viel Aufwand betreiben. Immer noch ungelöst.
Juanmf
5
Wir haben auch eine sehr wichtige architekturbedingte nichtfunktionale Anforderung, die Leistung, beiseite gelassen. Diese Dienste, die die Ausgabe anderer Dienste benötigen, stellen einen mehrstufigen Kommunikationsansatz für jeden Client-RQ bereit. Hinzufügen einer Latenz, die nur behoben werden kann, wenn ein starker Refaktor und möglicherweise eine Mikro-Service-Zusammenführung durchgeführt werden.
Juanmf
3
Da die Teams kein gemeinsames Verständnis des Domänenmodells hatten, führten sie unnötige "Unmarshalling + Objekt-Objekt-Transformationen" durch, um die Antworten der Mikrodienste an das Modell anzupassen, das der aufrufende Mikrodienst annahm. Ich weiß, dass die Kopplung aller Dienste an ein gemeinsames Domänenmodell lib andere betriebliche Probleme mit sich bringen kann, aber ich finde keine der beiden Optionen zufriedenstellend.
Juanmf
3
@juanmf Es wäre sehr wertvoll, wenn Sie eine Frage zu Ihren Problemen stellen könnten. Ich bin auch daran interessiert, Meinungen zu diesem Thema zu hören ...
Milos Mrdovic
1
Ich werde versuchen, etwas zu schreiben, das Sinn macht
juanmf
13

Wenn zwei Dienste so eng miteinander verbunden sind, dass es mühsam wäre, sie zu implementieren, ohne DTOs und andere Modellobjekte gemeinsam zu nutzen, ist dies ein starkes Zeichen, dass Sie nicht über zwei Dienste verfügen sollten.

Zweifellos macht das Beispiel als zwei Dienste wenig Sinn; Es ist schwer vorstellbar, dass die Spezifikation für die Benutzerverwaltung so kompliziert ist, dass ein ganzes Team so beschäftigt ist, dass es keine Zeit für die Authentifizierung hat.

Wenn dies aus irgendeinem Grund der Fall wäre, würden sie wie in OAuth 2.0 über im Grunde beliebige Zeichenfolgen kommunizieren .

Soru
quelle
4

Sie können sich diese als zwei getrennte begrenzte Kontexte vorstellen (in der domänengetriebenen Designsprache). Sie sollten außer einer ID, die zum Korrelieren des "Benutzers" des Authentifizierungskontexts mit dem "Benutzer" des anderen Kontexts verwendet wird, keine Daten zwischen ihnen austauschen. Sie können jeweils eine eigene Darstellung des "Benutzers" und ein eigenes Domänenmodell haben, das nur die Informationen enthält, die für die Wahrnehmung ihrer Geschäftsverantwortung erforderlich sind.

Denken Sie daran, dass ein Domain-Modell nicht versucht, ein reales "Ding" zu modellieren, sondern das, was dieses Ding in einem bestimmten Kontext ist (wie z. B. Identitäts- / Berechtigungsverwaltung oder Personalwesen usw.).

pnschofield
quelle
2

Sie haben beide das Konzept eines Benutzers und werden durch gegenseitige Anrufe über Benutzer sprechen.

Ich stimme auch dem zu, was @soru gesagt hat. Wenn ein Dienst die Daten eines anderen Dienstes benötigt, sind deren Grenzen falsch.

@Pnschofield hat sich eine gute Lösung ausgedacht: Behandeln Sie Ihre Services als begrenzten Kontext.

In Kürze: Shared Domain-Modelle verhindern die Autonomie von Diensten und verwandeln Ihr Microservice-System in einen verteilten Monolithen. Was anscheinend noch schlimmer ist als ein Monolith.

Es ist also immer noch eine allgemeine Frage ungelöst - wie werden Service- oder Kontextgrenzen definiert, damit sie in hoher Kohäsivität und loser Kopplungsgüte gedeihen.

Ich fand eine Lösung, um meine Kontexte als Geschäftsfähigkeit zu behandeln. Es ist eine übergeordnete Geschäftsverantwortung, eine Geschäftsfunktionalität, die zum allgemeinen Geschäftsziel beiträgt. Sie können sich diese Schritte als Schritte vorstellen, die Ihr Unternehmen ausführen muss, um geschäftlichen Nutzen zu erzielen.

Meine typische Abfolge von Schritten zum Ermitteln von Dienstgrenzen lautet wie folgt:

  1. Identifizieren Sie übergeordnete Geschäftsfunktionen. Normalerweise sind sie bei Organisationen aus derselben Domäne ähnlich. Sie können ein Gefühl dafür bekommen, wie es aussieht, wenn Sie das Wertschöpfungskettenmodell von Porter überprüfen .
  2. Tauchen Sie in die einzelnen Funktionen ein und identifizieren Sie untergeordnete Funktionen.
  3. Beachten Sie die Kommunikation zwischen den Funktionen. Schauen Sie sich an, was eine Organisation tut. In der Regel konzentriert sich die Kommunikation auf Fähigkeiten und informiert den Rest über das Ergebnis seiner Arbeit. Bei der Implementierung der technischen Architektur sollte Ihr Service daher auch über Ereignisse kommunizieren. Dies hat mehrere positive Konsequenzen. Mit diesem Ansatz sind Ihre Dienste autonom und kohärent. Sie benötigen keine synchrone Kommunikation und verteilte Transaktionen.

Wahrscheinlich würde Sie ein Beispiel für diese Technik interessieren. Zögern Sie nicht, mir Ihre Meinung mitzuteilen, da ich diesen Ansatz für sehr profitabel befunden habe. Sicher, es kann auch für Sie funktionieren.

Zapadlo
quelle
1

Bei Microservice geht es nicht um "nichts teilen", sondern um "so wenig wie möglich teilen". In den meisten Fällen ist "Benutzer" eine wirklich gebräuchliche Entität (nur weil der Benutzer durch einen gemeinsamen Identifikator identifiziert wird - Benutzer-ID / E-Mail / Telefon). Solche Entitäten werden per Definition geteilt. Das Benutzermodell ist außerhalb des Geltungsbereichs eines Mikrodienstes. Sie müssen also ein globales Schema haben, in das der Benutzer (nur die am häufigsten verwendeten Felder) eingefügt werden soll. Im strengen Fall ist nur id.

Evgeniy Ostapenko
quelle