diff --git a/docs/design/gateway-watchdog.md b/docs/design/gateway-watchdog.md new file mode 100644 index 0000000..959fd17 --- /dev/null +++ b/docs/design/gateway-watchdog.md @@ -0,0 +1,154 @@ +# Gateway Watchdog 设计文档 + +**版本**: 1.0 +**作者**: 庞统(副军师)🐦 +**日期**: 2026-05-28 +**状态**: 已实现 + +--- + +## 1. 问题背景 + +zhipu GLM-5.1 在高峰期返回 **429 限流**("该模型当前访问量过大,请您稍后再试",errorCode=1305),导致: + +1. Gateway 调用失败,`stopReason=error` +2. Session 进入 stalled 状态 +3. stalled 后无法自动恢复,必须手动重启 Gateway +4. 所有 Agent 假死,直到人工介入 + +### 历史记录 + +- 2026-05-26 09:00 CST — 429 导致假死 +- 2026-05-28 ~10:00 CST — 429 导致假死,持续约 1 小时 +- 累计 9 次 session.stalled 事件 + +## 2. 双层防护 + +### 2.1 第一层:跨 Provider Fallback(立即生效) + +**配置**: `~/.openclaw/openclaw.json` + +```json +{ + "model": { + "primary": "zhipu/glm-5.1", + "fallbacks": ["deepseek/deepseek-v4-pro"] + } +} +``` + +- zhipu 429 时自动切 deepseek(不同 provider,不会一起死) +- deepseek-v4-pro 也是免费的,支持 1M 上下文 +- Gateway 原生支持,无需额外代码 + +### 2.2 第二层:Watchdog 自动重启(兜底) + +即使 fallback 也失败(所有 provider 同时挂),watchdog 检测到连续 429 后自动重启 Gateway。 + +## 3. Watchdog 设计 + +### 3.1 检测原理 + +**数据源**: Gateway 的 session jsonl 日志 + +``` +~/.openclaw/agents/{agent-id}/sessions/*.jsonl +``` + +**429 精确特征**: +```json +{ + "message": { + "stopReason": "error", + "errorCode": "1305", + "errorMessage": "429 该模型当前访问量过大,请您稍后再试" + } +} +``` + +**判定条件**(全部满足才算 429): +1. `stopReason === "error"` +2. `errorMessage` 包含 `"429"` 或 `errorCode` 为 `"1305"` + +**不会误判**: +- 正常 stop(`stop=stop`、`stop=toolUse`)不算 +- 其他 error(如 context overflow 的 errorCode 不同)不算 +- `stopReason` 不是 `"error"` 的不算 + +### 3.2 检测流程 + +``` +每分钟执行 + │ + ├─ Gateway health check + │ ├─ 失败 → 直接重启(可能 Gateway 进程已死) + │ └─ 成功 → 继续 + │ + ├─ 遍历所有 agent session jsonl + │ ├─ 跳过 trajectory 文件 + │ ├─ 跳过 120 秒内未修改的文件(性能优化) + │ ├─ 跳过 <100 字节的文件 + │ └─ 统计 CHECK_WINDOW(120s) 内的 429 错误数 + │ + ├─ 判断 + │ ├─ 有新 429 → consecutive++ + │ └─ 无新 429 → consecutive=0(重置) + │ + └─ consecutive >= THRESHOLD(3) → 重启 Gateway + 重置计数 +``` + +### 3.3 参数 + +| 参数 | 默认值 | 说明 | +|------|--------|------| +| CHECK_WINDOW | 120s | 检查最近多少秒的日志 | +| THRESHOLD | 3 | 连续检测到多少次 429 才重启 | +| 检测频率 | 60s | crontab 每分钟执行 | + +### 3.4 状态文件 + +`/tmp/gateway-watchdog-429-count` — 记录连续 429 检测次数,重启后重置为 0。 + +### 3.5 日志 + +`/tmp/gateway-watchdog.log` — 每次执行的检测结果。 + +## 4. 文件位置 + +| 文件 | 路径 | +|------|------| +| 脚本 | `scripts/gateway-watchdog.sh` | +| 本文档 | `docs/design/gateway-watchdog.md` | +| 日志输出 | `/tmp/gateway-watchdog.log` | +| 状态文件 | `/tmp/gateway-watchdog-429-count` | + +## 5. 部署 + +```bash +# crontab 每分钟执行 +(crontab -l 2>/dev/null | grep -v "gateway-watchdog"; \ + echo "* * * * * /path/to/sanguo_moziplus_v2/scripts/gateway-watchdog.sh >> /tmp/gateway-watchdog.log 2>&1") \ + | crontab - +``` + +## 6. 运维 + +```bash +# 查看日志 +tail -20 /tmp/gateway-watchdog.log + +# 查看当前 429 计数 +cat /tmp/gateway-watchdog-429-count + +# 手动测试 +bash scripts/gateway-watchdog.sh + +# 停用 +crontab -l | grep -v "gateway-watchdog" | crontab - +``` + +## 7. 已知局限 + +1. **事后检测** — 检测的是已发生的 429,不是预防 +2. **重启治标** — 重启 Gateway 恢复 stalled session,但不解决 zhipu 限流根因 +3. **无通知** — 重启后没有主动通知用户(可后续加飞书/邮件通知)