天天看点

Axon Framework官方文档(十)10 Event Processing(事件处理)

10 Event Processing(事件处理)

应用程序生成的事件需要被发送到可以更新查询数据库、搜索引擎或需要这些事件的其他资源的组件上(通俗而言,即事件需要被传递到需要它的组件上):事件处理程序(event handler)。事件总线负责向所有感兴趣的组件发送事件消息。在接收端,Event Processors(事件处理器)负责处理这些事件,包括调用适当的Event Handlers(事件处理程序)。
           

10.1 Publishing Events(发布事件)

在绝大多数情况下,聚合将通过应用它们来发布事件。但是,有时候,需要将事件(可能来自另一个组件)发布到事件总线。要发布事件,只需用将描述事件信息的payload封装进一个EventMessage中。GenericEventMessage.asEventMessage(对象)方法允许你将任何对象包装进EventMessage对象。如果传递的对象已经是EventMessage,那么它将简单地返回。
           

10.2 Event Bus(事件总线)

EventBus是将事件分发到订阅该事件的处理程序上的机制。Axon提供了事件总线的两个实现:SimpleEventBus和EmbeddedEventStore。虽然这两种实现都支持订阅和跟踪处理器(参见事件处理器,就是10.3),但是EmbeddedEventStore可以持久化事件,这允许您在稍后的阶段可以重放它们。SimpleEventBus存储在一个不稳定的存储中,而且一旦事件被分发到订阅它的组件上,那么它就会将该事件"忘记"掉。
在使用配置API时,SimpleEventBus是默认使用的。要配置EmbeddedEventStore ,您需要提供一个StorageEngine的实现,它可以实际存储事件。
           
Configurer configurer = DefaultConfigurer.defaultConfiguration();
configurer.configureEmbeddedEventStore(c -> new InMemoryEventStorageEngine());
           

10.3 Event Processors(事件处理器)

Event Handler(事件处理程序)定义了在收到事件时要执行的业务逻辑。Event Processors(事件处理器)是负责处理该处理过程的技术方面的组件。它启动了一个工作单元,也可能是一个事务,但也确保了相关数据可以正确地连接到在事件处理过程中创建的所有消息。 
Event Processors(事件处理器)大致有两种形式:订阅和跟踪。
>订阅的事件处理器订阅了事件源,由分发机制管理的线程负责调用。
>另一方面,跟踪的事件处理器,使用它自己管理的线程从数据源中拉取消息。
           

10.3.1 Assigning handlers to processors(将处理程序分配给处理器)

所有的处理器都有一个名称,它跨JVM实例的来标识处理器实例。两个具有相同名称的处理器,可以看作是同一个处理器的两个实例。
所有事件处理程序都附加到一个处理器,而这个处理器的名称是事件处理程序的类的包名。
我们来看下面的例子:
下面的这些类
           
org.axonframework.example.eventhandling.MyHandler
org.axonframework.example.eventhandling.MyOtherHandler
org.axonframework.example.eventhandling.module.MyHandler
           
会触发两个处理器的创建:
           
org.axonframework.example.eventhandling(有两个处理程序注册给了它)
org.axonframework.example.eventhandling.module(只有一个命令处理程序注册给了它)
           
配置API允许您配置其他策略,将类分配给处理器,甚至将特定的实例分配给特定的处理器
           

10.3.2 Configuring processors(配置处理器)

默认情况下,Axon将使用订阅的事件处理器(即不存储事件,分发了就"忘记")。可以通过配置API的EventHandlingConfiguration来更改处理程序的分配方式以及处理器的配置方式
EventHandlingConfiguration类定义了大量的方法,可以配置处理器
>registerEventProcessorFactory :允许你定义一个默认的工厂方法,创建没有明确定义工厂的事件处理器。
>registerEventProcessor(String name, EventProcessorBuilder builder):定义工厂方法,用于创建给定name(名称)的处理器。注意,此种处理器只有当名称被选择作为任何可用的事件处理程序bean的处理器时才会创建。
>registerTrackingProcessor(String name):定义一个带有给定名称的处理器应该被配置为跟踪事件处理器,使用默认设置。它使用TransactionManager和TokenStore配置。
>usingTrackingProcessors():设置默认使用跟踪处理器而不是订阅处理器
跟踪处理器不同于订阅的处理器,需要一个令牌存储来存储它们的进度。跟踪处理器通过它的事件流接收到的每个消息都伴随着一个令牌。这个令牌允许处理器在以后的任何点上重新打开流,并在最后一个事件结束时重新打开它。
配置API接受令牌存储,以及来自全局配置实例的大多数其他组件处理器。如果没有显式定义TokenStore,则使用InMemoryTokenStore,这在生产中是不推荐的。
           

10.4 Distributing Events(分布式事件)

在某些情况下,需要将事件发布到外部系统,例如消息代理。
           

10.4.1 Spring AMQP

Axon为来自AMQP消息代理(如RabbitMQ)的事件传递提供了开箱即用的支持。
           

10.4.1.1 Forwarding events to an AMQP Echange(事件转发到AMQP)

SpringAMQPPublisher将事件转发给AMQP Exchanger(交换器)。它是通过SubscribableMessageSource来初始化的,它通常是一个EventBus或EventStore。从理论上讲,这可能是发布者可以订阅的任何事件源。
要配置SpringAMQPPublisher,只需将一个它的实例定义为Spring Bean。有许多setter方法允许您指定您期望的行为,例如事务支持、发布者确认(如果代理支持)和交换器名称。
默认的交换名称是“axon.eventbus”。
Note:
请注意,交换器不是自动创建的。您仍然必须声明您希望使用的队列、交换和绑定。查看Spring文档了解更多信息。
           

10.4.1.2 Reading Events from an AMQP Queue(从AMQP中读取消息)

Spring广泛支持从AMQP队列读取消息。然而,这需要“桥接”到Axon,这样就可以从Axon处理这些消息,就好像它们是常规事件消息一样。
SpringAMQPMessageSource允许事件处理器从队列读取消息,而不是从事件存储或事件总线中读取。它作为一个Spring AMQP和SubscribableMessageSource之间的适配器,它是这些处理器所必需的。
配置SpringAMQPMessageSource的最简单方法是定义一个bean,它覆盖默认的onMessage方法,并使用@ rabbitlistener注释它:
           
@Bean
public SpringAMQPMessageSource myMessageSource(Serializer serializer) {
    return new SpringAMQPMessageSource(serializer) {
        @RabbitListener(queues = "myQueue")
        @Override
        public void onMessage(Message message, Channel channel) throws Exception {
            super.onMessage(message, channel);
        }
    };
}
           
Spring的@RabbitListener注解告诉Spring,该方法需要在给定队列的每个消息上调用(示例中的队列是“myQueue”)。此方法简单地调用super.onmessage()方法,而他则会将事件的实际发布到那些订阅到该事件上的处理器上。
要将处理器订阅到此MessageSource,请将正确的SpringAMQPMessageSource实例传递给订阅处理器的构造函数:
           
// in an @Configuration file:
@Autowired
public void configure(EventHandlingConfiguration ehConfig, SpringAmqpMessageSource myMessageSource) {
    ehConfig.registerSubscribingEventProcessor("myProcessor", c -> myMessageSource);
}
           
注意,跟踪处理器与SpringAMQPMessageSource不兼容。
           

10.5 Asynchronous Event Processing(异步事件处理)

异步处理事件推荐的方法是使用跟踪事件处理器。这个实现可以保证所有事件的处理,甚至在发生系统故障的情况下(假定事件已经被持久化)。
然而,也有可能在SubscribingProcessor中异步处理事件。要做到这一点,SubscribingProcessor必须用EventProcessingStrategy配置。这种策略可以用来改变事件监听器的调用应如何管理。
默认策略(DirectEventProcessingStrategy)在传递事件的线程中调用这些事件处理程序。这允许处理器使用现有的事务
默认策略(DirectEventProcessingStrategy)调用这些线程提供了事件处理程序。这允许处理器使用现有的事务。
其他Axon-provided strategy是AsynchronousEventProcessingStrategy。它使用一个Executor异步调用事件侦听器。
尽管AsynchronousEventProcessingStrategy异步执行,某些事件按顺序处理仍然是可取的。SequencingPolicy定义了事件是否必须以顺序、并行或两者的组合来处理。策略返回给定事件的序列标识符。如果策略返回两个事件的相同标识符,则意味着它们必须由事件处理程序按顺序处理。空一个空序列标识符意味着事件可能与任何其他事件并行处理.
Axon提供了一些可以使用的通用策略:
>FullConcurrencyPolicy将告诉Axon这个事件处理程序可以同时处理所有事件。这意味着,需要按照特定顺序处理的事件之间没有关系。
>SequentialPolicy告诉Axon,所有事件都必须按顺序处理。事件的处理将在处理前一个事件完成时开始。
>SequentialPerAggregatePolicy将迫使域事件从同一聚合顺序处理。然而,来自不同聚合的事件可以同时处理。这通常是一个合适的策略,用于事件侦听器更新数据库中聚合的细节。

除了这些提供的策略之外,您还可以定义自己的策略。所有策略都必须实现SequencingPolicy接口。这个接口定义了一个getSequenceIdentifierFor方法,返回为一个给定的事件序列标识符。返回一个相等序列标识符的事件必须按顺序处理。产生不同序列标识符的事件可以同时处理。出于性能原因,如果事件可以与任何其他事件并行处理,则策略实现应该返回null。这更快,因为Axon不需要检查事件处理的任何限制。
当使用AsynchronousEventProcessingStrategy时建议明确定义一个ErrorHandler。默认的ErrorHandler传播异常,但在异步执行中没有什么可以传播的,除了Executor。这可能导致事件没有被处理。相反,建议使用一个ErrorHandler报告错误,并允许继续处理。ErrorHandler被配置在SubscribingEventProcessor的构造函数上,还提供了EventProcessingStrategy。