在Axon框架中揭开跟踪事件处理器的神秘面纱

跟踪令牌

跟踪事件处理器使用跟踪令牌来跟踪已处理的事件。跟踪令牌表示事件流中事件的位置。不同的事件存储实现可以使用跟踪令牌的不同实现来可靠地表示该位置。为了能够在进程重新启动后继续事件处理(我们稍后会看到这不是唯一的原因),跟踪令牌存储在令牌存储中。Token Store有几种实现 - JPA,JDBC,Mongo,当然,你可以提供自己的。通常,存储跟踪令牌的最佳位置是也存储投影(或Saga)的位置。图1显示了这些概念如何一致。

跟踪事件源Axon应用程序中的事件处理

图1 - 跟踪事件处理

每个TEP声明其跟踪令牌,以避免在不同的线程/节点中多次处理相同的事件。声明跟踪令牌是在令牌存储中设置跟踪令牌的所有者的过程。所有者不是无限期设置,而是可配置的超时。当此超时到期且当前所有者未回收令牌时,其他所有者(TEP)可以声明它。TEP可以发布声明,告知其他TEP继续处理。有意识地发布跟踪令牌为TEP重新平衡奠定了基础,在TEP之间平均分配了大量事件处理。

并行处理

在Axon中,通过分割事件流来实现并行处理。对于某个TEP,我们将启动几个并行处理它们自己的事件流段的线程。每个TEP的段数是可配置的。让我们定义一个段实际上是什么。

段是事件总流量的一小部分(参见图2))。换句话说,跟踪令牌被分段为几个部分,这意味着令牌存储包含每个跟踪令牌和段的条目。段包含段标识符和掩码。掩码用于确定某个事件是否属于给定的段。段在并行和分布式事件处理中起着重要作用。每个TEP可以分配几个段。对于它们中的每一个,它启动一个单独的线程进行事件处理,使我们能够进行并行处理。可以在多个节点上的TEP之间分配段,使我们能够以分布式方式处理事件(请注意,不同节点上的TEP仍然必须声明跟踪令牌,因此它们不处理相同的事件)。

Axon框架中的事件流解剖

图2 - 将事件流拆分为段

重播

在我们想要重建投影(视图模型)的情况下,重放过去的事件会派上用场。这个想法是从时间的开始(或从某个时间点开始)并重新调用所有事件处理程序这样做,必须在某个时间点重置TEP(请注意在重置TEP之前应该停止) - 这意味着跟踪令牌会更新。你可以问问自己,令牌存储中的跟踪令牌的手动更新是否足以触发TEP重新处理过去的事件,而你是对的,事件的重放也会以这种方式发生。您可以从Replay API中提取的好处是TEP保留了新发布的事件和重放的事件之间的差异。这使您可以控制哪些事件被重放,哪些事件不被重放。Sagas(默认情况下)不可重播。出于重播目的,Axon提供重播令牌。

处理循环

启动TEP时,它会在单独的线程中为每个段启动一个worker。他们每个人都试图在一定时间内申请跟踪令牌。如果声明成功,则启动处理循环。处理循环的快乐流程包含图3所示的步骤

Axon框架中跟踪事件处理器的处理循环

图3 - 处理循环

  1. 事件流在Tracking Token指向的位置打开。如果没有可用的事件,我们等待一秒钟,以便在流中提供事件。然后,跟踪令牌声明得到扩展,我们从头开始循环。否则,我们继续循环。

  2. 从流中读取事件并将其放入批处理中。没有能够处理它们的处理程序的事件订阅此TEP不会进入批处理。如果在此步骤之后批处理保持空白,我们会延长对跟踪令牌的声明,更新TEP状态,并从头开始循环。否则,我们继续循环。

  3. 先前创建的一批事件由在UOW(工作单元)中订阅此TEP的事件处理程序处理在提交UOW之前,跟踪令牌存储在令牌存储中。

  4. TEP状态包含有关事件处理进度的信息 - 段,TEP是否跟上事件处理,TEP是否正在重放事件以及实际的跟踪令牌。

在事件处理停止后(显式或错误),TEP释放该段,以便另一个处理器可以声明它并继续处理。

错误处理

在跟踪事件处理中,事件在不同的线程中处理,这使得错误处理更加复杂。为解决此问题,Axon提供了可在TEP上配置的错误处理程序,并在事件处理组件中发生异常时执行操作。默认情况下,会传播异常,最终导致TEP释放其声明并开始重试。如有必要,可以向TEP提供自定义错误处理程序。建议是明确定义错误情况并用相应的例外表示。有了这个,错误处理程序可以使用不同的策略对它们进行操作,以解决意外行为。

结论

跟踪事件处理是Axon Framework中一个非常强大的机制,它为我们提供:

  • 重放事件的能力 - 事件源系统的一个重要优势是能够根据过去构建新投影,或者在需求发生变化时重建现有投影。

  • 位置透明度 - 在您想要的任何节点中处理您的事件,只需确保您有权访问事件流和令牌存储。

  • 性能 - 在同一节点上启动多个段以并行处理它们并加快处理速度。

在CQRS体系结构中,查询模型与命令模型分开更新,这使我们可以以不同方式扩展查询模型。在这种情况下(以及许多其他情况),跟踪处理是事件处理的首选方式。因此,使用事件存储时,跟踪处理是默认设置。


猜你喜欢

转载自blog.51cto.com/14009535/2327696