Snapshot acara di Axonframework 3, meningkatkan kinerja

Ikhtisar kerangka kerja axonframework


Axonframework adalah kerangka kerja yang menerapkan beberapa prinsip dan pola desain seperti:

CQRS - Memisahkan pemrosesan permintaan untuk membaca dan menulis data
Sumber Acara adalah ketika keadaan aplikasi disimpan sebagai rantai acara.
DDD Aggregate - objek domain yang menyimpan status

Salah satu kelemahan menyimpan keadaan akhir suatu aplikasi dalam bentuk rangkaian peristiwa adalah jumlah peristiwa yang disimpan dan diproses. Untungnya, Axonframework memungkinkan Anda membuat acara snapshot, yang berisi hasil dari beberapa peristiwa (peristiwa domain).

Cuplikan Acara


Snapshot event - ini adalah nilai yang dihasilkan dari beberapa peristiwa (peristiwa domain). Ini memungkinkan Anda untuk dengan cepat membuat ulang keadaan Agregat. Penting untuk dipahami bahwa snapshot dibuat dari peristiwa yang digunakan untuk Unit tertentu dengan pengidentifikasi unik.

Sebagai contoh ( Gbr. 1 ), kami mengatur konfigurasi untuk membuat snapshot untuk setiap dua peristiwa (ambang = 2 - untuk tujuan ilustrasi). Dalam hal ini, ketika dua peristiwa mengubah status Unit, satu gambar akan dibuat dengan nilai yang dihasilkan dari dua peristiwa sebelumnya.


Gambar 1. Cuplikan dari dua peristiwa. (ambang = 2)

Perhatikan contoh yang lebih rumit ( Gbr. 2 ), konfigurasi juga menentukan ambang 2 sehingga snapshot dibuat setiap dua peristiwa. Ketika 2 acara mengubah status Unit, satu gambar akan dibuat. Selanjutnya, 2 peristiwa lainnya mengubah status Unit dan gambar baru tidak dibuat, tetapi yang sudah ada diperbarui.


2 Hasil dari rantai peristiwa dalam satu gambar (ambang = 2)

Performa


Di satu sisi, ketika rantai panjang peristiwa terakumulasi dalam suatu aplikasi, dibutuhkan waktu untuk membaca dan memproses sejumlah besar peristiwa untuk menciptakan kembali keadaan Unit. Di sisi lain, jika Anda membuat snapshot, keadaan Unit akan dibuat kembali dengan cepat, tetapi akan butuh waktu untuk membuat snapshot. Keseimbangan harus dicapai antara kedua situasi ini.


Gbr. 3 Performa tanpa mengambil snapshot


Gambar. 4 Performa dengan snapshot (ambang = 3)

Secara default, snapshot dibuat di utas yang disebut metode scheduleSnapshot (). Pengaturan ini tidak disarankan untuk lingkungan tempur (lihat Gbr. 4 / entri).

Di bawah ini adalah contoh kode menggunakan ThreadPoolExecutor (...) yang akan menyediakan utas terpisah untuk membuat snapshot. Dalam hal ini, klien kami tidak akan melihat perlambatan dalam aplikasi dan waktu yang diberikan untuk membuat snapshot.

Kode


Untuk mengaktifkan pembuatan snapshot, Anda perlu membuat sedikit perubahan pada kode aplikasi. Anotasi agregat menunjukkan nama repositori yang digunakan dalam kode kelas konfigurasi. Di kelas konfigurasi, ambang batas untuk membuat snapshot, metode untuk membuat snapshot, repositori, dll. Diindikasikan.

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 { //… } 

Patut dicatat bahwa utas diskusi Google Groups berisi contoh dan diskusi kode yang bermanfaat.

Pilih ambang untuk foto



5.1. Cara teoretis

Mari kita hitung jumlah peristiwa yang bisa diterapkan ke Unit di kelas EventListener. Kemudian secara teoritis kami memperkirakan jumlah rata-rata peristiwa yang diterapkan pada Unit dalam situasi tipikal dan menetapkan nilai sedikit kurang dari ini sebagai ambang batas untuk membuat gambar. Ini dapat dilakukan jika aplikasi baru saja dibuat dan tidak ada data nyata untuk dianalisis.

5.2. Cara praktis

Kami menganalisis data dari database, dan kami menganggap bahwa database digunakan oleh MongoDB dan berfungsi di dalam wadah buruh pelabuhan.

 > 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” } 

Setiap peristiwa yang tersimpan berisi bidang Agregat Identifikasi, yang dengannya kami menghitung jumlah acara yang diterapkan untuk setiap Agregat dengan kueri sederhana:

 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 } 

Ambang batas untuk membuat foto dapat dipilih di bawah rata-rata sehingga foto dibuat secara efektif. Dalam hal ini, nilai 50 baik-baik saja.

Memeriksa aktivasi snapshot


 > 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 

Jika koleksi snapshotevents tidak kosong dan berisi snapshot, maka pembuatan snapshot telah berhasil diaktifkan.

Pilihan foto lainnya


Dokumentasi menyebutkan variasi lain tentang cara mengaktifkan pembuatan snapshot, misalnya:

  • jumlah peristiwa yang dihasilkan sejak foto terakhir melebihi ambang batas
  • Inisialisasi unit habis
  • waktu tunda, dll. dll.

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


All Articles