不能直接用 goroutine + channel 做任务编排,因其缺乏状态持久化、失败重试、跨节点调度和 dag 依赖管理能力,进程崩溃导致任务丢失,且无法满足真实场景下的容错与调度需求。

为什么不能直接用 goroutine + channel 做任务编排
因为缺乏状态持久化、失败重试、跨节点调度和依赖拓扑管理能力。单机 goroutine 在进程崩溃后所有运行中任务就丢了,channel 无法表达 A→B→C 的有向无环图(DAG)依赖,也无法跨机器同步执行状态。
真实场景下,你得面对:节点宕机后任务要自动漂移、某个子任务超时需触发降级、上游失败时下游必须跳过而非卡死——这些都不是语言原语能覆盖的。
- 别把调度逻辑写进业务 handler,否则上线后改个重试策略就得发版
- 避免用内存 map 存任务状态,哪怕加了 mutex,重启即失联
-
context.WithTimeout只管单次调用,不管整个 DAG 的全局 deadline
temporal.io 和 cadence 的选型关键差异
二者同源(Cadence 是 Temporal 前身),但 API 和运维模型已明显分化。现在新项目几乎都该选 Temporal,除非你正维护遗留 Cadence 集群。
Temporal 的 Go SDK 更贴近 Go 习惯:workflow 函数可直接用 workflow.Sleep、workflow.ExecuteActivity,而 Cadence 的 ExecuteActivity 要手动传 ctx 且类型约束更死;Temporal 支持本地开发模式(temporalite),启动一个二进制就能跑全链路,Cadence 则必须搭 Cassandra 或 MySQL。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- Temporal 的 visibility 查询默认走内存索引(
memory模式),适合测试;生产必须切到Elasticsearch,否则查历史任务会慢 - Cadence 的 worker heartbeat 间隔硬编码为 30s,Temporal 允许通过
WorkerOptions.HeartbeatTimeout自定义 - 升级 Temporal Server 时,务必先读 versioning 文档,Workflow 函数签名变更不兼容
如何让 Go workflow 函数真正“可重入”
Temporal 要求 workflow 函数必须幂等,因为可能被反复 replay(比如 history event 追加、worker 重启)。不是加个 sync.Once 就算数——replay 时整个函数从头执行,内存态全丢。
核心原则:所有副作用(发 HTTP、写 DB、发 MQ)必须封装成 activity,由 Temporal 保证最多执行一次;workflow 函数里只做决策、等待、条件分支。
- 错误示范:
http.Post(...)写在 workflow 函数里 → 重放时重复请求 - 正确做法:用
workflow.ExecuteActivity(ctx, sendEmailActivity, input),Temporal 自动记录是否已执行并跳过 - 若 activity 失败,workflow 可捕获
temporal.ActivityError并决定是重试、降级还是标记失败 - 临时状态存
workflow.GetMutableSideEffect,它基于当前 history event 序列生成 deterministic hash,replay 时自动还原
本地调试 workflow 时常见的 nil pointer dereference 错误来源
不是你的代码空指针,而是 Temporal SDK 在 replay 阶段未初始化某些 mock 对象。最典型的是:你在 test 中用 testSuite.NewTestWorkflowEnvironment() 启动环境,但忘记对 activity 注册 mock 实现。
现象是 workflow 函数刚进第一行就 panic,堆栈指向 workflow.ExecuteActivity 内部 —— 因为没注册 activity,SDK 返回 nil,后续调用直接崩。
- 注册必须在
env.RegisterActivity中完成,且函数名要和 workflow 里ExecuteActivity第二个参数完全一致(包括大小写) - mock activity 函数里不要用
time.Sleep,改用workflow.Sleep或注入ctx控制延时,否则测试会不可控 - 用
env.SetWorkerOptions开启EnableLoggingInReplay: true,能看清 replay 时每一步执行了什么
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










