Fork me on GitHub

精简化事件:事件驱动架构的精益力量

精简化事件:事件驱动架构的精益力量

在软件开发领域,事件驱动架构(Event-Driven Architecture,简称 EDA)因其促进实时通信、具有良好的可扩展性以及构建松耦合系统的能力,越来越受到重视。其核心思想是通过事件来实现通信。在使用事件驱动架构的过程中,关于事件的设计一直存在争议:我们应该采用“详细事件”还是“简单事件”?

至今没固定答案;两者在特定情况下各有优势。但根据我的经验,简单事件通常更能使软件运行平稳且具有灵活性。以下是我对这个问题的解释。

1 简单事件与详细事件:选择合适的传递者

以用户注册场景为例:

详细事件

用户注册场景中,详细事件会包含全面而详细的数据。这可能包括姓名、地址、偏好设置甚至头像等所有信息。这些数据非常丰富——但是,我们真的需要立即获取所有这些信息吗?

简单事件

同样在这个场景中,简单事件可能只是一个通知,仅包含用户 ID。它有效地传达了核心信息——如果需要更多细节,可以稍后查询。

可将简单事件(有时称为“事件通知”)比作电报,用最少的数据传递关键信息,下游系统可以根据需求再获取具体细节。
而详细事件(有时称为“胖事件”或“事件携带的状态传输”)更像是一份详尽的报告。它们一开始就携带了大量数据,可能包含了你可能需要的所有信息。可以将其视为用户注册的详尽报告。

2 不止是传递:事件协调系统

在事件驱动架构中,事件的作用不仅仅是传递消息;它们还在系统中引发一系列动作。通过异步通信,事件使得系统的不同部分可以独立运作并动态响应,从而实现松耦合。松耦合意味着系统的各个部分可以独立运作和修改,而不必依赖于其他部分的内部运作。异步通信允许系统各部分在不等待即时响应的情况下进行交互。这种通信方式的好处在于,它支持独立操作和动态响应,使系统能够实时响应事件,而不会因其他进程而受阻。
事件的主要价值在于它告知系统何时发生了某个动作,并帮助系统保持灵活性、可扩展性和稳定性。它们让系统的其他部分知道某个变化已发生,从而触发其他流程。例如,一个“商品购买”事件将触发库存更新、订单确认和发货通知等动作。在 EDA 中,这些动作协同工作。

3 简单事件:EDA 的灵活核心

在事件驱动架构中,简单事件因其简洁、模块化和适应性而非常有用。以下是简单事件之所以重要的原因:

明确的界限

可将简单事件比作幕后工作人员,确保表演过程中的平稳过渡。它们宣布动作——例如“用户评论”——但将数据收集的任务留给专家:API。通过明确任务之间的界限,简单事件促进了模块化。这意味着系统可以独立发展,而不会对整体性能产生负面影响。如果通知系统收到“用户评论”事件,这已经足够启动通知流程;它不需要知道用户的姓名或头像等信息。有了明确的界限和沟通,系统就能和谐地运行。

无特定依赖,适应性强

简单事件具有多功能性;它们可以适应不同的需求。即使消费者数量增加或事件消费的目的随时间演变,它们也能顺利扩展。例如,“用户更新个人资料”事件并不关心新系统是否需要这些数据用于营销——它只是传递核心信息。这种适应性确保了事件在不断变化的消费者环境中仍然保持相关性和高效性。

平衡之道

详细事件在数据粒度和效率之间往往难以取得平衡。决定包含哪些信息总是一个在信息量与负载大小之间权衡的问题。而简单事件则避免了这个问题,因为它们优先考虑简化通信。这意味着它们可以避免过大的负载和复杂且不断变化的数据结构。

4 详细事件:针对特定问题的策略性使用

尽管简单事件在事件驱动架构中具有许多优势,但在某些特定情况下,详细事件仍然有其价值,特别是在需要预先包含数据的情况下。以下是详细事件可能有用的一些情况:

集成事件

设想你正在尝试将支付系统集成到你的平台中。共享的上下文可能有限,因此无缝通信至关重要。在这种情况下,一个设计良好的详细事件,包含订单详情和支付信息,可以弥补这一差距,确保数据顺利交换。

特定时刻的状态

在数据频繁变化的动态领域,消费者通常需要特定时刻的准确数据,比如在尝试捕捉支付信息或通知内容时。通过在事件中包含所有必要数据,可以更好地确保后续的准确呈现。例如,如果一个“支付处理”事件需要包括交易金额、余额和货币信息以进行准确处理,那么它可能需要是一个详细事件。

注意事项

  • 在大型应用程序中,使用详细事件可能不太理想,但在事件消费者与事件生产者位置相近的小型解决方案中,可以考虑使用详细事件。在这种情况下,生产者应
  • 清楚消费者的数据需求,并且确信暴露过多数据不会带来安全风险。然而,随着解决方案的发展,定期重新审视这些假设是至关重要的。

5 DDD 与详细事件:走钢丝

在事件驱动架构中,关于详细事件应该包含哪些数据存在一种两难选择:我们应该为整个聚合体添加数据,还是只为聚合体中的一个实体添加数据?这就是所谓的实体与聚合数据包含困境。在领域驱动设计(DDD)中,实体和聚合是两个基本且相关的概念。实体是具有唯一标识和明确定义行为的个体对象;聚合是由实体组成的一致性集合。聚合通常代表一个完整的业务行为单元。
嵌入实体级数据意味着包括特定于聚合体内单个实体的细粒度信息。虽然这种方法提供了详细的信息,但如果在聚合体中引用了多个实体,它可能会导致事件数量的增加。这种复杂性使得管理模式变化变得困难,并可能违反 DDD 的封装原则。
另一方面,嵌入聚合级数据则意味着包含代表整个聚合体状态或其中相关实体的数据。虽然这种方法可以防止事件数量的膨胀,但它可能会过度暴露并非所有消费者都需要的细节,从而可能导致系统之间的紧耦合。例如,如果消费系统接收到包含超出其实际需求的详细信息的聚合级数据,它可能会开始依赖这些额外的细节。这会创建一种依赖性,使消费系统与生产系统的实现细节紧密耦合。
此外,关于数据隐私也存在潜在的担忧;数据可能会暴露给不应访问它的消费者。然而,API 应该能够很好地处理此类场景,提供对数据访问的控制和安全层,并确保遵守隐私法规。

6 设计权衡

在事件驱动架构中选择使用详细事件还是简单事件时,有许多值得考虑的因素。

  • 偏向最小数据:从触发下游操作所需的最少信息开始。不要在事件中添加不必要的细节。
  • 利用 API 获取详细数据访问:允许消费者通过定义良好的 API 检索他们需要的具体数据,遵循关注点分离原则。
  • 仔细评估详细事件,列出具体需求,并在复杂性与收益之间进行权衡。记录你选择背后的原因,以备将来参考。
  • 将数据包含放在上下文中:如果不可避免地需要嵌入数据,请仔细考虑具体的使用场景。

7 结论

尽管详细事件有其适用的场景,但简单事件的简洁性和灵活性使它们成为大多数事件驱动架构设计中的首选。简单事件通过关注简化、模块化和明确的职责划分,使系统能够顺利增长并适应不断变化的需求,而不影响其稳定性或效率。

然而,我们需要记住的是,没有一种解决方案适用于所有情况。根据你的具体情况、数据需求和通信要求做出明智的选择。不断尝试,积累经验,并充分利用事件驱动架构的潜力,以构建强大且灵活的系统。

关注我,紧跟本系列专栏文章,咱们下篇再续!

作者简介:魔都架构师,多家大厂后端一线研发经验,在分布式系统设计、数据平台架构和AI应用开发等领域都有丰富实践经验。

各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。

负责:

  • 中央/分销预订系统性能优化
  • 活动&券等营销中台建设
  • 交易平台及数据中台等架构和开发设计
  • 车联网核心平台-物联网连接平台、大数据平台架构设计及优化
  • LLM Agent应用开发
  • 区块链应用开发
  • 大数据开发挖掘经验
  • 推荐系统项目

目前主攻市级软件项目设计、构建服务全社会的应用系统。
本文由博客一文多发平台 OpenWrite 发布!

posted @ 2024-08-24 23:50  公众号-JavaEdge  阅读(12)  评论(0编辑  收藏  举报