微信客服会话撑爆 4.2GB:一次压缩超时的排查,和三条存储纪律

举报
阿诺林 发表于 2026/11/05 09:16:35 2026/11/05
【摘要】 引语:卡住我的不是连接断没断,是长跑会话怎么减负。52 万 tokens 的会话、压缩自己先超时、库 4.2GB——排查过程和纪律都摆在这,改改就能用。 1. 起点:一条「Compression aborted」的报障我养着一个微信客服智能体,全天候接学生咨询。10 月 14 日凌晨它转来报障:「Compression aborted: Request timed out. No messa...

引语:卡住我的不是连接断没断,是长跑会话怎么减负。52 万 tokens 的会话、压缩自己先超时、库 4.2GB——排查过程和纪律都摆在这,改改就能用。

1. 起点:一条「Compression aborted」的报障

我养着一个微信客服智能体,全天候接学生咨询。10 月 14 日凌晨它转来报障:「Compression aborted: Request timed out. No messages were dropped — conversation continues unchanged.」

第一眼容易误判成掉线。但日志里 inbound 五分钟一封收得整齐,poll error 一条没有——连接活着,是压缩动作自己超时了。带着反差往下挖,真正的难题浮出来:会话怎么减负,不弄丢对话记忆。

先交代选型:会话存储用 SQLite(单文件 state.db)加 FTS5 索引,理由是「写多读少 + 单机」,单文件备份、拷走即迁移。选型没错,错在我以为单文件库不需要运维。

2. 第一个坑:报障说超时,根因是膨胀

顺着日志翻到 52 万 tokens——客服 dm 会话膨胀到约 524,594,压缩触发线 524,288。就差 300,preflight 压缩被触发,把整个会话历史发给模型做摘要,52 万 tokens 跑超时被中止,报障就来了。

误导性表象:报障说「No messages were dropped」,看着自己扛住了。但代价藏在别处——该会话每条响应耗时 76.7 到 172.8 秒,家长发一句话等近三分钟,体感上「机器人死了」。报错说没事,不代表体验没事。

朴素判别法:分诊只看两样——inbound 是否正常、有没有 poll error。前者正常 + compression aborted = 膨胀型,走减负;前者消失 + poll error = 通道死亡型,走重启。两条路径别混,重启治不了膨胀。

旁证:膨胀不是一天涨上来的。9 月 17 日刚建时正常,9 月 19 日约 457k,10 月中旬爬到 52 万——条数温和(一千七百多条),token 翻近十倍,大头是长工具输出和整段引用。判断规模看 token 读数,别看条数。

3. 方法论:删消息之前,先回答三个问题

减负不是一条 DELETE 就完事。动手前三个问题,后来固化成纪律:

第一问:删之前能不能回溯? 先全量备份:hermes sessions export --session-id 20260917_214954_d1b222 导出 3.3MB JSONL,一千七百多条可回溯。几十秒的成本——永远先备份。

第二问:FTS 索引会不会变孤儿? 我原以为要手动清两个索引,翻 schema 发现 messages 表挂着六个触发器:insert/delete/update 各管两个索引。DELETE 主表,FTS 自动同步,手动清是多余动作——前提是建表时触发器建齐,事后补的只对增量生效。

第三问:删多少? 留最近 100 条,约 29KB、3 万 tokens,脱离触发线一整个量级。为什么不留 500 条?长工具输出的大头恰在「看起来还有用」的中段历史里——留得越多,二次膨胀越快。100 条够上下文连续,删完验证:用户无感。

给运维侧同学的检索提示词,直接抄:

会话库减负检查提示词(改改就能用):
1. 读数:SELECT COUNT(*), SUM(LENGTH(content))/1048576 FROM messages;
   —— 条数与体积分开看,token 以压缩日志 context=~N 为准
2. 归属:SELECT session_id, COUNT(*) c FROM messages GROUP BY session_id
   ORDER BY c DESC LIMIT 5; —— 先找最大会话再动手
3. 触发器:SELECT name FROM sqlite_master WHERE type='trigger';
   —— FTS 索引必须有 insert/delete/update 三件套,
   缺 delete 触发器的库禁止直接 DELETE(索引会变孤儿)
4. 拆解:SELECT name, SUM(pgsize)/1048576 FROM dbstat GROUP BY name
   ORDER BY 2 DESC LIMIT 5; —— 体积按表拆开看,索引吃掉的量
   正文看不出来;先 VACUUM 再 drop 多余索引

4. 第二个坑:删完了,库还是 4.2GB

删 1680 条、留 100 条,验证一切正常,我以为收工了。结果看文件体积:4.2GB。内容三百多 MB,文件是它的十几倍。我照老经验先查删除残留——被数据推翻:freelist 只有 498 页约 2MB,删除残留根本不是主因。

拿 dbstat 按表拆开,真身才露出来。平台差异:sqlite3 CLI 自带 dbstat,python 的 sqlite3 模块可能没编 dbstat(本机即报 no such table)——python 侧用 PRAGMA 三件套替代:

import sqlite3
con = sqlite3.connect("file:state.db?mode=ro", uri=True)
print("内容 MB :", con.execute(
    "SELECT SUM(LENGTH(content))/1048576 FROM messages").fetchone()[0])
print("page_cnt:", con.execute("PRAGMA page_count").fetchone()[0])
print("free    :", con.execute("PRAGMA freelist_count").fetchone()[0])

实测:内容 333MB、freelist 106(约 0.4MB);CLI 侧 dbstat 拆出 trigram 索引 2,052 MB、普通索引 911 MB、正文 939 MB。

七成体积在两个 FTS 索引上,trigram 一个吃掉 2GB。根因一句话:trigram 分词器按任意三字符切片,中文长文本经它索引体积放大四倍多,而我当初建两个索引是为检索实验——实验完了,索引留下,每条消息入三份。修法两步:先 VACUUM 挤掉删除残留的页,再 drop 用不上的索引——实验索引不拆,删消息省的空间追不上索引增量。

连带发现:最大的会话不是客服会话——另一个自动化运营会话已攒到三千六百多条,正朝触发线爬。膨胀是复发的,不是一次性的。它是摘要任务每半小时自我追加,条数稳定增长,属结构性膨胀,和「偶发大输出」是两种病。

5. 兜底方案:三类膨胀,三套处方

三类的处方分开说:

偶发大输出型(客服会话,单条工具输出几万 tokens):治本是删旧留新。窗口选安静期(深夜最佳),留 100 条,先备份再删、删完 VACUUM。链路完整跑通,零重启、零感知。

结构性增长型(摘要任务,每轮固定追加):删除治标,源头在别处——摘要产出外移、命令输出限量、会话只留结论。减负周期设成固定的,别等压缩报障再动手。

索引放大型(双 FTS 索引,正文入三份):治理是 drop 多余索引 + VACUUM。建索引前算放大倍率——trigram 对中文长文本四倍多,两个索引并存必须有分工,实验完尽快拆。

预防提示词,把分诊固化成值班动作:

会话健康值班提示词(可以直接抄):
每天一次,三个数:
1. 库文件体积(ls 看字节)与内容体积(SUM(LENGTH(content)))之比——
   超 3 倍先跑 dbstat 拆表,找索引放大或删除残留
2. 最大会话的条数与最近 token 读数——条数近 2000 或响应超 100 秒即减负,
   勿等压缩超时报障
3. 压缩日志 context=~N 读数——贴着 524,288 触发线就是高危,
   减负提前到触线之前做

6. 总结

三条判断收尾:

第一,报障文案是最坏的取证起点。它说的是数据没丢,不是体验没坏——真相在日志的耗时字段里。

第二,单文件库也是要运维的。SQLite 给了触发器和 freelist,但没人替你跑 VACUUM、盯触发线——觉得「单机不需要运维」的环节,事后都要还。

第三,治本永远是删消息,不是重试压缩。52 万 tokens 体量下,压缩请求自己就是最大负载,重试只会再超时。

那天凌晨改完,客服机器人回话回到秒级,家长毫无感知。索引的账记进值班检查。一句收尾:智能体的会话库和人的书房一样,不是越满越有学问——定期清掉的过程,才是它还能继续学的前提。

作者:林华鼎 · 华为云开发者发展与支持部 · 科技博主系列

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。