Autonome Microservices, Ereigniswarteschlangen und Serviceerkennung


15

Ich habe in letzter Zeit viel über Mikrodienste gelesen und hier sind einige der Schlussfolgerungen, die ich bisher gezogen habe (bitte korrigieren Sie mich, wenn ich mich irgendwann irre).

  1. Die Mikrodienstarchitektur passt gut zum domänengetriebenen Design. Normalerweise repräsentiert eine MS einen begrenzten Kontext.
  2. Wenn der Mikrodienst A eine Funktionalität erfordert, die sich im Mikrodienst B befindet , ist mein Modell wahrscheinlich falsch, und A und B sollten eigentlich ein Mikrodienst / BC sein.
  3. Die synchrone Kommunikation zwischen Mikrodiensten (direkte HTTP-Anforderungen) ist schlecht, da sie den Zweck von Mikrodiensten nicht erfüllt und eine Kopplung zwischen Komponenten einführt.
  4. Eine asynchrone Kommunikation zwischen Diensten ist wünschenswert. Dienste sollten Ereignisse in Nachrichtenwarteschlangen veröffentlichen, damit andere Dienste ihren Teil des Ereignisses abonnieren und verarbeiten oder ihn zum Replizieren eines Teils der für ihren Kontext erforderlichen Daten verwenden können. Auf diese Weise können Dienste Anforderungen verarbeiten, auch wenn andere Dienste nicht verfügbar sind, was bei der synchronen Kommunikation nicht der Fall wäre.
  5. Wenn der Mikrodienst A ein Ereignis veröffentlicht, der Mikrodienst B dieses Ereignis abonniert und als Ergebnis ein neues Ereignis erzeugt, sollte der Mikrodienst A nicht dasjenige sein, das das neu erzeugte Ereignis verarbeitet, da dies eine zirkuläre Abhängigkeit wäre. In diesem Fall sollten wir einen dritten Mikrodienst einführen oder A und B zu einem AB- Mikrodienst kombinieren .
  6. Micro-Service ist eigentlich ein irreführender Begriff. Wir sollten nach kleinen Zusammenhängen streben, aber das muss nicht so sein. Begriff sollte nicht "Mikrodienst" sein, sondern " groß genug, um den Arbeitsdienst zu erledigen ".
  7. Mit Micro-Services können wir neue Funktionalitäten einfacher einführen, ohne befürchten zu müssen, dass wir das gesamte System beschädigen. Dies kann durch Einführung eines neuen Dienstes oder durch Umgestaltung eines bestehenden Dienstes erfolgen.
  8. Jeder Mikrodienst sollte über einen eigenen Datenspeicher verfügen. Datenreplikation / -duplikation ist in dieser Architektur ein wünschenswertes Verhalten.

Abgesehen davon, dass mein Verständnis dieser Architektur bestätigt wurde, bezieht sich mein anderer Teil der Frage hauptsächlich auf die Serviceerkennung. Wenn die Services asynchron kommunizieren und eine zentrale Ereigniswarteschlange wie Amazon SQS verwenden, bedeutet dies, dass die Serviceerkennung in einer solchen Architektur keinen Platz hat?

Dienste sollten keine Kenntnisse über andere Dienste im System haben. Sie sind sich nur ihres Kontexts und ihrer Ereignisse bewusst, die sie veröffentlichen oder abonnieren sollten?

Antworten:


4

Ihre Schlussfolgerungen scheinen größtenteils begründet zu sein und fassen den Weg für Microservices sehr gut zusammen.

Ich würde jedoch 2, 5 und 8 nicht vollständig unterstützen:

  • 2) Eine einfache Abhängigkeit sollte nicht automatisch zu einer Fusion führen. Sie müssen die Häufigkeit dieser abhängigen Anrufe und auch die Häufigkeit der Anrufe von anderen Diensten berücksichtigen.

    Wenn also ein Mikrodienst A sehr häufig Funktionen in Mikrodienst B benötigt und Mikrodienst B von anderen Mikrodiensten selten benötigt wird, sollten Sie die vorgesehene Struktur in Frage stellen und fragen, ob es nicht sinnvoller wäre, beide Mikrodienste zu gruppieren.

  • 5) Natürlich müssen Sie endlose Zyklen in der Nachrichtenverarbeitung vermeiden.

    Das Hinzufügen eines Vermittlers wird dies jedoch nicht verhindern: A könnte eine von C bearbeitete Nachricht starten, die eine von B bearbeitete Nachricht startet, die von A bearbeitete Nachricht startet, und hier befinden Sie sich in einer Schleife.

    Das Problem kann nicht nur anhand des Microservice-Levels beurteilt werden: Die Frage bezieht sich wirklich auf den Nachrichtentyp und den Inhalt, der zum Zyklus führen könnte. Das Diagramm, das die Verteilung und Verarbeitung von Nachrichten über die Dienste hinweg modelliert, muss daher als Ganzes analysiert werden (dies kann tatsächlich komplex sein, sodass Sie sich einen Überwachungs-Mikrodienst vorstellen können, der solche Zyklen erkennt und sie unterbricht).

  • 8) Ja, jeder Mikrodienst muss seinen eigenen Speicher / seine eigene Datenbank haben.

    Ein Minimum an Replikation ist erforderlich, damit die Dienste unabhängig sind. Ich würde jedoch nicht so weit gehen, um zu sagen, dass Replikation gewünscht wird: Sie muss auf ein Minimum beschränkt werden, um eine versteckte Kopplung über Replikationsprozesse zu vermeiden.

    Bei Microservices geht es um lose Kopplung. Dies kann manchmal effektiver erreicht werden, indem ein anderer Mikrodienst aufgerufen wird, um verwandte Daten abzurufen, anstatt Daten zu replizieren.

Die beiden letzten nicht nummerierten Bestätigungen sind zu weit gefasst, um hier eindeutig beantwortet zu werden. Ich denke, Ihr Vorschlag ist ein guter Ausgangspunkt, aber er hängt wirklich von den architektonischen Anforderungen und Einschränkungen ab.


"Dies kann manchmal effektiver erreicht werden, indem ein anderer Mikrodienst aufgerufen wird, um verwandte Daten abzurufen, anstatt Daten zu replizieren." Mit ein wenig synchroner Kommunikation und direkten Aufrufen (über HTTP), um einen Teil der Daten abzurufen, ist also nichts falsch Solange diese Abfrage keine verteilte Transaktion / Befehl darstellt, können wir andernfalls die Atomizität dieses Befehls nicht garantieren.
Robert

1
Es gibt keine perfekte Lösung hier: es lose Kopplung ist und Kapselung ( microservices.io/patterns/data/database-per-service.html ) zum Ausgleich gegen Leichtigkeit aber Redundanz ( microservices.io/patterns/data/event-driven-architecture .html ) im Kontext des Gesamtbildes ( microservices.io/patterns/microservices.html )
Christophe

3

Bei Mikrodiensten geht es darum, verschiedene Funktionsbereiche zu entkoppeln. Jeder Service kann von einem anderen Team mit einem anderen Technologie-Stack in einem anderen Tempo entwickelt werden. Dies schafft organisatorische Flexibilität. Der Kompromiss ist die Komplexität des Betriebs, bei der jeder zusätzliche Service eine weitere Sache erzeugt, die in einer Betriebsumgebung verwaltet werden muss. Bei dem grundsätzlichen Kompromiss zwischen Monolith und Mikroservice geht es also nicht darum, Abhängigkeiten zu vermeiden, sondern darum, die schrittweise Entwicklung und Bereitstellung zu vermeiden, bei der alles auf einmal ausgeliefert werden muss, sondern um den Preis, häufiger ausgeliefert werden zu müssen, weil es solche gibt mehr bewegliche Teile.

Dienste sollten keine Kenntnisse über andere Dienste im System haben. Sie sind sich nur ihres Kontexts und ihrer Ereignisse bewusst, die sie veröffentlichen oder abonnieren sollten?

Das Problem der Abhängigkeitsvermeidung ist ein roter Hering. Sie werden immer Abhängigkeiten zwischen Teilen Ihres Produkts haben, und ob sie sich in einem separaten Service oder in einem Teil desselben Codes befinden, ändert nichts an der Tatsache, dass Abhängigkeiten aufbrechen können. Sie können auf betrieblicher Ebene ausfallen, weil ein Schlüsselserver ausfällt, und Sie verwalten dies durch betriebliche Redundanz und Failover-Verfahren. Sie können auch auf der Integrationsebene unterbrochen werden, da sich Teile auf inkompatible Weise ändern, was Sie durch Integrationstests feststellen. Durch das Mischen von Code zwischen Diensten wird das Problem potenziell beschädigter Abhängigkeiten nicht gelöst. Die Lösungen zur Vermeidung unterbrochener Abhängigkeiten sind Betriebsredundanz- und Integrationstests, die nichts mit der Größe Ihrer Services zu tun haben.

Wenn die Dienste asynchron kommunizieren und eine zentrale Ereigniswarteschlange wie Amazon SQS verwenden, bedeutet dies, dass die Diensterkennung in einer solchen Architektur keinen Platz hat?

Um diese Frage zu beantworten, beantworten Sie zuerst diese Frage: Warum möchten Sie asynchron kommunizieren? Soll die eigenständige Entwicklung separater Komponenten erleichtert werden? Soll die Verfügbarkeit eines 24/7-Systems verbessert werden? Nehmen wir an, es ist das letztere und Sie möchten Warteschlangen verwenden, um Daten in lokale Datenbanken zu replizieren. Nun können Ihre Daten veraltet sein. Irgendwann wird es zu abgestanden sein. Wie gehst du damit um? Wie stellen Sie außerdem die betriebliche Verfügbarkeit der Warteschlange sicher, die eine weitere Laufzeitkomponente darstellt? Und wie stellen Sie die Verfügbarkeit dieser lokalen Datenbanken sicher? Anstatt einen Datenbankcluster zu verwalten, haben Sie jetzt mehrere. Kann Ihr OP-Team diese Arbeitsbelastung bewältigen? Und wirklich, lohnt sich die Komplexität, wenn Ihre Benutzer mit mehr Funktionen und ein paar Stunden Ausfallzeit jeden Monat zufriedener wären, wenn Sie einen einfachen Monolithen bauen würden?

Ich denke du verstehst meinen Standpunkt. Beim Systemdesign geht es nicht um Richtig und Falsch, sondern um die Auswahl aus einer Vielzahl von Kompromissen. Alles, was falsch ist, kann richtig sein und umgekehrt, wenn man es aber nur im richtigen Kontext sieht. Ihr Kontext ist einzigartig für Sie, daher können wir Ihnen zwar eine Antwort geben, dies ist jedoch nicht die Antwort. Erinnern Sie sich, wer Ihr Publikum ist, welche Bedürfnisse es hat, und das richtige Design wird sich zeigen.


1

Ihre Schlussfolgerungen sind nette Faustregeln, aber nicht universell. Es wird Fälle geben, in denen die beste Option darin besteht, diese Regeln zu brechen, selbst in einem Projekt auf der grünen Wiese. In einigen Fällen ist die synchrone Kommunikation die beste Option. In einigen Fällen ist es nicht sinnvoll, zwei Dienste zu einem zusammenzuführen, selbst wenn sie durch synchrone Kommunikation gekoppelt sind.

Und zu Ihrer anderen Frage: Für die warteschlangenbasierte Kommunikation ist keine Serviceerkennung erforderlich.


1
  1. Die Mikrodienstarchitektur passt gut zum domänengetriebenen Design. Normalerweise repräsentiert eine MS einen begrenzten Kontext.

Nicht zustimmen. DDD neigt dazu, sehr OO zu sein. Wird eine Bestellung geliefert? Order.Deliver () während Micro-Services DeliveryService.Deliver (order) haben würden

  1. Wenn der Mikrodienst A eine Funktionalität erfordert, die sich im Mikrodienst B befindet, ist mein Modell wahrscheinlich falsch, und A und B sollten eigentlich ein Mikrodienst / BC sein.

Nicht einverstanden, sollten Sie versuchen, Sie Micro Services Micro zu halten. Teile sie noch kleiner auf!

  1. Die synchrone Kommunikation zwischen Mikrodiensten (direkte HTTP-Anforderungen) ist schlecht, da sie den Zweck von Mikrodiensten nicht erfüllt und eine Kopplung zwischen Komponenten einführt.

Nicht zustimmen. Dienste sollten sich nicht darum kümmern, wer sie anruft, und Anrufer sollten sich nicht darum kümmern, dass die Logik in einem Mikrodienst implementiert ist.

  1. Eine asynchrone Kommunikation zwischen Diensten ist wünschenswert. Dienste sollten Ereignisse in Nachrichtenwarteschlangen veröffentlichen, damit andere Dienste ihren Teil des Ereignisses abonnieren und verarbeiten oder ihn zum Replizieren eines Teils der für ihren Kontext erforderlichen Daten verwenden können. Auf diese Weise können Dienste Anforderungen verarbeiten, auch wenn andere Dienste nicht verfügbar sind, was bei der synchronen Kommunikation nicht der Fall wäre.

Warteschlangen sind gut. Aber deine Argumentation ist falsch. Der einzige Unterschied zwischen Synchronisierungsantworten und Asynchronisierung besteht darin, dass Sie auf die Synchronisierung warten. Sie können RPC-Aufrufe mit Warteschlangen und mehreren Workern ohne Probleme implementieren.

  1. Wenn der Mikrodienst A ein Ereignis veröffentlicht, der Mikrodienst B dieses Ereignis abonniert und als Ergebnis ein neues Ereignis erzeugt, sollte der Mikrodienst A nicht dasjenige sein, das das neu erstellte Ereignis verarbeitet, da dies eine zirkuläre Abhängigkeit wäre. In diesem Fall sollten wir einen dritten Mikrodienst einführen oder A und B zu einem AB-Mikrodienst kombinieren.

Nicht zustimmen. Es ist keine zirkuläre Abhängigkeit, da Ihre Mikrodienste nicht gekoppelt sind. Außerdem möchten Sie SendEmail, EmailFailed und SendAgain erneut senden, da keine drei Mikrodienste erforderlich sind

  1. Micro-Service ist eigentlich ein irreführender Begriff. Wir sollten nach kleinen Zusammenhängen streben, aber das muss nicht so sein. Begriff sollte nicht "Mikrodienst" sein, sondern "groß genug, um den Arbeitsdienst zu erledigen".

Nicht zustimmen. Schauen Sie sich Nano-Services an.

  1. Mit Micro-Services können wir neue Funktionalitäten einfacher einführen, ohne befürchten zu müssen, dass wir das gesamte System beschädigen. Dies kann durch Einführung eines neuen Dienstes oder durch Umgestaltung eines bestehenden Dienstes erfolgen.

Nicht zustimmen. Ja, Sie werden entkoppelt, aber die Orchestrierung von Mikrodiensten kann genauso entmutigend sein wie jedes Monolithprojekt

  1. Jeder Mikrodienst sollte über einen eigenen Datenspeicher verfügen. Datenreplikation / -duplikation ist in dieser Architektur ein wünschenswertes Verhalten.

Nicht zustimmen. Obwohl Sie den Speicher nicht gemeinsam nutzen sollten, sollten Ihre Mikrodienste nach Möglichkeit versuchen, statusfrei zu sein. Dupliziere keine Daten, es sei denn, sie sind im Flug


0

Ähm, Sie sprechen nur von objektorientierter Programmierung. Oder zumindest, wie es ursprünglich gedacht war: unabhängige Teile des laufenden Codes, die über Nachrichten miteinander kommunizieren.

Alan Kay stellte sich OOP als ein Modell biologischer Systeme vor, bei denen Zellen relativ unabhängig voneinander sind und nur über Nachrichten kommunizieren, die an externe Schnittstellen anderer Zellen angeschlossen werden.

Warum denken wir nicht mehr an OOP, nur weil nicht alle Objekte auf demselben Computer ausgeführt werden? Wenn überhaupt, ist dies noch objektorientierter als wenn sie sich auf demselben Computer befinden und Teil derselben Anwendung sind. Wenn sich alle Objekte in derselben App befinden, brechen Entwickler die OOP häufig durch die Verwendung globaler Variablen, die von allen Klassen und gemeinsam genutzt werden Einschließen der gleichen Header in jede Datei usw. Wenn alle Objekte von denselben Inhalten abhängen, sind sie nicht so gekapselt, als wären sie völlig unabhängig voneinander, und die Kapselung ist der springende Punkt von OOP.

Zum Beispiel ist fast alles, was in den anderen Antworten gesagt wird, eine Lehrbuchaussage über OOP.


0

Da ich ein so wichtiges Konzept wie Bounded Context und Core Domain oft falsch verstehe, möchte ich etwas näher darauf eingehen.

Ich fand es äußerst profitabel, Sub-Domains als Geschäftsfähigkeiten zu betrachten. Geschäftsfähigkeit ist etwas, was Ihre Organisation tut. Es ist eine seiner Geschäftsfunktionen. Da unser Ziel die Ausrichtung von Business und IT ist , möchte ich auf jeden Fall, dass sie 1: 1 mit meinen technischen Diensten in Beziehung stehen .

Dieser Prozess läuft also auf Folgendes ab. Zunächst definiere ich übergeordnete Geschäftsfunktionen. Es sollte die Form von Nomen und Verb (oder eine abgeleitete Form) annehmen. Es gibt normalerweise weniger als 10 Geschäftsmöglichkeiten. Dann bin ich immens tiefer und identifiziere verschachtelte Fähigkeiten. Und so weiter, bis es nichts mehr zu spalten gibt. Die Funktionen, die Sie für diesen Ansatz ausgewählt haben, spiegeln die tatsächliche Domäne und die tatsächliche Funktionsweise Ihres Unternehmens wider. Diese Funktionen sind von Natur aus lose miteinander verbunden. Wenn Sie also Ihre technischen Dienste diesen Funktionen zuordnen, sind sie autonom und ereignisgesteuert. Dieser Prozess wird als Business-Capability-Mapping bezeichnet . Es gibt jedoch auch andere Möglichkeiten, Ihre Services zu finden. Die bekannteste davon ist wahrscheinlich die Wertschöpfungsanalyse .

Im Folgenden finden Sie ein Beispiel zum Identifizieren von Dienstgrenzen mithilfe dieses Ansatzes.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.