背景:Discord 大面积无响应
某天早晨,多个 Discord 频道突然停止响应。日志显示 DiscordMessageListener 处理时间严重超标:
一个上午触发了 5 次以上 gateway 重启,用户体验完全崩溃。
根因诊断
第一层:sessions.json 文件异常膨胀
第二层:skillsSnapshot 是罪魁祸首
OpenClaw 在每个 session entry 里存储了一份完整的 skillsSnapshot,包含所有 79 个 workspace skills 的系统提示文本。
为什么要存 skillsSnapshot? 设计上服务三个功能:
- 技能变更检测:文件 watcher 监控 SKILL.md 变化,session 检测到版本不匹配时重新构建系统提示
- Env 变量覆盖恢复:某些 skill 配置了 API key 等环境变量,tool call 时从 snapshot 恢复
- 系统提示缓存:避免每次 turn 重新读取 79 个 SKILL.md 文件
设计缺陷:prompt 全文(~70KB)应该全局共享一份 + 各 session 存 hash 引用,而不是每个 session 存一份完整拷贝。500 entries × 75KB vs 1 × 75KB + 500 × 64B,相差约 37 倍。
第三层:同步 I/O 阻塞 event loop
源码中 loadSessionStore() 在 turn 处理的关键路径使用同步读取:
| |
每条 Discord 消息都触发这个流程。加上 OpenClaw 的 turn 队列是串行的,一个慢 turn 会阻塞所有频道。
第四层:cron session 无限积累
40+ 个 cron job 每次运行都创建新的 isolated session entry,每个携带 75KB 的 skillsSnapshot。427 个 cron entries 贡献了约 31MB。
解决方案
立即修复:清理脚本
编写 cleanup-sessions.py,逻辑与 OpenClaw 原生 maintenance 行为对齐:
| |
关键细节:
- 删除 entry 时同步归档对应的
.jsonltranscript 文件 - 归档方式:
rename → xxx.jsonl.deleted.2026-03-04T…Z(与 OpenClaw 行为一致) - OpenClaw 自身会在 30 天后清理
.deleted.文件
优化效果
| 指标 | 之前 | 之后 |
|---|---|---|
| sessions.json | 39.7 MB | 2.8 MB(↓93%) |
| entries 总数 | 511 | 447 |
| 归档 Discord thread | 13 个占着 | 已清除 |
| 过期 session | 51 个 | 已清除 |
长期维护:每日 Cron
Discord Thread 操作与 Session 的关系
| 操作 | Discord 历史 | sessions.json | .jsonl 文件 |
|---|---|---|---|
/new | ✅ 保留 | ✅ 新 sessionId | 旧 → .reset. 归档 |
| Close thread | ✅ 保留 | ❌ 不动 | ❌ 不动 |
| Lock thread | ✅ 保留 | ❌ 不动 | ❌ 不动 |
| Delete thread | ❌ 删除 | ❌ 不动 | ❌ 不动 |
/new 是唯一真正重置 AI session 的方式。 Discord 的 close/lock/delete 只影响 Discord 侧,不碰 OpenClaw 的 session 状态。清理已关闭 thread 的正确姿势:先 /new,然后 Lock thread。
关联 Issues
- #15145(open):skillsSnapshot per-session 存储导致 sessions.json 膨胀 — 已提交详细诊断数据
- #11950(open):提议 per-session 文件替代单一 sessions.json
- #12289(closed):cron session 无限积累
- #9238:Discord 消息队列卡死
后续计划
- 持续关注 #15145 是否有官方修复
- 监控 sessions.json 大小,必要时降低
--days阈值 - 考虑提 PR:cron
:run:entry 不写入 skillsSnapshot(一行代码修复根因)
脚本存档路径:~/.openclaw/workspace/memory/reference/scripts/cleanup-sessions.py
