可观测性、测试与发布

本节目标

让单个实例可追溯、系统退化可度量、失败路径可复现,并通过版本化发布和运行手册安全运营工作流。

三类可观测信号

  • 事件/日志回答“这个实例发生了什么”。记录状态迁移、步骤、attempt、错误码和操作主体。
  • 指标回答“整体是否退化”。例如队列年龄、成功率、补偿率、尾延迟和成本。
  • trace回答“时间花在了哪里、跨哪些服务”。通过上下文传播关联触发器、消息、步骤、API、LLM 和工具调用。

OpenTelemetry 是生成、收集和导出 traces、metrics、logs 的厂商中立框架。Semantic Conventions 当前页面仍为 1.43.0;消息 spans 页面在 2026-07-22 仍标注 Development,所以采用前应固定版本并核对稳定性,不要把草案字段写死成永久合同。对异步消息,规范以 producer/consumer 的 context propagation 与 span link 关联链路;一条 trace 不是一串可靠的父子关系,也不应因批处理而强造单一 parent。

事件字段与隐私

建议记录可关联的日志字段;只有低基数维度才适合作为指标 label:

workflow.name、workflow.version、instance_id、step、attempt_id、operation_id、state_from/to、event_id、trace_id、error.code、duration、receipt_id、outcome.status、result_fingerprint。

不要把订单全文、完整提示、模型响应、密钥或工具参数默认写入日志。高基数字段(如每个用户 ID、实例 ID 或完整 operation_id)不适合直接作为指标 label,否则成本和查询稳定性变差;可放日志并通过受控查询关联。

相关性不等于可信身份

trace_id、traceparent、消息 metadata 和前端传来的 tenant 字段只用于关联或诊断,不能成为授权输入。入口验证后,应由服务端把 actor、授权范围、策略版本和实例/资源关系写入受控审计事件;执行时仍按当前授权重新检查。这样既能保留跨系统因果链,也不会让可伪造的可观测性字段越过权限边界。

必备指标

维度指标示例能发现什么
入口触发量、去重/冲突率上游重复或协议问题
排队队列长度、最老消息年龄消费能力不足
步骤成功率、attempt、错误分类依赖或版本退化
恢复租约接管、未知结果对账worker/网络故障
补偿触发率、失败率、人工积压业务一致性风险
审批等待时长、过期/拒绝率人工瓶颈与策略问题
端到端p50/p95/p99 时长、deadline 违约用户体验与尾延迟
LLM任务质量、无效结构、token/成本模型或提示回归

告警要配运行手册和责任人。对已自动重试成功的单次错误可作为信息事件;重试耗尽、补偿失败、积压年龄和质量门槛跌破才升级为操作告警。

测试金字塔

  1. schema、条件、幂等键等纯函数单元测试;
  2. DAG 重名、未知依赖、环和 handler 注册静态检查;
  3. producer/consumer 合同测试与旧版本夹具;
  4. 外部依赖 mock 的步骤集成测试;
  5. 虚拟时间测试调度、退避、等待和审批过期;
  6. 故障注入:重复事件、超时、崩溃窗口、迟到结果、补偿失败;
  7. 入口安全测试:伪造/过期签名、重放、同身份异载荷、已撤销 actor 与越权资源;
  8. 从真实脱敏历史恢复/重放的兼容测试;
  9. 端到端与容量测试;LLM 节点另有固定评测集。

顺利路径全部通过不足以证明可靠。最重要的测试往往是“副作用提交后崩溃”“同一键不同参数”“旧批准用于新状态”和“补偿本身永久失败”。

发布策略

工作流定义、handler、schema、提示和模型配置都要版本化。新定义不能无条件覆盖运行中实例:

  • 新实例使用新版本;
  • 旧实例继续旧 worker,或通过已测试的兼容代码恢复;
  • 需要迁移时生成可审计迁移事件;
  • 先影子验证,再灰度少量新实例;
  • 以错误率、积压、补偿率、任务质量和成本作为回退门槛。

回滚代码不会撤销已经发生的付款、通知或发布。发布计划要包含外部副作用的对账与补偿路径。

安全部署最低线

  • 工作流定义只允许受审查来源,CI 验证 schema、链接、测试与依赖;
  • worker 使用非管理员服务身份和最小权限;
  • 密钥来自安全存储,日志与检查点做敏感字段检查;
  • 网络出口、工具和目标资源 allowlist 在服务端执行;
  • 定义、容器/包和迁移脚本可追溯到版本;
  • 审批/人工操作具备经验证身份、理由和按风险保护的审计证据;普通日志本身不自动构成“不可抵赖”证明。

Windows 11 / PowerShell 7 运行手册模板

# 1. 进入项目并确认 Python # 先确认执行环境,而不是把部署故障误判为工作流逻辑错误
Set-Location -LiteralPath 'D:\path\to\workflow' # 替换为自己的工作流项目绝对路径,-LiteralPath 不把通配符当作模式
python --version # 记录实际解释器版本,便于发布时重现验证环境
 
# 2. 先验证定义与测试;-B 不生成 pyc # 发布前先证明静态合同和离线行为仍成立
python -B .\examples\workflow_engine.py --validate # 只校验 DAG/契约定义,不触发真实业务任务
python -B -m unittest discover -s .\examples -p 'test_*.py' -v # 发现并详细执行示例目录中的全部回归测试
 
# 3. 查看当前定义哈希和计划变更;不要在这里输出密钥 # 哈希可关联版本,但不应取代敏感配置管理
Get-FileHash -Algorithm SHA256 .\examples\workflow.json # 记录当前工作流定义内容摘要,便于灰度与回退时精确比对
 
# 4. 灰度后检查队列年龄、失败分类和补偿/审批积压 # 这些信号能发现吞吐、下游失败或人工瓶颈
# 5. 达到回退门槛时停止新触发,排空或固定旧实例版本 # 回退是受控状态迁移,不是删除历史运行记录

Linux 服务可把相同步骤放入 CI 和受控部署脚本;额外核对 systemd/container 的停止宽限期、只读文件系统、非 root 用户、健康检查和信号处理。

故障运行手册

告警先确认安全动作禁止动作
队列年龄上升到达率、消费率、依赖限流降低入口、扩容、延后低优先级无限增加 retry
重复副作用幂等表、键/参数哈希暂停该步骤并对账直接删状态重跑
补偿失败主动作结果、补偿 attempt转人工队列、保留证据强改为 completed
新版错误率高按定义版本切片停止新实例使用新版让旧实例自动跟随 latest
审批积压过期率、责任人、风险级别升级/重新分派/安全过期批量自动批准

练习与自测

为订单流程列出至少 15 个测试,必须覆盖重复触发、同键不同金额、并发领取、审批过期、迟到结果、主动作崩溃窗口、补偿失败、旧检查点和新版定义。再写一页“支付步骤异常”的运行手册。

自测:

  1. 日志、指标和 trace 分别回答什么?
  2. 为什么指标 label 不宜放任意实例 ID?
  3. 定义回滚为何不能撤销外部副作用?
  4. 发布新 worker 前最有价值的历史兼容测试是什么?

下一步

继续 离线 DAG 工作流项目。

参考资料