第 26 期:永不崩溃 — 错误处理、重试与告警体系
生产环境的残酷现实
开发时一切正常的工作流,上线后会遇到:API 超时、限速、凭证过期、数据格式异常、第三方服务宕机...
graph TB
subgraph "生产环境错误的三层防线"
L1["🛡️ 第一层: 节点级
单个节点的重试与降级"]
L2["🛡️ 第二层: 工作流级
Error Trigger 全局捕获"]
L3["🛡️ 第三层: 系统级
多渠道告警 + 自动恢复"]
end
L1 --> L2 --> L3
style L1 fill:#22c55e,stroke:#16a34a,color:#fff
style L2 fill:#f59e0b,stroke:#d97706,color:#fff
style L3 fill:#ef4444,stroke:#dc2626,color:#fff1. 节点级错误处理
graph TB
Node[任意节点] --> Error{执行出错?}
Error -->|"成功"| Next[正常继续]
Error -->|"失败"| Strategy{错误处理策略}
Strategy --> S1["🔄 Retry
重试 N 次后继续"]
Strategy --> S2["⏭️ Continue
跳过此节点继续"]
Strategy --> S3["🛑 Stop
停止整个工作流"]
Strategy --> S4["🔀 Output Error
将错误作为输出传递"]
style S4 fill:#22c55e,stroke:#16a34a,color:#fff// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 节点错误处理设置 (Settings → On Error)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 策略 1: Retry on Fail
// - Max Retries: 3 // 最多重试 3 次
// - Wait Between Retries: 2000ms // 重试间隔 2 秒
// 适用: API 瞬时超时、网络抖动
// 策略 2: Continue on Error (最推荐)
// - 节点失败后,将错误信息作为 Item 传递给下游
// - 下游可以用 If 节点判断是否有错误
// 适用: 批量处理中个别 Item 失败不应影响整体
// 策略 3: Stop Workflow
// - 默认行为,任何节点失败立即终止
// 适用: 关键路径节点(如支付确认)
// 策略 4: Output Error Data
// 节点失败时输出的 Item 结构:
// {
// "json": {
// "error": {
// "message": "Request failed with status 429",
// "name": "NodeApiError",
// "httpCode": 429
// }
// }
// }
2. Error Trigger 全局捕获
graph TB
subgraph "正常工作流"
T[Trigger] --> A[节点 A] --> B[节点 B] --> C[节点 C]
end
subgraph "错误处理工作流 (独立的)"
ET[⚠️ Error Trigger
捕获任何工作流的错误] --> Parse[解析错误信息]
Parse --> Log[📝 写入 Data Table]
Parse --> Alert[🚨 Slack/Email 告警]
Parse --> Retry[🔄 尝试自动恢复]
end
B -.->|"💥 异常"| ET
style ET fill:#ef4444,stroke:#dc2626,color:#fff// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Error Trigger 输出的数据结构
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{
"json": {
"execution": {
"id": "exec_abc123", // 失败的执行 ID
"url": "https://n8n.../execution/abc123", // 可直接点击查看
"retryOf": null, // 如果是重试,引用原执行
"mode": "trigger" // manual | trigger
},
"workflow": {
"id": "1",
"name": "天气机器人" // 失败的工作流名称
},
"error": {
"message": "Request failed: 429 Too Many Requests",
"node": "HTTP Request", // 报错的节点名
"timestamp": "2026-04-09T12:00:00Z"
}
}
}
3. 优雅降级模式
graph TB
API[调用外部 API] --> Check{成功?}
Check -->|"✅ 成功"| Normal[正常处理]
Check -->|"❌ 失败"| Fallback{降级策略}
Fallback --> Cache["📦 使用缓存数据
(上次成功的结果)"]
Fallback --> Default["📋 使用默认值
(预设的兜底响应)"]
Fallback --> Queue["📬 加入重试队列
(稍后重试)"]
style Fallback fill:#f59e0b,stroke:#d97706// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 优雅降级实现 (Code 节点)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
const apiResult = $input.first().json;
// 检查是否有错误
if (apiResult.error) {
// 从 Data Table 读取缓存
const cached = $('Data Table').first()?.json;
if (cached && cached.cachedAt) {
// 使用缓存数据,并标记为降级响应
return [{
json: {
...cached.data,
_degraded: true,
_degradedReason: apiResult.error.message,
_cachedAt: cached.cachedAt
}
}];
}
// 缓存也没有,使用默认值
return [{
json: {
message: "服务暂时不可用,请稍后再试",
_degraded: true
}
}];
}
return [{ json: apiResult }]; // 正常流程
4. 多渠道告警
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 告警分级策略
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// P0 (紧急): 支付/关键流程中断
// → Slack #alerts-critical + 短信/电话 + PagerDuty
// P1 (重要): API 连续失败 ≥ 5 次
// → Slack #alerts + Email
// P2 (警告): 单次失败但已自动恢复
// → Data Table 记录即可
// P3 (信息): 降级但仍可用
// → 日志记录
下一步
Ep 27 将探索 Sub-Workflow 子工作流架构——将复杂逻辑拆分为可复用的模块化组件。