CQRS-ES系统中第三方服务事件订阅与邮件通知部署位置咨询
CQRS-ES架构中副作用操作与事件总线的疑惑
我开发CQRS-ES系统已有数年,研读了大量相关文献,但仍不清楚第三方服务更新及邮件通知等副作用操作的合理执行位置。
典型无副作用场景流程
在无需触发外部系统更新、邮件通知等副作用的典型场景中,流程如下:
- 用户发起命令
- 命令验证
- 创建事件
- 将事件发布至
EventStore - 触发监听该事件的事件处理器
- 更新读写模型
目前步骤5和6为同步执行,计划转为异步。在无CQRS的事件溯源架构中,步骤4、5、6处于同一事务,但CQRS中只需发布事件,事件处理器异步运行,实现最终一致性。
查阅相关文章得知,可通过EventBus发布Integration Events告知其他上下文/服务ES系统的变更,但仍存疑问:
场景1 - 邮件通知
当存在需触发邮件发送的OrderUpdated事件时,有三种方案:
- 由
OrderingService负责更新Order Aggregate并执行发送邮件等副作用- 劣势:聚合需支持可重放且无副作用,此方案违背设计原则,不理想
- 让
EmailNotifierService与其他事件监听器一同监听OrderUpdated事件,与更新读写模型的处理器同步执行- 劣势:同步场景下会阻塞事务,拖慢主流程性能
- 让
EmailNotifierService订阅OrderUpdatedIntegrationEvent,在步骤6之后、事务外执行- 优势:脱离领域事务,不影响主流程,更贴合CQRS最终一致性的设计思路
场景2 - 通用领域事件订阅
现有Inventory服务与Quality Management Service,用户可将Inventory服务的任意事件映射至Quality Management Service,配置需同步的事件及数据。此时边界上下文模糊,难以解耦,针对QualityManagementService的部署有三种思路:
- 将该服务置于主域的其他事件监听器中,判断需关注的事件、映射格式并调用API写入数据
- 问题:主域与Quality Management Service耦合度高,破坏了上下文边界的独立性
- 使用通用集成事件
EVENT_CREATED,让该服务监听此通用事件并执行对应操作- 问题:通用事件语义模糊,难以维护,且无法精准传递事件所需的特定数据
- 拆分操作:主域知晓映射规则,通过钩子判断是否需第三方更新,发布
CREATED_EVENT_WHICH_REQUIRES_THIRD_PARTY_UPDATE集成事件,由该服务监听并完成更新- 优势:主域仅负责判断触发条件并发布语义明确的集成事件,解耦了与第三方服务的具体交互逻辑
核心疑惑
- 若最终所有事件处理器均为异步,是否可暂时将其与其他事件处理器放在一起?
- 为何此类场景需要事件总线?
内容的提问来源于stack exchange,提问作者Giles
相关产品推荐
相关产品推荐

