Workflow Protocol - State & History
Workflow 构建块内部机制的低层描述。
状态和历史管理
Dapr Workflows 采用事件溯源模式,这意味着工作流的状态是从一系列事件中推导出来的。本文档描述了 Dapr 如何存储和管理这些历史记录和状态。
后端存储:Dapr Actors
默认情况下,Dapr Workflow 引擎使用 Dapr Actors 作为其存储后端。每个工作流实例都映射到一个唯一的 actor 实例。这提供了以下特性:
- 并发控制:Actors 确保在任意时刻只有一个操作在处理工作流实例。
- 可靠性:Actor 状态会持久化到配置好的 Dapr 状态存储中。
- 定时器:Dapr Actors 提供持久化提醒,用于实现工作流定时器。
工作流状态架构
工作流实例(actor)的状态由以下几个组件构成:
1. 元数据
存储有关该实例的高级信息:
instance_id:工作流的唯一 ID。name:工作流的名称。status:当前运行时状态(如 Running、Completed、Stalled 等)。version:工作流版本的名称及任何活跃的补丁。created_at:创建时间戳。last_updated_at:最后活动时间戳。input:原始输入数据。output:最终输出数据(如已完成的)。
2. 历史记录
一系列 HistoryEvent 对象,记录工作流中发生的所有事件。为了优化大型历史记录,Dapr 通常将历史事件以分块或单独键值的形式存储在状态存储中:
- 键格式:
wf-history-<instance_id>-<index> - 事件内容:序列化的 protobuf 消息,包含事件类型、时间戳以及类型特定的数据(如
TaskScheduled、TaskCompleted)。
3. 收件箱(待处理事件)
已发生但尚未被编排器处理(重放)的事件集合。包括:
- 向工作流引发的外部事件。
- 已完成的 activity 结果。
- 已触发的定时器。
当编排器下次运行时,它会"排空"收件箱,将这些事件移入历史记录,然后重放逻辑。
重放与状态重建
当 Worker(SDK)收到工作项时,Dapr 提供历史事件。SDK 通过按顺序重放这些事件来重建编排的内部状态(例如本地变量、当前执行点)。
确定性原则与历史记录
历史记录是"真相的来源"。如果编排代码以非确定性的方式发生变化(例如在现有代码中间添加新的 activity 调用),重放将失败,因为代码的请求将与记录的历史记录不匹配。
清除状态
当清除工作流时,Dapr 会从状态存储中删除元数据及所有相关的历史事件键。这通常是为了在完成工作流后进行清理。