Temporal 持久化工作流生产部署与故障恢复

Temporal 不是普通的定时任务平台,也不是把一串 HTTP 请求连起来的低代码编排器。它通过持久化工作流事件历史,让业务流程在进程重启、节点故障、网络超时甚至跨越数月之后仍能从确定的位置继续执行。订单履约、审批、支付补偿、数据处理、设备开通和 AI Agent 长任务都适合这一模型,但生产落地需要同时治理服务端、Worker、业务代码兼容性和事件历史增长。

一、先理解执行模型

Temporal 应用主要由 Workflow、Activity、Worker 和 Task Queue 构成。

  • Workflow 描述业务状态机,必须保持确定性;
  • Activity 执行数据库、HTTP、文件和第三方系统等有副作用的操作;
  • Worker 轮询 Task Queue 并执行 Workflow Task 或 Activity Task;
  • Temporal Service 保存事件历史、调度任务、处理超时和重试;
  • Client 负责启动、查询、发信号和取消工作流。

Workflow 代码不是从某一行暂停后保存内存,而是根据事件历史重新播放并恢复状态。因此,Workflow 中不能直接读取当前时间、随机数、环境变量或执行网络请求,必须使用 SDK 提供的确定性 API,外部操作则放入 Activity。

业务系统 → Temporal Frontend → History / Matching / Worker
                         │
                         ├─ 持久化数据库
                         └─ Visibility 检索存储

二、适用与不适用场景

适合:

  1. 流程持续时间长,可能跨越分钟、天或月;
  2. 需要可靠重试、超时、补偿和人工信号;
  3. 服务重启后不能丢失执行进度;
  4. 需要查询流程状态与完整审计轨迹;
  5. 流程由多个微服务共同完成。

不适合把所有短小同步请求都包装为 Workflow。高频、毫秒级、无状态计算更适合普通服务调用;大文件内容也不应塞入 Payload,应保存对象存储引用。Temporal 保证工作流编排可靠,不会自动让非幂等的外部系统变得幂等。

三、生产服务端架构

自建集群通常包含 Frontend、History、Matching 和 Worker Service。小规模可以合并部署,生产环境应按请求类型独立扩缩容,并分散在多个故障域。

1. 持久化数据库

数据库保存 Namespace、任务、事件历史和执行状态,是恢复能力的核心。选择官方支持的数据库类型和版本,采用高可用实例、独立账号、TLS、连接池监控、自动备份和时间点恢复。不要只备份 Temporal Pod 或虚拟机磁盘。

数据库容量应估算:

日增量 ≈ 日工作流数 × 平均事件数 × 平均单事件大小
保留容量 ≈ 日增量 × 历史保留天数 × 安全系数

事件数量比 Workflow 数量更能反映负载。大量短间隔 Timer、频繁 Signal、过细 Activity 和无限重试都会快速扩大历史。

2. Visibility

Visibility 用于按 Workflow Type、状态、时间和 Search Attribute 检索执行记录。它不应被当作业务报表数据库。高基数 Search Attribute 会增加索引成本,应只保存真正用于检索的维度,敏感信息不要写入可见字段。

3. Namespace

按环境、业务域或租户划分 Namespace,并明确历史保留期、访问权限、故障域和配额。生产与测试不能只用名称区分而共用无限权限账号。跨集群复制、全局 Namespace 等能力需要单独设计和演练,不能在故障时临时开启。

四、Worker 的生产部署

Worker 是业务代码真正运行的位置。共享且持续使用的 Task Queue 至少部署两个 Worker 实例,并分散到不同节点或可用区。容量不能只看 CPU,还要看:

  • Schedule-to-Start 延迟;
  • Activity 和 Workflow Task 执行时长;
  • Worker Slot 使用率;
  • Poller 数量;
  • Sticky Cache 命中与回放成本;
  • 下游连接池与限流;
  • Task Queue 积压。

Task Queue 应按业务和资源特征拆分。CPU 密集、IO 密集、需要专用网络、需要 GPU 或访问本地文件的 Activity 不应全部混在同一个队列。

order-workflow      工作流决策
payment-activity    支付调用
warehouse-activity  仓储与物流
manual-review       人工复核

Worker 应作为不可变制品由 CI/CD 发布,连接地址、Namespace 和凭据通过运行时注入。滚动发布不要一次停止全部 Worker,否则 Sticky Cache 同时失效会引发集中回放。

五、超时、重试和幂等

1. Activity 超时

  • Schedule-to-Close:从调度到最终完成的总时限;
  • Start-to-Close:一次尝试的执行时限;
  • Schedule-to-Start:任务等待 Worker 的时限;
  • Heartbeat:长 Activity 报告进度和取消感知。

超时必须来自业务边界,不能统一设置为一个很大的值。Schedule-to-Start 超时通常不应被滥用为容量告警替代品。

2. 重试策略

区分临时错误和永久错误。网络超时、限流和短暂不可用可以指数退避;参数错误、权限拒绝、余额不足等业务失败应明确为不可重试或转人工处理。无限快速重试会放大下游故障。

3. 幂等键

Activity 可能在“外部系统已经成功、完成事件尚未写回”时被再次执行。调用支付、创建工单、发货等接口必须携带稳定幂等键,例如 Workflow ID 加业务步骤名。

idempotency_key = orderId + ":capture-payment:v1"

Temporal 的“至少一次 Activity 执行”语义要求业务端真正实现去重,不能只靠日志判断。

六、工作流代码演进

正在运行的 Workflow 可能使用数月前的事件历史。直接改变分支、循环、Activity 顺序或计时逻辑可能导致非确定性错误。

推荐优先使用 Worker Versioning,把新 Workflow 固定到新版本 Worker,旧执行继续由旧版本处理。无法使用版本管理时,使用 SDK 的 Patch/Version 机制兼容历史。上线前必须用真实历史做 Replay 测试。

升级流程:

  1. 导出具有代表性的事件历史;
  2. 在 CI 中用新代码执行 Replay;
  3. 发布新 Worker 版本但不立即全量路由;
  4. 启动少量新执行验证;
  5. 逐步提升流量;
  6. 等旧执行完成后再下线旧 Worker;
  7. 保留可操作的回滚窗口。

七、长历史与 Continue-As-New

持续接收 Signal、频繁运行 Timer 或永久循环的 Workflow 会积累巨大事件历史,导致回放变慢和存储增长。应使用 Continue-As-New 生成同一业务流程的新 Run,并把必要状态传给下一次执行。

不要等历史接近平台限制才处理。根据事件数、历史大小或业务周期主动续接,并确保 Signal 在切换窗口不会丢失。大对象只传引用,避免每次事件都复制完整 Payload。

八、安全与数据保护

  • 服务端和 Worker 之间启用 TLS/mTLS;
  • Namespace 使用最小权限;
  • 凭据放入密钥系统并定期轮换;
  • Payload 中的个人信息和密钥进行客户端加密或根本不写入;
  • Web UI 放在受控运维网并接入统一身份认证;
  • 审计启动、终止、重置、批量操作和权限变更;
  • 限制批量查询和重放工具权限。

事件历史具有长期保存特征,日志脱敏并不能移除已经写入历史的敏感 Payload。数据分类应在开发阶段完成。

九、监控与告警

服务端重点关注:请求错误率和延迟、Persistence 延迟、History Shard、Task Queue、数据库连接、服务间 RPC、Namespace 配额和节点资源。

Worker 重点关注:

  • Schedule-to-Start 延迟持续升高;
  • Task Queue Backlog 增长;
  • Activity 失败、超时与重试率;
  • Workflow Task 失败和非确定性错误;
  • Worker Slot 长期饱和;
  • Poller 数量异常下降;
  • 长时间没有进展的执行。

业务告警应围绕“订单多久未完成”“审批在哪个状态停留”,而不是只看 Temporal Pod 是否存活。

十、备份、恢复与灾难演练

备份对象包括数据库、可见性存储、动态配置、Namespace 配置、TLS 证书、授权策略、部署清单和 Worker 制品。数据库备份必须验证一致性和可恢复性。

恢复演练建议:

  1. 在隔离环境恢复数据库;
  2. 使用兼容版本启动 Temporal Service;
  3. 验证 Namespace 和执行历史;
  4. 以只读方式检查关键 Workflow;
  5. 部署对应版本 Worker;
  6. 观察 Replay、Task Queue 和下游幂等;
  7. 验证 Signal、Query、取消和新建执行;
  8. 记录 RPO、RTO 与人工步骤。

不能只恢复最新 Worker。若旧执行仍绑定旧版本,必须保留对应制品和依赖。

十一、常见故障排查

Workflow 长时间 Running

查看 Pending Activity、Timer、Task Queue、Schedule-to-Start、最近事件和 Worker Poller。区分任务没被领取、Activity 卡住、等待外部 Signal,还是代码进入了正常长等待。

Activity 重复执行

确认是否发生超时、Worker 崩溃或完成事件写回失败。修复幂等,而不是简单关闭重试。

新版本出现非确定性错误

立即停止新版本接管旧历史,恢复兼容 Worker,用 Replay 找出代码路径差异,再通过版本管理或 Patch 修复。

Task Queue 积压

检查 Worker 数量、Slot、下游限流、长 Activity、分区不合理和发布期间 Sticky Cache 重建。扩容前确认瓶颈不是数据库或下游系统。

数据库延迟升高

同时检查慢查询、连接池、磁盘、锁、历史增长和批量操作。Temporal 服务扩容无法解决数据库写入瓶颈。

十二、生产检查清单

  • [ ] Workflow 与 Activity 边界清晰;
  • [ ] 所有外部副作用具备幂等键;
  • [ ] 超时和重试按业务分类设置;
  • [ ] Worker 至少跨两个故障域;
  • [ ] Task Queue 按资源特征拆分;
  • [ ] 代码升级经过历史 Replay;
  • [ ] 长工作流使用 Continue-As-New;
  • [ ] Payload 不包含不受控敏感信息;
  • [ ] 数据库和 Visibility 有备份与监控;
  • [ ] 旧 Worker 制品可恢复;
  • [ ] 已演练数据库恢复和 Worker 重建;
  • [ ] 告警能够落到具体 Namespace、Queue 和 Workflow Type。

参考资料

Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-11-04 16:12:48

results matching ""

    No results matching ""