Axonframework 3中的事件快照,提高了性能

Axonframework框架概述


Axonframework是一个实现多种设计原理和模式的框架,例如:

CQRS-分离对读取和写入数据的请求的处理
事件源是将应用程序的状态存储为事件链的情况。
DDD聚合 -存储状态的域对象

以事件链的形式存储应用程序最终状态的缺点之一是存储和处理的事件数。 幸运的是,Axonframework允许您创建一个快照事件,其中包含多个事件(域事件)的结果。

事件快照


快照事件-这些是几个事件(域事件)的结果值。 这使您可以快速重新创建聚合的状态。 重要的是要了解,快照是根据用于具有唯一标识符的特定单元的事件创建的。

例如( 图1 ),我们将配置设置为每两个事件创建一个快照(阈值= 2-出于说明目的)。 在这种情况下,当两个事件改变了本机的状态时,将使用前两个事件的结果值创建一张图像。


图1.两个事件的快照。 (阈值= 2)

考虑一个更复杂的示例( 图2 ),该配置还指定一个阈值为2,以便每两个事件创建一个快照。 当2个事件改变本机的状态时,将创建一张照片。 此外,其他2个事件会更改单元的状态,并且不会创建新图片,但是会更新现有图片。


图2一幅图像中事件链的结果(阈值= 2)

性能表现


一方面,当一长串事件累积在应用程序中时,读取和处理大量事件以重新创建单元状态需要花费时间。 另一方面,如果创建快照,则将快速重新创建单元的状态,但是创建快照将花费一些时间。 在这两种情况之间必须取得平衡。


图3不带快照的性能


图4带快照的性能(阈值= 3)

默认情况下,在称为scheduleSnapshot()方法的线程中创建快照。 不建议在战斗环境中使用此设置(请参见图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; } 

Reservation.java

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

值得注意的是,Google网上论坛讨论线程包含有用的代码示例和讨论。

选择快照的阈值



5.1。 理论方法

让我们在EventListener类中计算可应用于Unit的事件数。 然后,我们从理论上估计典型情况下应用到该单元的平均事件数,并设置一个稍小于此值的值作为创建图像的阈值。 如果刚刚创建了应用程序,并且没有用于分析的真实数据,则可以执行此操作。

5.2。 实用方式

我们分析数据库中的数据,并假设该数据库由MongoDB使用,并且在docker容器内工作。

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

每个存储的事件都包含一个gregationIdentifier字段,通过该字段,我们可以通过简单的查询来计算应用于每个聚合的事件数:

 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 

如果快照事件集合不为空且包含快照,则快照创建已成功激活。

其他快照选项


文档提到了有关如何激活快照创建的其他变体,例如:

  • 自上次快照以来超过阈值生成的事件数
  • 单元初始化超时
  • 时间延迟等 等

Source: https://habr.com/ru/post/zh-CN435522/


All Articles