Temporal Go SDK是持久化执行引擎,其Workflow函数必须确定性、纯函数,禁止非确定性操作;所有外部I/O须移入Activity,并配置超时与重试策略。

Temporal Go SDK 不是“又一个任务队列”,它是用确定性重放 + 持久化事件日志来保证长时业务最终一致的底层引擎。直接上手写 Workflow 和 Activity 之前,必须先区分清楚:哪些逻辑该进工作流函数,哪些必须拆成活动函数——混在一起写,本地跑得通,上线必丢状态、必重放失败。
Workflow 函数必须是纯函数,不能含任何非确定性操作
常见错误现象:Workflow 函数里调用 time.Now()、rand.Intn()、os.Getenv() 或直接访问数据库/HTTP 客户端,导致重放时时间戳不一致、随机数不同、环境变量缺失,进而触发 Non-deterministic error 致使工作流卡死在 Running 状态。
- 只允许调用 Temporal 提供的确定性 API:
workflow.Sleep()、workflow.ExecuteActivity()、workflow.SideEffect()(用于封装一次性非确定性计算) - 所有外部 I/O、网络调用、系统时间、随机数、文件读写,一律移入
Activity函数 - 如果真需要“当前时间”作为业务输入,应在启动工作流时由客户端传入
startTime参数,而非运行时获取
Activity 函数要显式声明超时和重试策略,别依赖 workflow.Context
使用场景:支付回调、库存扣减、邮件发送、LLM 调用等典型外部依赖操作。这些操作天然具备不确定性,Temporal 的容错能力全靠 Activity 层配置生效。
-
ActivityOptions必须为每个workflow.ExecuteActivity()调用单独设置,不能复用全局 context - 关键参数示例:
StartToCloseTimeout: 10 * time.Second(从调度到完成总耗时上限)、RetryPolicy: &temporal.RetryPolicy{MaximumAttempts: 3} - 避免把多个 HTTP 请求塞进同一个 Activity 函数——它会共享同一套超时和重试,导致慢接口拖垮快接口;应按语义拆分为
ChargePaymentActivity、DeductInventoryActivity等独立单元
Worker 注册顺序和函数名拼写错误,会导致任务永远无法被消费
错误现象:工作流启动成功、日志显示 Scheduled,但 Activity 一直卡在 Started 或 Running,History Service 查不到对应 ActivityTaskStartedEvent。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
立即学习“go语言免费学习笔记(深入)”;
- Worker 启动时注册的函数名(字符串)必须与
workflow.ExecuteActivity()中传入的完全一致,包括大小写和下划线 —— Temporal 不做任何 normalize - 注册顺序无关紧要,但必须在
worker.Start()前完成;漏注册或拼错名,Matching Service 就找不到匹配的 Worker - 调试建议:启动 Worker 后立刻查日志,确认输出类似
Registered activity function 'DeductInventoryActivity';再用 CLI 执行temporal workflow describe --workflow-id xxx,看activityInfo里activityType是否与注册名一致
本地测试用 temporaltest.NewServer() 时,别忽略 SQLite 内存库的事务隔离限制
性能影响:内存 SQLite 默认开启 WAL 模式,但在高并发模拟下仍可能出现 database is locked,尤其当多个测试 goroutine 并发启动工作流时。
- 临时解决:在
temporaltest.NewServer()前加os.Setenv("TEMPORAL_SQLITE_WAL", "false")切换回 DELETE 模式(仅限测试) - 更稳妥做法:单测中用
temporaltest.NewTestWorkflowEnvironment()替代真实 Server,它完全绕过数据库,纯内存执行,速度更快也更稳定 - 注意:test environment 不支持信号(Signal)、查询(Query)、外部事件唤醒等高级功能,集成测试阶段必须切回 real server
真正难的不是写对第一个工作流,而是当流程分支增加、人工节点介入、跨服务回调涌入时,还能让每个 Activity 的超时边界清晰、每次重放可预测、每条历史记录能准确定位到具体哪一行代码出问题。Temporal 的确定性模型是铁律,不是可选项。

















