نظرة عامة على إطار عمل Axonframework
Axonframework هو إطار يقوم بتنفيذ العديد من مبادئ وأنماط التصميم مثل:
CQRS - يفصل معالجة طلبات قراءة وكتابة البيانات
مصدر الحدث هو عندما يتم تخزين حالة التطبيق كسلسلة من الأحداث.
تجميع DDD - كائن مجال يخزن الحالة
واحدة من عيوب تخزين الحالة النهائية للتطبيق في شكل سلسلة من الأحداث هو عدد الأحداث المخزنة والمعالجة. لحسن الحظ ، يسمح لك Axonframework بإنشاء حدث لقطة ، والذي يحتوي على نتيجة لعدة أحداث (حدث مجال).
لقطات الحدث
حدث اللقطة - هذه هي القيم الناتجة للعديد من الأحداث (حدث المجال). هذا يسمح لك بإعادة إنشاء حالة التجميع بسرعة. من المهم أن نفهم أن لقطة تم إنشاؤها من الأحداث التي استخدمت لوحدة معينة مع معرف فريد.
على سبيل المثال (
الشكل 1 ) ، قمنا بتعيين التكوين لإنشاء لقطة لكل حدثين (العتبة = 2 - لأغراض التوضيح). في هذه الحالة ، عندما يغير حدثان حالة الوحدة ، سيتم إنشاء صورة واحدة مع القيم الناتجة للحدثين السابقين.
الشكل 1. لقطة من حدثين. (العتبة = 2)النظر في مثال أكثر تعقيدا (
الشكل 2 ) ، يحدد التكوين أيضا عتبة 2 بحيث يتم إنشاء لقطة كل حدثين. عندما يغير حدثان حالة الوحدة ، سيتم إنشاء صورة واحدة. علاوة على ذلك ، يغير الحدثان الآخران حالة الوحدة ولا يتم إنشاء صورة جديدة ، ولكن يتم تحديث الصورة الحالية.
الشكل 2: نتيجة لسلسلة الأحداث في صورة واحدة (العتبة = 2)الأداء
من ناحية ، عندما تتراكم سلسلة طويلة من الأحداث في تطبيق ما ، يستغرق الأمر وقتًا طويلاً لقراءة عدد كبير من الأحداث ومعالجتها لإعادة إنشاء حالة الوحدة. من ناحية أخرى ، إذا قمت بإنشاء لقطة ، سيتم إعادة إنشاء حالة الوحدة بسرعة ، لكن الأمر سيستغرق بعض الوقت لإنشاء لقطة. يجب إقامة توازن بين هاتين الحالتين.
الشكل 3 الأداء دون أخذ لقطة
الشكل 4 الأداء مع لقطة (العتبة = 3)بشكل افتراضي ، يتم إنشاء لقطة في مؤشر الترابط الذي يسمى أسلوب schedSnapshot (). لا ينصح بهذا الإعداد لبيئة قتالية (انظر الشكل 4 / الإدخال).
يوجد أدناه مثال على التعليمات البرمجية باستخدام ThreadPoolExecutor (...) والتي ستوفر مؤشر ترابط منفصل لإنشاء لقطة. في هذه الحالة ، لن يلاحظ عميلنا أي تباطؤ في التطبيق والوقت المخصص لإنشاء لقطة.
كود
لتنشيط إنشاء لقطات ، تحتاج إلى إجراء تغييرات صغيرة على رمز التطبيق. يشير التعليق التوضيحي الكلي إلى اسم مستودع التخزين المستخدم في رمز فئة التكوين. في فئة التكوين ، تتم الإشارة إلى الحد الأدنى لإنشاء اللقطات ، وطريقة إنشاء اللقطات ، ومستودعات التخزين ، إلخ.
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; }
الحجز
@Aggregate(repository = "reservationRepository") public class Reservation {
تجدر الإشارة إلى أن سلسلة مناقشة مناقشات مجموعات Google تحتوي على أمثلة ومناقشات مفيدة للشفرة.
حدد عتبة لقطات
5.1. الطريقة النظريةدعونا نحسب عدد الأحداث التي يمكن تطبيقها على الوحدة في فئة EventListener. ثم ، من الناحية النظرية ، نقدر متوسط عدد الأحداث المطبقة على الوحدة في موقف نموذجي ونضع قيمة أقل بقليل من ذلك كحد أدنى لإنشاء الصور. يمكن القيام بذلك إذا تم إنشاء التطبيق للتو ولم تكن هناك بيانات حقيقية للتحليل.
5.2. طريقة عمليةنقوم بتحليل البيانات من قاعدة البيانات ، ونفترض أن قاعدة البيانات تستخدم من قبل MongoDB وأنها تعمل داخل حاوية عامل الميناء.
> 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” }
يحتوي كل حدث مخزّن على حقل aggregateIdentifier ، نحسب من خلاله عدد الأحداث المطبقة على كل تجميع باستخدام استعلام بسيط:
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 }
يمكن تحديد الحد الأدنى لإنشاء اللقطات أسفل المتوسط بحيث يتم إنشاء اللقطات بشكل فعال. في هذه الحالة ، قيمة 50 على ما يرام.
التحقق من تفعيل لقطة
> 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
إذا كانت مجموعة اللقطات ليست فارغة وتحتوي على لقطات ، فسيتم تنشيط إنشاء اللقطة بنجاح.
خيارات لقطة أخرى
تشير
الوثائق إلى أشكال أخرى حول كيفية تنشيط إنشاء لقطة ، على سبيل المثال:
- تجاوز عدد الأحداث التي تم إنشاؤها منذ اللقطة الأخيرة العتبة
- انتهت تهيئة الوحدة
- تأخير الوقت ، الخ الخ