Files
2026-07-13 21:36:20 +08:00

5.3 KiB
Raw Permalink Blame History

name, version, license
name version license
workflow-orchestration-patterns 1.0.0 MIT

工作流编排模式 —— 详细模式与实操示例

关键设计决策:工作流 vs 活动

基本原则(来源:temporal.io/blog/workflow-engine-principles):

  • 工作流 = 编排逻辑与决策
  • 活动 = 外部交互(API、数据库、网络调用)

工作流(编排)

特征:

  • 包含业务逻辑与协调
  • 必须具有确定性(相同输入 → 相同输出)
  • 不能直接进行外部调用
  • 状态在故障时自动保留
  • 即使基础设施发生故障,也可运行数年

工作流示例任务:

  • 决定执行哪些步骤
  • 处理补偿逻辑
  • 管理超时与重试
  • 协调子工作流

活动(外部交互)

特征:

  • 处理所有外部系统交互
  • 可以是非确定性的(API 调用、数据库写入)
  • 内置超时与重试逻辑
  • 必须是幂等的(调用 N 次 = 调用一次)
  • 生命周期短(通常数秒至数分钟)

活动示例任务:

  • 调用支付网关 API
  • 写入数据库
  • 发送电子邮件或通知
  • 查询外部服务

设计决策框架

是否涉及外部系统?→ 活动
是否为编排/决策逻辑?→ 工作流

核心工作流模式

1. Saga 模式与补偿

目的:实现分布式事务,具备回滚能力

模式(来源:temporal.io/blog/compensating-actions-part-of-a-complete-breakfast-with-sagas):

每个步骤:
  1. 在执行之前先注册补偿
  2. 执行该步骤(通过活动)
  3. 失败时,按相反顺序(后进先出)运行所有补偿

示例:支付工作流

  1. 预留库存(补偿:释放库存)
  2. 扣款(补偿:退款)
  3. 履约订单(补偿:取消履约)

关键要求:

  • 补偿操作必须是幂等的
  • 在执行步骤之前先注册补偿
  • 按相反顺序运行补偿
  • 优雅处理部分失败

2. 实体工作流(Actor 模型)

目的:代表单个实体实例的长期运行工作流

模式(来源:docs.temporal.io/evaluate/use-cases-design-patterns):

  • 一个工作流执行 = 一个实体(购物车、账户、库存项)
  • 工作流在实体生命周期内持续存在
  • 通过信号接收状态变更
  • 支持通过查询获取当前状态

使用场景示例:

  • 购物车(添加商品、结账、过期)
  • 银行账户(存款、取款、余额查询)
  • 产品库存(库存更新、预订)

优势:

  • 封装实体行为
  • 保证每个实体的一致性
  • 天然的事件溯源

3. 扇出/扇入(并行执行)

目的:并行执行多个任务,汇总结果

模式:

  • 启动子工作流或并行活动
  • 等待所有任务完成
  • 汇总结果
  • 处理部分失败

扩缩规则(来源:temporal.io/blog/workflow-engine-principles):

  • 不要扩缩单个工作流
  • 对于 100 万个任务:启动 1K 个子工作流 × 每个处理 1K 个任务
  • 使每个工作流的规模有界

4. 异步回调模式

目的:等待外部事件或人工审批

模式:

  • 工作流发送请求并等待信号
  • 外部系统异步处理
  • 发送信号以恢复工作流
  • 工作流继续处理响应

使用场景:

  • 人工审批工作流
  • Webhook 回调
  • 长时间运行的外部进程

状态管理与确定性

自动状态保留

Temporal 的工作原理(来源:docs.temporal.io/workflows):

  • 完整程序状态自动保留
  • 事件历史记录每个命令和事件
  • 从崩溃中无缝恢复
  • 应用程序恢复到故障前状态

确定性约束

工作流作为状态机执行

  • 重放行为必须一致
  • 相同输入 → 每次相同输出

工作流中禁止的操作(来源:docs.temporal.io/workflows):

  • 线程、锁、同步原语
  • 随机数生成(random()
  • 全局状态或静态变量
  • 系统时间(datetime.now()
  • 直接文件 I/O 或网络调用
  • 非确定性库

工作流中允许的操作

  • workflow.now()(确定性时间)
  • workflow.random()(确定性随机数)
  • 纯函数与计算
  • 调用活动(非确定性操作)

版本化策略

挑战:在旧执行仍在运行时修改工作流代码

解决方案:

  1. 版本化 API:使用 workflow.get_version() 进行安全变更
  2. 新的工作流类型:创建新工作流,将新执行路由到它
  3. 向后兼容:确保旧事件能正确重放

弹性与错误处理

重试策略

默认行为Temporal 会无限重试活动

配置重试:

  • 初始重试间隔
  • 退避系数(指数退避)
  • 最大间隔(重试延迟上限)
  • 最大尝试次数(最终失败)

不可重试的错误:

  • 无效输入(校验失败)
  • 业务规则违反
  • 永久性失败(资源未找到)

幂等性要求

为何至关重要(来源:docs.temporal.io/activities):

  • 活动可能被执行多次
  • 网络故障会触发重试
  • 重复执行必须是安全的

实现策略:

  • 幂等键(去重)
  • 先检查再执行 + 唯一约束
  • 使用更新插入操作替代插入
  • 跟踪已处理的请求 ID

活动心跳

目的:检测停滞的长时间运行活动

模式:

  • 活动定期发送心跳
  • 包含进度信息
  • 若未收到心跳则超时
  • 支持基于进度的重试