Java >> Java Tutorial >  >> Java

Microservice-Beispiel-Ereignisquellenarchitektur

In diesem Beitrag erstellen wir einen einfachen Microservice unter Verwendung eines Event Source-Architekturmusters. Zuvor habe ich die ereignisgesteuerte Architektur besprochen. In diesem Beitrag wird ausführlicher erläutert, wie man mit diesem Muster einen Microservice erstellen kann. Aber bevor wir das tun, schauen wir uns einige Grundlagen an.

Ereignisbeschaffung

Event Sourcing ist ein Ereignisprotokoll, das nur angehängt wird. Wir speichern die Ereignisse und auch den Kontext dieser Ereignisse. Jeder Dienst speichert die Daten als Ereignisse.

Normalerweise beziehen sich die Daten auf Änderungen an der Geschäfts-/Domänenentität. Jede Änderung wird als Ereignis erfasst. Der Dienst speichert das Ereignis mit dem gesamten erforderlichen Kontext in einer Datenbank. Dies ermöglicht die Wiederherstellung des aktuellen Zustands der Entität.

Auditing ist einer der Vorteile von Event Sourcing. Der Hauptunterschied zwischen Audit-Logs und Event-Sourcing ist der Kontext. In Überwachungsprotokollen gibt es keinen Kontext von Änderungen an Entitäten. Beim Event Sourcing ist der Kontext jedoch Teil der Speicherung.

Ereignisspeicher

Event Store ist eine Ereignisdatenbank. Ein System protokolliert jede Änderung der Domain in der Datenbank. Der Ereignisspeicher speichert unveränderliche Ereignisse. Ereignisse sind von Natur aus unveränderlich. Wir können den Entitätsstatus mithilfe des Ereignisspeichers neu erstellen.

Um ein Beispiel zu geben – stellen Sie sich vor, Sie ziehen eine Debitkarte durch, um etwas zu kaufen, und das Geld wird von Ihrem Bankkonto abgebucht.

In diesem Szenario löst ein System ein Ereignis CardSwiped aus . Wir speichern das Ereignis CardSwiped mit Details wie Datum, Preis und Händlerdetails. Wenn die Transaktion aus irgendeinem Grund rückgängig gemacht werden muss, sendet das System ein weiteres Ereignis, anstatt etwas mit dem ersten Ereignis zu ändern. Die Stornierung einer Transaktion ist selbst ein Ereignis. Also wird CardTransactionReverse ausgelöst Veranstaltung.

Kurz gesagt, wir haben CardSwiped nicht geändert als Ereignis in der Datenbank, aber wir haben den Effekt geändert, den es verursacht hat.

Streams

Innerhalb des Ereignisspeichers werden die Ereignisse für eine Domain live in einem Ereignisstrom angezeigt. Man kann den Zustand der Domain wiederherstellen, indem man alle Ereignisse aus einem Stream liest.

Wie der Name schon sagt, sind Streams eingehende Ereignisse. Die Reihenfolge der Ereignisse ist wichtig, insbesondere wenn sich der Status der Domäne ändern wird. Eine eindeutige Zahl oder ein numerischer Wert stellt die Position des Ereignisses dar.

Vorteile von Event Sourcing

Die Verwendung von Event Sourcing bietet eine Reihe von Vorteilen. Hier kommt die Liste

  • Prüfung
  • Asynchrone Kommunikation
  • Fehlertoleranz
  • Einfacher, den Zustand neu aufzubauen
  • Beobachtbarkeit
  • Dienstautonomie – Wenn ein Dienst mit Event-Sourcing ausfällt, können abhängige Dienste aufholen, wenn der Dienst wieder verfügbar ist.

Microservice-Beispiel

In diesem Beispiel sehen wir uns an, wann ein Kunde Essen bestellt.

  1. Kundenbestellungen für Lebensmittel. Der Bestelldienst nimmt die Bestellung auf und führt vor dem Erstellen der Bestellung eine Validierung durch.
  2. Der Bestelldienst ruft den Verbraucherdienst an, um die Verbraucherdetails zu überprüfen.
  3. Der Bestellservice ruft den Küchenservice an, um ein Essensbestellticket zu erstellen.
  4. Der Bestellservice ruft den Accounts-Service für die Kreditkartenautorisierung an.
  5. Wenn alles geklappt hat, erstellt der Bestellservice eine Bestellung.

Zu Demonstrationszwecken werden wir nicht jedes Stück dieses Beispiels detailliert beschreiben. Ich werde zeigen, wie ein Bestellservice eine Bestellung erstellt.

Bei der Ereignisbeschaffung ist jedes Ereignis ein Domänenereignis. Um das Domänenereignis besser zu verstehen, sollten Sie das Domänengesteuerte Design überprüfen.

Domain-Ereignis

Beim Event-Sourcing vertreten wir Domänenentitäten oder aggregieren mit Domänenereignissen. Der übliche Ansatz, um ein Ereignis zu benennen, ist die Verwendung von Verben im Partizip Perfekt. Beispiel – OrderCreated CreditCardAuthorized .

Diese Domänenereignisse enthalten Informationen über die Domäne. Es stellt die Zustandsänderungen für die Domänenentität dar. Es enthält auch Ereignis-ID, Zeitstempel und Benutzerinformationen.

In unserem Microservice-Beispiel verwenden wir die Anzahl der Domänenereignisse – OrderCreated , CreditCardAuthorized , OrderRejected , OrderShipped .

Immer wenn ein Verbraucher eine Bestellung aufgibt, um Lebensmittel zu kaufen, sendet entweder der Kunde eine Bestellanfrage. Für die Verwaltung von Bestellungen haben wir einen Microservice OrderService . OrderService kann die eingehende Bestellanfrage unverändert in der Datenbank speichern. OrderService muss KitchenService informieren über die Bestellung, damit er das Essen zubereiten kann. Wenn wir in der Zwischenzeit eine Aktualisierung der ursprünglichen Bestellung erhalten, werden die Details der ursprünglichen Bestellung überschrieben. Wir verlieren wichtige Zustandsänderungen.

Jetzt kommt die Ereignisbeschaffung.

Mit Event Sourcing können wir Domain-Events erstellen und diese Events verfolgen den Zustand der Domain. Wenn ein Client eine erste Anfrage sendet, wird das Ereignis OrderCreated verfolgt die Auftragserstellung. Bevor die Bestellung für KitchenService vorbereitet wird , wenn ein Kunde die Bestellung aktualisiert oder storniert, haben wir OrderUpdated ODER OrderCanceled Veranstaltungen.

Wir speichern jedes dieser Ereignisse im Ereignisspeicher. Der Ereignisspeicher ermöglicht das Erstellen von Objekten durch Anwenden dieser Ereignisse.

In vielen Fällen können Aggregate eng gekoppelt werden. Um die enge Kopplung zu vermeiden, kann jedes Aggregat ein Domänenereignis veröffentlichen, während es die Ereignisdaten in seinem Speicher speichert. Dieser Speicher fungiert als Prüfprotokoll und bietet die Möglichkeit, den Status wiederherzustellen.

Der Bestellservice veröffentlicht dann das Ereignis OrderCreated über Message-Broker. Verschiedene Dienste wie Küchenservice und Buchhaltungsservice abonnieren die Veranstaltung. Sie werden ihre Arbeit asynchron ausführen. Der Küchendienst führt dann eine Verbraucherüberprüfung durch und sendet bei Erfolg ConsumerVerified Veranstaltung. Accounts Service erstellt ebenfalls CreditCardAtuhorized .

CQRS-Muster

Wenn Sie Event Sourcing als Architekturmuster verwenden, verwenden Sie auch das CQRS-Muster (Command Query Responsibility Segregation).

In traditionellen Datenbankanwendungen verwenden wir CRUD-Operationen, um Daten zu verwalten. CQRS trennt konzeptionell das Modell für Aktualisierung und Anzeige. Der Befehl dient zum Erstellen, Aktualisieren und Löschen und die Abfrage zum Abrufen der Daten aus der Datenbank.

In unserem Beispiel für den Bestellservice sendet der Kunde eine Anfrage, wenn ein Benutzer Essen bestellt. Wir verwenden Anforderungsdetails, um den Befehl CreateOrder aufzurufen . Order Repository verwendet diesen Befehl, um Bestelldetails zu speichern. Und dann orderCreated Das Ereignis wird an die Ereigniswarteschlange ausgegeben. Abonnierte Dienste verwenden dieses Ereignis zur weiteren Verarbeitung.

Behandlung von Idempotenz

Jeder Abonnentendienst muss Idempotenz zum Konsumieren der Ereignisse implementieren. Es ist möglich, dass der Veröffentlichungsdienst die Veranstaltung mehr als einmal veröffentlicht. Wenn der Abonnent dieses Ereignis bereits zuvor verarbeitet hat, sollte der Abonnent sicherstellen, dass er den Domänenstatus nicht ändert, wenn das Ereignis zum zweiten Mal auftritt.

Die übliche Lösung besteht darin, bei jedem Ereignis eine eindeutige ID zu übergeben. Der Abonnent speichert dann die Ereignis-ID in der Datenbanktabelle ProcessedMessages als einzigartig. Wenn ein Abonnent das Ereignis mit derselben ID nutzt, tritt beim Speichern dieser ID in der Datenbanktabelle ein Fehler auf.

Schlussfolgerung

In diesem Beitrag habe ich ausführlich über Event Sourcing berichtet. Event Sourcing ist eine großartige Möglichkeit, Mikroservices zu schreiben. Insbesondere löst es das Problem der Datenkonsistenz. Immer wenn ein Status einer Entität geändert wird, wird ein neues Ereignis zur Liste der Ereignisse hinzugefügt. Es hilft auch dabei, das Problem der objektbezogenen Impedanzfehlanpassung zu vermeiden.


Java-Tag