事件驱动架构
Event-Driven Architecture (EDA) — 通过事件进行通信的软件架构
01基础概念
事件驱动架构(Event-Driven Architecture, EDA):是通过事件进行通信的软件架构。本质上是一种应用/组件间的集成架构模式。
EDA 在五大典型架构中的位置
官方教程第 1 章将常用架构分为五类典型架构,事件驱动架构是其中之一:
分层架构
表现层 / 业务层 / 持久层 / 数据库
★ 事件驱动架构
通过事件通信,四大组件构成
微核架构
内核 + 即插组件(插件架构)
微服务架构
SOA 的升级,独立部署单元
云架构
处理单元 + 虚拟中间件
EDA 的关键特性
事件和传统的消息不同,事件具有 schema,所以可以校验 event 的有效性;同时 EDA 具备 QoS 保障机制,也能够对事件处理失败进行响应。
02四大组成部分
官方教程第 1 章给出的标准 EDA 结构图,由四个部分组成:
| 组件 | 英文名 | 说明 |
|---|---|---|
| ① 事件队列 | Event Queue | 接收事件的入口。保存系统中的事件并以先来先服务(FIFO)模式进行分派。能够存储任意时间内产生的事件,并支持检索以供将来处理。 |
| ② 分发器 | Event Mediator | 将不同的事件分发到不同的业务逻辑单元。 |
| ③ 事件通道 | Event Channel | 分发器与处理器之间的联系渠道。 |
| ④ 事件处理器 | Event Processor | 实现业务逻辑,处理完成后会发出事件,触发下一步操作。 |
03云原生场景下的 EDA(第 14 章)
在云原生架构相关技术中,EDA 是七大主要架构模式之一(与服务化、Mesh化、Serverless、存储计算分离、分布式事务、可观测架构并列)。
典型的发布-订阅模型
核心机制
- 具备 schema: 事件不同于传统消息,具有结构化定义,可以进行有效性校验。
- QoS 保障: 具备 Quality of Service 保障机制,能对事件处理失败进行响应。
- 异步集成: 服务间是异步集成的,下游处理失败不会被上游感知。
04★ EDA 的五大应用场景(核心考点)
事件驱动架构不仅用于(微)服务解耦,还可应用于以下场景中:
由于服务间是异步集成的,也就是下游的任何处理失败甚至宕机都不会被上游感知,自然也就不会对上游带来影响。
价值: 提升系统整体可用性,故障隔离。
把对服务状态有影响的命令用事件来发起,而对服务状态没有影响的查询才使用同步调用的 API 接口。
结合 EDA 中的 Event Sourcing 机制可以用于维护数据变更的一致性。当需要重新构建服务状态时,把 EDA 中的事件重新"播放"一遍即可。
在服务架构下,往往一个服务中的数据发生变化,另外的服务会感兴趣。
典型例子: 用户订单完成后,积分服务、信用服务等都需要得到事件通知并更新用户积分和信用等级。
在 EDA 下,事件的提供者并不用关心有哪些订阅者,不像服务调用的场景——数据的产生者需要知道数据的消费者在哪里并调用它,因此保持了接口的开放性。
应用于大量事件流(而非离散事件)的数据分析场景,典型应用是基于 Kafka 的日志处理。
在 IoT 时代大量传感器产生的数据,不会像人机交互一样需要等待处理结果的返回,天然适合用 EDA 来构建数据处理应用。
增强韧性 / CQRS / 数据变化通知 / 开放式接口 / 事件流处理
05EDA 与 Serverless 的关系
在云原生架构中,EDA 与 Serverless 紧密相关。Serverless 适用于事件驱动场景,但并非所有应用都适合 Serverless。
Serverless 不适用的场景
- 有状态的应用: 由于 Serverless 的调度不会帮助应用做状态同步,因此云在进行调度时可能导致上下文丢失。
- 长时间后台运行的密集型计算任务: 会无法发挥 Serverless 的优势。
- 涉及频繁的外部 I/O(网络或者存储,以及服务间调用): 因为繁重的 I/O 负担、时延大而不适合。
Serverless 适合的三类场景
① 事件驱动的数据计算任务
典型 EDA 场景与 Serverless 的完美结合
② 计算时间短的请求/响应应用
无需长时间维持上下文
③ 没有复杂相互调用的长周期任务
独立性强、调度简单
06Event Sourcing 事件溯源架构
Event Sourcing 的三个核心观点
- 整个系统以事件为驱动,所有业务都由事件驱动来完成。
- 事件是核心,系统的数据以事件为基础,事件要保存在某种存储上。
- 业务数据只是一些由事件产生的视图,不一定要保存到数据库中。
与 Lambda 架构的关系
Lambda 架构中数据集的存储使用的概念与 Event Sourcing 中的思想完全一致,二者都是在使用统一的数据模型对数据处理事件本身进行定义。
这样在发生错误的时候,能够通过模型找到错误发生的原因,对这一事件进行重新计算以丢弃错误信息,恢复到系统应该的正确状态,以此实现了系统的容错性。
07CQRS 命令查询职责分离
CQRS 是领域驱动设计(Domain-Driven Design, DDD)的一个架构模式,主要用来解决数据库报表的输出处理方式。
CQRS 与 Lambda 架构的关系
Lambda 架构中:
- 数据的修改通过批处理和流处理实现,通过写操作将数据转换成查询时所对应的 View。
- 对数据进行查询时,实际上是通过读取 View 直接得到结果,读出所需的内容。
- 这实际上是一种形式的读写分离。
读操作实际上比写操作要省时得多,如果将读和写操作放在一起,实际处理大量数据时会因为写操作的时长问题影响整体业务的处理效率。在大数据系统中经常处理海量数据,进行读写分离重要性不言而喻。
三者关系总结
| 架构 | 提出者/出处 | 核心思想 |
|---|---|---|
| EDA | 多年发展的架构风格 | 通过事件进行通信的软件架构,组件间集成的范式 |
| Event Sourcing | Martin Fowler / ThoughtWorks | 数据持久化方式,事件是核心,业务数据是事件产生的视图 |
| CQRS | DDD 领域驱动设计 | 读写分离,命令(改状态)与查询(读状态)职责分离 |
08★ ATAM 评估案例:两个 EDA 实例(第 8 章)
官方教程第 8 章用两个事件驱动架构作为 ATAM 方法评估的完整案例:胡佛(Hoover)事件架构和"银行"(Banking)事件架构。
胡佛(Hoover)事件架构
胡佛事件架构由组成事件框架的组件和利用框架服务的应用程序组成。事件由两个主要部分组成:事件类型(Event Type)和事件需要处理的参数(Args)。
- 事件队列(Queue):保存系统中的事件,以 FIFO 模式分派。
- 事件管理器(Event Manager):核心组件,绑定事件队列和事件类型(Type Bindings);维护事件类型注册表(Event Type Registry)数据结构,将事件类型注册到相关关联的处理程序中。一个事件可能关联多个处理程序。
- Handler 组件:所有处理程序的基类,包含:
- STOP handler:负责系统终止。
- IDLE handler:执行"空闲等待",直到用户输入一个输入事件。
评估结论:主进程控制事件类型和应用程序的状态,也控制着事件管理器。具有高度的可修改性,每个组件可以独立出来并重新使用。
"银行"(Banking)事件架构
- 事件有两个主要部分:类型(Type)及其参数(Args)。
- 事件队列(Queue):FIFO 模式;如果没有要返回的事件,则会生成"空闲"事件。
- 基本处理程序(Handler):由三个标准的指定处理程序组成:
- START handler:在启动时初始化系统。
- STOP handler:终止系统。
- IDLE handler:验证输入事件是否有效。如果有效,则事件排队;否则会产生另一个空闲事件。
- 主模块(Main):是框架的一部分。将事件管理器和事件队列绑定到一起。从事件队列中取出一个事件并将其分派给事件管理器进行处理。
两种架构的差异(质量属性视角)
| 质量属性 | 胡佛架构 | "银行"架构 |
|---|---|---|
| 可修改性 | 高(每个组件可独立重用) | 较差(事件管理器暴露给应用程序,没有封装) |
| 可重用性 | 较好 | 较差(组件高度相互依赖,互相协同完成功能) |
| 可靠性 | — | 较好(在初始阶段就消除有缺陷的输入) |
| 额外开销 | 较低 | 较高(空闲事件需要额外处理空间) |
ATAM 评估中涉及的利益相关者
评估这两种架构时考虑的主要利益相关者包括三类:
- 最终用户:通过在命令行界面向系统提供输入来使用"成品"。
- 架构师:事件框架的创建者。
- 应用程序开发人员:负责构建使用事件框架的事件驱动的应用程序。
关键质量属性场景(来自利益相关者)
ATAM 评估四阶段在 EDA 案例中的应用
| 阶段 | 关键步骤 | 说明 |
|---|---|---|
| 阶段 1 演示 | 第 1 步:介绍 ATAM | 评估负责人提供 ATAM 过程的一般信息,说明分析技术与预期结果。 |
| 第 2 步:介绍业务驱动因素 | 定义被评估系统的主要功能,涉及的利益相关者。 | |
| 第 3 步:介绍要评估的体系结构 | 架构团队描述要评估的架构,侧重于体系结构、时间可用性以及质量要求。 | |
| 阶段 2 调查与分析 | 第 4 步:确定架构方法 | 理解系统关键需求的关键架构方法,解释架构的流程控制。 |
| 第 5 步:生成质量属性效用树 | 以"效用"作为根节点,质量属性构成辅助级别,叶节点是质量属性说明。优先级排名为高(H)、中(M)、低(L)。 | |
| 第 6 步:分析体系结构方法 | 找出风险、非风险、敏感点和权衡点。 |
1. 两个架构的结构差异(关键看事件管理器是否被框架封装)
2. 质量属性场景与利益相关者的对应关系
3. 优先级 (H, M, L) 的判断:对系统成功的重要性 + 对架构师的难易度
09考点速记卡
事件具有 schema,可校验有效性 + 具备 QoS 保障机制(可对处理失败响应)
事件 → 队列 → 分发器 → 通道 → 处理器
简单项目可合并为:事件代理 + 事件处理器
韧 · C · 知 · 开 · 流
增强韧性 / CQRS / 数据变化通知 / 开放式接口 / 事件流处理
EDA = 架构模式(整体框架,事件驱动通信)
Event Sourcing = 数据持久化方式(Martin Fowler 提出,事件是核心)
CQRS = 读写分离(DDD 模式,命令/查询职责分离)
胡佛架构:事件管理器在框架内,封装良好 → 可修改性强
银行架构:事件管理器暴露给应用 + 组件高度依赖 → 可修改性、可重用性都较差,但可靠性较好(初始就过滤错误输入)
- EDA 是异步集成 —— 下游失败上游无感(增强韧性的根本原因)
- CQRS 中,命令用事件,查询用同步 API(不要混淆)
- Event Sourcing 的"播放":重新执行历史事件以重建状态
- 事件流 vs 离散事件:事件流处理适用于 Kafka 等海量日志场景
- IoT 天然适合 EDA:传感器数据无需等待返回结果
- Serverless 不适用的三种情况:有状态、长时间密集计算、频繁外部 I/O
对于 EDA 相关案例题,可按以下框架展开:
1. 识别架构组件:事件队列、分发器、通道、处理器是否齐全?
2. 评估同步/异步:是否真正实现异步集成?
3. 检查解耦程度:发布者是否需要知道订阅者?
4. 列举质量属性:可修改性、可重用性、可靠性、性能
5. 识别敏感点/权衡点:事件队列容量、处理器并发能力等