处理事件

在现代系统中,遵循诸如 DDD(领域驱动设计)和 Clean Architecture(整洁架构)等架构最佳实践时,事件是用于建模状态变化以及组件或系统之间异步通信的基本机制。 事件表示在应用程序域中已经发生的事情,并且可能对系统的其他部分或外部服务有兴趣。

领域事件

领域事件表示在应用程序上下文中发生的重要事实。 它们在系统内部生成和消费,允许状态变化以解耦的方式传播,也就是说,对象之间无需直接相互了解。

何时使用领域事件?

  • 当某个操作在领域中产生重大变化,并且需要通知或触发系统的其他部分时。
  • 为保持领域模型的内聚性,使不同的流程能够触发而无需在模块或服务之间创建直接依赖。

Lino 中,创建新的领域事件非常简单。您可以执行:

lino event new

CLI 向导将要求提供:

  • 服务 – 将要创建事件的服务。
  • 模块 – 将要创建事件的模块(仅适用于模块化服务)。
  • 实体 – 事件将创建/关联的实体。
  • 事件类型 – 领域事件或集成事件。
  • 事件名称 – 在领域中使用的名称,与实体关联。

示例

创建与 User 实体关联的领域事件 UserCreated 时, 系统会自动创建名为 UserCreatedDomainEvent 的事件。 该名称清楚地表明,消费该事件的系统部分,用户创建操作已完成。

Lino 生成的结构:

MyApp/
└── src/
    └── Services/
        └── MyService/
            └── Domain/
                ├── MyApp.MyService.Domain.csproj
                └── Aggregates/
                    └── Users/
                        ├── User.cs
                        ├── Errors/
                        ├── Events/
                        │   └── UserCreatedDomainEvent.cs
                        ├── Repositories/
                        └── Resources/

领域事件处理器

Domain Event Handler 是一个类,负责响应 领域事件,执行与应用程序内部状态相关的操作,并始终在相同的事务上下文中运行。

这些处理器的主要目的是保持系统的内聚性和松耦合,使得可以在不增加实体或聚合核心逻辑负担的情况下应用额外规则。

例如,在创建 User 后,可能需要更新统计数据、生成内部日志或通知其他聚合。 这些操作在领域内是合理的,可以同步执行,从而保证即时一致性。

但是,依赖外部资源的操作——例如发送电子邮件或调用第三方 API——不应直接从领域事件中执行,因为这会将事务绑定到缓慢或不稳定的任务。 在这种情况下,领域可以生成一个集成事件(记录在 Outbox 中),稍后以异步且具弹性的方式处理。

主要特性:

  • 响应事件,但绝不修改事件。
  • 仅执行与领域一致性相关的进程内操作。
  • 确保所有操作在同一事务中运行。

要创建新的领域事件处理器,只需运行以下命令:

lino event-handler new

CLI 向导将要求提供:

  • 服务 – 创建事件处理器的服务。
  • 模块 – 创建事件处理器的模块(仅在模块化服务中)。
  • 实体 – 创建事件处理器的实体。
  • 事件类型 – 领域事件或集成事件。
  • 事件 – 将被消费的事件。
  • 事件处理器名称 – 将与实体和领域事件关联的名称。

示例

创建与实体 User 和事件 UserCreatedDomainEvent 关联的领域事件处理器 UserCreated,系统将自动创建名为 UserCreatedDomainEventHandler 的事件处理器。

Lino 生成的结构:

MyApp/
└── src/
    └── Services/
        └── MyService/
            └── Application/
                ├── MyApp.MyService.Application.csproj
                └── UseCases/
                    └── Users/
                        ├── Commands/
                        ├── EventHandlers/
                        │   └── Domain/
                        │       └── UserCreatedDomainEventHandler.cs
                        ├── Logging/
                        ├── Queries/
                        └── Resources/

集成事件

集成事件是指示发生了重要事件的消息,需要与外部系统或其他微服务共享。

与领域事件不同,这里的目标是系统间通信和状态同步。

何时创建集成事件:

  • 当系统中的更改需要反映到其他系统时。
  • 当您的微服务需要发布更改,以便其他微服务做出响应时。

领域事件与集成事件的主要区别:

方面 领域事件 集成事件
目标受众 内部 外部
耦合度 低(内部) 必要(系统间)
处理时间 即时 可以异步,并提供交付保证
持久化需求 非必须 是(为了可靠性和弹性)

Lino 中,创建新的集成事件很简单。 您可以执行:

lino event new

CLI 助手将提示:

  • 服务 – 创建事件的服务。
  • 模块 – 创建事件的模块(仅适用于模块化服务)。
  • 实体 – 创建/关联事件的实体。
  • 事件类型 – 领域事件或集成事件。
  • 事件名称 – 集成事件的名称,与实体关联。

示例

创建与实体 User 关联的集成事件 UserCreated 时,系统会自动生成名为 UserCreatedIntegrationEvent 的事件。 此名称清楚地告诉系统中消费该事件的任何部分,用户创建操作已完成。

Lino 生成的结构:

MyApp/
└── src/
    └── Services/
        └── MyService/
            └── IntegrationEvents/
                ├── MyApp.MyService.IntegrationEvents.csproj
                └── Users/
                    └── UserCreatedIntegrationEvent.cs

集成事件处理器

Integration Event Handler 是一个类,负责消费通常由其他服务或上下文发布的 Integration Event, 并在自身的领域内执行特定操作。

这些处理器通过消息机制(如 RabbitMQ、Kafka、Azure Service Bus 等)接收事件, 通常与 Outbox 模式结合使用,以确保可靠的投递和异步处理。

例如,当 Identity 服务发布 UserCreated 事件时,另一个上下文中的对应处理器可以通过发送欢迎邮件或调用外部 API 来响应。 这些操作可能较慢或容易失败,但由于它们在主事务之外处理,因此不会影响应用的内部一致性。

主要特性:

  • 响应对其他上下文具有业务相关性的事件。
  • 执行可能较慢或外部的操作(例如:发送邮件、调用 API)。
  • 以异步和弹性的方式处理,通常伴随重试和监控。
  • 确保外部失败不会影响原始领域事务。
  • 便于有界上下文和分布式系统之间的集成。

要创建新的集成事件处理器,只需运行以下命令:

lino event-handler

CLI 向导将请求以下信息:

  • 服务 – 创建事件处理器的服务。
  • 模块 – 创建事件处理器的模块(仅限模块化服务)。
  • 实体 – 创建事件处理器的实体。
  • 事件类型 – 域事件或集成事件。
  • 服务 – 要消费的事件所在的服务。
  • 模块 – 要消费的事件所在的模块(仅限模块化服务)。
  • 实体 – 要消费的事件所在的实体。
  • 事件 – 将被消费的事件。
  • 事件处理器名称 – 将关联到实体和集成事件的名称。

示例

创建与 User 实体及 UserCreatedIntegrationEvent 事件关联的集成事件处理器 SendEmailOnUserCreated 时,系统会自动创建一个名为 SendEmailOnUserCreatedIntegrationEventHandler 的处理器。

Lino 生成的结构:

MyApp/
└── src/
    └── Services/
        └── MyService/
            └── Application/
                ├── MyApp.MyService.Application.csproj
                └── UseCases/
                    └── Users/
                        ├── Commands/
                        ├── EventHandlers/
                        │   └── Integration/
                        │       └── SendEmailOnUserCreatedIntegrationEventHandler.cs
                        ├── Logging/
                        ├── Queries/
                        └── Resources/
发生了未处理的错误。 重新加载 🗙