Ereignis-Snapshots in Axonframework 3 verbessern die Leistung

Ăśbersicht ĂĽber das Axonframework-Framework


Axonframework ist ein Framework, das verschiedene Designprinzipien und -muster implementiert, z.

CQRS - Trennt die Verarbeitung von Anforderungen zum Lesen und Schreiben von Daten
Event Sourcing ist, wenn der Status einer Anwendung als Ereigniskette gespeichert wird.
DDD-Aggregat - Ein Domänenobjekt, das den Status speichert

Einer der Nachteile beim Speichern des Endzustands einer Anwendung in Form einer Ereigniskette ist die Anzahl der gespeicherten und verarbeiteten Ereignisse. Glücklicherweise können Sie mit Axonframework ein Snapshot-Ereignis erstellen, das das Ergebnis mehrerer Ereignisse enthält (Domänenereignis).

Ereignis-Snapshots


Snapshot-Ereignis - Dies sind die resultierenden Werte mehrerer Ereignisse (Domänenereignis). Auf diese Weise können Sie den Status des Aggregats schnell wiederherstellen. Es ist wichtig zu verstehen, dass ein Snapshot aus Ereignissen erstellt wird, die für eine bestimmte Einheit mit einer eindeutigen Kennung verwendet wurden.

Zum Beispiel ( Abb. 1 ) legen wir die Konfiguration so fest, dass für jeweils zwei Ereignisse ein Snapshot erstellt wird (Schwellenwert = 2 - zur Veranschaulichung). In diesem Fall wird ein Bild mit den resultierenden Werten der beiden vorherigen Ereignisse erstellt, wenn zwei Ereignisse den Status der Einheit ändern.


Abbildung 1. Eine Momentaufnahme von zwei Ereignissen. (Schwelle = 2)

Betrachten Sie ein komplizierteres Beispiel ( Abb. 2 ). In der Konfiguration wird außerdem ein Schwellenwert von 2 angegeben, sodass alle zwei Ereignisse ein Snapshot erstellt wird. Wenn 2 Ereignisse den Status der Einheit ändern, wird ein Bild erstellt. Außerdem ändern die anderen 2 Ereignisse den Status der Einheit und es wird kein neues Bild erstellt, aber das vorhandene wird aktualisiert.


Abb. 2 Das Ergebnis der Ereigniskette in einem Bild (Schwelle = 2)

Leistung


Wenn sich in einer Anwendung eine lange Kette von Ereignissen ansammelt, dauert es einerseits einige Zeit, eine groĂźe Anzahl von Ereignissen zu lesen und zu verarbeiten, um den Status der Einheit wiederherzustellen. Wenn Sie dagegen einen Schnappschuss erstellen, wird der Status der Einheit schnell neu erstellt, das Erstellen eines Schnappschusses dauert jedoch einige Zeit. Zwischen diesen beiden Situationen muss ein Gleichgewicht hergestellt werden.


Abb. 3 Leistung ohne Schnappschuss


Abb. 4 Leistung mit Schnappschuss (Schwellenwert = 3)

Standardmäßig wird im Thread ein Snapshot erstellt, der die Methode schedSnapshot () aufruft. Diese Einstellung wird für eine Kampfumgebung nicht empfohlen (siehe Abb. 4 / Eintrag).

Unten finden Sie ein Beispiel fĂĽr Code mit ThreadPoolExecutor (...), der einen separaten Thread zum Erstellen eines Snapshots bereitstellt. In diesem Fall wird unser Client keine Verlangsamung der Anwendung und die zugewiesene Zeit zum Erstellen eines Snapshots bemerken.

Code


Um die Erstellung von Snapshots zu aktivieren, müssen Sie kleine Änderungen am Anwendungscode vornehmen. Die aggregierte Annotation gibt den Namen des Repositorys an, das im Code der Konfigurationsklasse verwendet wird. In der Konfigurationsklasse werden der Schwellenwert zum Erstellen von Snapshots, die Methode zum Erstellen von Snapshots, Repositorys usw. angegeben.

AxonConfig.java

@Autowired private EventStore eventStore; @Bean public SpringAggregateSnapshotterFactoryBean springAggregateSnapshotterFactoryBean() { return new SpringAggregateSnapshotterFactoryBean(); } @Bean public SpringAggregateSnapshotter snapshotter(ParameterResolverFactory parameterResolverFactory, EventStore eventStore, TransactionManager transactionManager) { Executor executor = Executors.newFixedThreadPool(10); return new SpringAggregateSnapshotter(eventStore, parameterResolverFactory, executor, transactionManager); } @Bean("reservationRepository") public EventSourcingRepository<Reservation> reservationRepository(Snapshotter snapshotter, ParameterResolverFactory parameterResolverFactory) { return new EventSourcingRepository<Reservation>(reservationAggregateFactory(), eventStore, parameterResolverFactory, new EventCountSnapshotTriggerDefinition(snapshotter, 50)); } @Bean(name = "reservationAggregateFactory") public AggregateFactory<Reservation> reservationAggregateFactory() { SpringPrototypeAggregateFactory<Reservation> aggregateFactory = new SpringPrototypeAggregateFactory<>(); aggregateFactory.setPrototypeBeanName("reservation"); return aggregateFactory; } 

Reservation.java

 @Aggregate(repository = "reservationRepository") public class Reservation { //… } 

Es ist erwähnenswert, dass der Diskussionsthread von Google Groups nützliche Codebeispiele und Diskussionen enthält.

Wählen Sie den Schwellenwert für Schnappschüsse



5.1. Theoretischer Weg

Berechnen wir die Anzahl der Ereignisse, die auf die Einheit in der EventListener-Klasse angewendet werden können. Dann schätzen wir theoretisch die durchschnittliche Anzahl von Ereignissen, die in einer typischen Situation auf die Einheit angewendet werden, und legen einen etwas niedrigeren Wert als diesen Schwellenwert für die Erstellung von Bildern fest. Dies ist möglich, wenn die Anwendung gerade erstellt wurde und keine realen Daten für die Analyse vorhanden sind.

5.2. Praktischer Weg

Wir analysieren die Daten aus der Datenbank und gehen davon aus, dass die Datenbank von MongoDB verwendet wird und im Docker-Container funktioniert.

 > docker exec -it <container-id> mongo > show dbs admin 0.000GB axonframework 0.000GB local 0.000GB > use axonframework switched to db axonframework > show collections domainevents sagas snapshotevents > db.domainevents.findOne() { “_id” : ObjectId(“5bb1dc8d4446d63bcc765feb”), “aggregateIdentifier” : “b1e320d5–58aa-4b9b-a667-aa724900592f”, “type” : “Reservation”, “sequenceNumber” : NumberLong(0), “serializedPayload” : “<com.example.ReservationStarted><reservationIdentifier>b1e320d5–58aa-4b9b-a667-aa724900592f</reservationIdentifier><duration resolves-to=\”java.time.Ser\”><byte>1</byte><long>2400</long><int>0</int></duration></com.example.ReservationStarted>”, “timestamp” : “2018–10–01T08:36:29.434Z”, “payloadType” : “com.example.ReservationStarted”, “payloadRevision” : null, “serializedMetaData” : “<meta-data><entry><string>traceId</string><string>b090b86a-ec89–484b-ae9f-e4fa0f9bcd39</string></entry><entry><string>correlationId</string><string>b090b86a-ec89–484b-ae9f-e4fa0f9bcd39</string></entry></meta-data>”, “eventIdentifier” : “f324f021–50b4–4e91–84d0-f8c4425f3eb9” } 

Jedes gespeicherte Ereignis enthält ein aggregiertes IDentifier-Feld, anhand dessen wir die Anzahl der Ereignisse berechnen, die auf jedes Aggregat mit einer einfachen Abfrage angewendet werden:

 db.domainevents.aggregate([ {$group: {_id: "$aggregateIdentifier", count: {$sum: 1} } }, {$sort : {count : -1} } ]); { "_id" : "0d84afd1-f199-45c8-b50e-7d9ebfa4c8fb", "count" : 136 } { "_id" : "49de7c32-38ea-435a-b837-ccdb61ec0baa", "count" : 136 } { "_id" : "12957b0b-af05-47c4-a3d8-968b75cf9ffb", "count" : 136 } { "_id" : "97a24559-ee3a-43e7-a6be-1eb6840b662a", "count" : 132 } { "_id" : "b6aeb1af-0620-4b02-8de3-c2446c2f7d83", "count" : 132 } { "_id" : "b385aaf4-3338-489f-8d1b-4600d5e088b9", "count" : 132 } { "_id" : "5970327f-9551-4945-94e9-3844c0cd3543", "count" : 132 } ... { "_id" : "0182239h-3948-3334-98t5-9643j4ld8346", "count" : 1 } 

Der Schwellenwert für die Erstellung von Snapshots kann unter dem Durchschnitt ausgewählt werden, damit Snapshots effektiv erstellt werden. In diesem Fall ist ein Wert von 50 in Ordnung.

ĂśberprĂĽfen der Snapshot-Aktivierung


 > mongo > show dbs admin 0.000GB axonframework 0.000GB local 0.000GB > use axonframework > show collections domainevents sagas snapshotevents > db.domainevents.count() 515 > db.snapshotevents.count() 7 

Wenn die Snapshotevents-Sammlung nicht leer ist und Snapshots enthält, wurde die Snapshot-Erstellung erfolgreich aktiviert.

Andere Schnappschussoptionen


In der Dokumentation werden andere Variationen zum Aktivieren der Snapshot-Erstellung erwähnt, zum Beispiel:

  • Die Anzahl der seit dem letzten Snapshot generierten Ereignisse hat den Schwellenwert ĂĽberschritten
  • ZeitĂĽberschreitung bei der Geräteinitialisierung
  • Zeitverzögerung usw. usw.

Source: https://habr.com/ru/post/de435522/


All Articles