Page 1 of 1

基于事件存储的一致集成事件

Posted: Thu Jan 30, 2025 9:38 am
by suchona.kani.z
下图展示了应用程序事件和集成事件之间的区别Spring 应用程序事件是一种在 Java 应用程序中解耦模块的绝佳方法:即使两个模块(Module1 和 Module2)通过应用程序事件相互通信,这也不会导致两个模块之间产生强依赖性:一个模块也不会调用其他,也不存在任何导入或构建依赖项。两个模块唯一需要知道的是应用程序事件和 Spring 框架。

正如简介中提到的,发送集成事件时存在一致性方面的挑战:如果底层执行失败,则不得发送集成事件。在上面的示例中,如果价格服务中的价格更改提交失败,则不会发送任何价格更改事件。但是,如果执行成功,则应发送集成事件。

原则上,这些一致性要求可以通过使用分布式事务来保证,即通过基于两阶段提交协议的XA标准。然而,分布式事务的声誉值得怀疑,因为它们实施起来很复杂,并且常常导致性能不佳。在许多情况下,该选项无论如何 贷款人员电子邮件列表 都不可用,因为框架不允许 XA 事务。例如,在本文所基于的项目中,REST 被定义为一种用于实现集成事件的技术。但是,REST 或 HTTP POST 请求不支持分布式事务。但不能假定消息代理等其他技术支持 XA 事务 - 例如,RabbitMQ 也不支持它们。

确保一致性的另一种方法是 Vernon 在“实现域驱动设计”中描述的基于事件存储的方法。其工作原理如下:

所有集成事件都在发生事件的服务中序列化,并与应用程序数据存储在同一数据库中。存储集成事件的一个或多个表形成所谓的事件存储。在示例中,这与价格数据位于同一数据库中。
集成事件保留在事件存储中的同一事务中,同时业务应用程序数据也保留在事件存储中。
集成事件仅在事务成功提交后才实际发送。
该解决方案确保仅当发送服务中的业务逻辑成功完成时才发送集成事件。由于集成事件安全地保存在事件存储中,因此可以很容易地多次尝试传递,并且如果需要,如果重复发生故障,则可以进入受控和记录的错误处理。与没有事件存储的更简单的解决方案相比,这是一个显着的优势,其中首先完成数据库事务,然后从正在运行的请求或 Java 线程的上下文数据发送集成事件。如果使用此解决方案发送失败(也称为尽力而为 1 阶段提交),则集成事件就会丢失。