DeepSeek Harness dsh web 性能排查:每 12 秒断连重连与主线程常驻 1 核
DeepSeek Harness(DSH)的 dsh web 有两种「一直很忙」的典型表现,症状方向完全相反:一种是连接很忙**——面板约每 12 秒闪一次「连接成功」,浏览器看到 code=1006 且非正常关闭,实际是心跳把大快照传输误判成失联、反复重建连接;另一种是CPU 很忙——node 进程的 JS 主线程常驻约 1 核、进程占到 2 核以上、内存峰值十几 GB,来自会话日志冷读、投影缓存被整轮清空、设置描述无缓存三条热路径叠加。** 前者的关键是判定窗口由心跳间隔与允许错过的次数共同决定,而后者的关键是冷读被高频轮询放大——所以两条都能通过「先确认变量、再调参数」解决,不必等核心改动(#9603、#9517)。
DSH插件 每 12 秒断连重连:心跳把大快照误判成失联
一句话结论:心跳按固定间隔要应答,连续错过两次就终止连接;而一次数 MB 的会话历史快照可能让事件循环被占住超过这个判定窗口,应答来不及处理,于是服务端主动断开——前端重连又触发下一次快照,形成自维持循环。 症状是面板反复闪「连接成功」、浏览器显示 code=1006 且 wasClean=false(#9603)。
DSH插件 先排除两个常见误判
这两条很重要,能省掉大半天排查时间(#9603):
- 不是背压问题:该实现用的是通用 WebSocket 库,不是那种自带背压控制的服务端框架,所以「连接被写满」这个方向不成立;
- 别被「文件大小阈值」带偏:讨论中曾出现 68KB–1.6MB 之类的经验阈值,后来被确认为巧合——真正的判据是「排空时间是否超过心跳窗口」,而不是某个固定体积(#9603)。
DSH插件 三步判据与处置
- 确认它是误杀而不是真断网:短链路上(同机或局域网)一切正常,只有在链路较慢或快照较大时出现约 12 秒周期的闪断——即为本条(#9603)。
- 调大心跳间隔(部署侧,最直接):
# 在该网关/typert 相关配置里
websocketHeartbeatIntervalMs: 15000
讨论中确认这个参数是公开的、并有 README 背书(#9603)。
DSH插件 主线程常驻 1 核:三条热路径 + 一个放大器
一句话结论:主线程被三条热路径持续占用——会话日志冷读(全量解压 + 逐行解析)、投影缓存被整轮清空、设置描述无结果缓存;而「移动端应用以几秒间隔轮询」是放大器。 症状是单进程长期占满约 1 核 JS 主线程、进程达 2 核以上、RSS 峰值十几 GB,甚至被超时信号杀掉(#9517)。
DSH插件 三条热路径拆开看
| 热路径 | 现象量级 | 说明 |
|---|---|---|
| 会话日志冷读 | 解析峰值约 3.7 万次/秒 | 全量解压后逐行解析,被移动端 7–9 秒轮询放大(#9517) |
| 投影缓存整轮清空 | 每轮清空后集中重建 | 第三方插件的缓存按容量与存活时间清理,超限时整轮清空(本机实测 269 个文件量级)(#9517) |
| 设置描述无缓存 | 每次调用重算 | 没有结果缓存,也不能按命名空间过滤,调用频繁时持续占用主线程(#9517) |
DSH插件 一条要当心:被撤回的结论不要写进排查
「缓存容量硬编码不可配置」这条结论被报告者自己撤回了——该参数其实是公开配置项、默认值较小。所以如果你在别处看到「容量写死」的说法,不要沿用(#9517)。
DSH插件 四步部署侧处置
- 把准备缓存容量调大到不小于会话数:
preparedSessionCacheSize: 64 # 按你的实际会话数设置,至少不小于它
- 停掉秒级轮询:移动端或监控类客户端如果以 7–9 秒间隔拉取,先把它关掉或拉长——这是把冷读从「持续」变成「偶发」的关键一步(#9517)。
- 减少同时跟随的会话数:少开几个面板/标签页,避免并发冷读(#9517)。
- 验证:用系统监视看进程 CPU 占用。讨论中报告者本地按这些方向改后,主线程从 0.99 核降到 0.12–0.13 核(约 12 倍)(#9517)。
- 注意与内存那条区分:本条的症结是 CPU 热路径,与「内存泄漏导致 OOM」是不同族的问题,排查时不要混(#9517)。 同理,「整屏空白、内容不对」这一族属于渲染侧,与本条的性能/连接族也不要混——可对照 DeepSeek Harness Web 界面渲染异常:折叠吞内容、整屏空白、着色与公式、路径转义。
DSH插件 排查注意事项
这两条看起来差很远,但共用一个排查框架:先固定「变量」(链路质量 / 轮询频率 / 会话数量),再看「参数」,最后才怀疑实现缺陷。 八条要点:
- 先做对照:短链路正常、慢链路闪断 = 心跳误杀;关掉轮询就降负载 = 冷读被放大(#9603、#9517)。
- 别把体积阈值当判据:那条 68KB–1.6MB 的经验值已被确认为巧合(#9603)。
- 分块发快照不是方案(协议上非法)(#9603)。
- 调大心跳要接受「断线发现变慢」的代价(#9603)。
- 减少「已停止会话」的全量快照更贴近根因,优先做(#9603)。
- 轮询是放大器:先把轮询关掉再评估其他手段(#9517)。
- 缓存容量是公开配置项,别沿用「写死」的旧说法(#9517)。
- 修复状态如实:两条在讨论所指版本(
0.2.0-rc.2)里都未修;websocketHeartbeatIntervalMs与preparedSessionCacheSize属公开配置项(可自行调整),而「减少已停止会话的全量快照」「给设置描述加缓存」属核心侧改动。
dsh web 的性能问题常与「同时开了多少东西」直接相关,其中插件数量与装卸动作也是变量之一。若想把插件这一层先排掉,与其在各处手敲命令,不如用 DSH Plugin Hub 这类可视化插件市场:已安装列表、装卸历史与系统日志集中在一个面板里。

常见问题
DeepSeek Harness 的 Web 面板反复闪「连接成功」,是因为网关的应用层心跳把大快照传输误判成了失联。心跳按固定间隔发送并要求应答,连续错过两次就把连接终止;而当一次会话历史快照有数 MB 时,事件循环可能被占住超过这个判定窗口,应答来不及处理,于是服务端主动断开,前端重连又触发下一次快照,形成自维持的循环。规避是把心跳间隔调大(例如调到 15 秒),或减少一次推送的数据量。
DeepSeek Harness 的 dsh web 单进程长期占满一个核,是因为三条主线程热路径叠加:会话日志冷读会全量解压并逐行解析、第三方插件的投影缓存被整轮清空后重建、以及设置描述没有结果缓存且不能按命名空间过滤。如果再有移动端应用以几秒的间隔轮询,冷读会被不断放大。部署侧可以先让准备缓存容量不小于会话数,并停掉秒级轮询,实测能把主线程占用从约一个核降到十分之一左右。
在 DeepSeek Harness 里把会话快照分块发送不行,因为分块发送在一次响应里在协议上是非法的。可行的方向是降低单次快照体积(例如减少一次跟随的会话数量、避免对已经停止的会话重复发送全量快照),或者提高心跳的容忍窗口;把大报文拆成多次独立响应属于协议外做法,不应作为方案。
DeepSeek Harness 里调大心跳间隔的主要副作用是真实断连的发现会变慢——原本几秒内能察觉的网络中断,可能要等到下一个心跳周期才被识别。这是「减少误杀」与「及时发现断线」之间的取舍,建议先确认问题确实是误杀(短链路上一切正常、只有大快照时闪断),再决定调到多大。
DeepSeek Harness 的页面在慢链路上频繁闪断,是因为心跳判定的是「在窗口内有没有收到应答」,而这与链路的排空时间直接相关。同一条数 MB 的快照在高速链路上几秒就传完、在慢链路上可能要十几秒,于是同一套心跳参数在慢链路上就变成了误杀。排查时应把链路质量作为一个变量,而不是只盯服务端参数。
相关术语
- 应用层心跳
- 应用层心跳是 DeepSeek Harness 网关在 WebSocket 之上自己实现的存活检测:按固定间隔发送心跳并要求对端应答,连续错过若干次即终止连接。它与底层 TCP 保活不同,判定窗口由心跳间隔与允许错过的次数共同决定。— https://github.com/deepseek-ai/deepseek-harness/discussions/9603
- 会话冷读
- 会话冷读指读取尚未进入缓存的会话日志时需要全量解压并逐行解析的过程。它在主线程上执行,遇到大日志或高频轮询时会成为主要 CPU 消耗来源。— https://github.com/deepseek-ai/deepseek-harness/discussions/9517
- preparedSessionCacheSize
- preparedSessionCacheSize 是 DeepSeek Harness 里控制「已准备会话」缓存容量的配置项,默认值较小。把它调到不小于实际会话数量,可以避免频繁的冷读与重建。— https://github.com/deepseek-ai/deepseek-harness/discussions/9517
- 投影缓存
- 投影缓存是 DeepSeek Harness 客户端或插件侧用于避免重复计算的派生数据缓存。它按容量上限与存活时间清理,当前实现里存在「超出容量即整轮清空」的行为,会让后续请求集中触发重建。— https://github.com/deepseek-ai/deepseek-harness/discussions/9517
来源
- #9603 — [Bug] Web 面板约每 12 秒断连重连:「连接成功」反复弹出,session/follow 大快照疑似触发服务器端销毁 mux 连接· deepseek-ai(GitHub Discussions)
- #9517 — [Bug] 0.2.0-rc.2:dsh web 的 JS 主线程常驻 1 核、进程 2.35 核 —— 会话冷读 + 投影缓存 + settings.describe· deepseek-ai(GitHub Discussions)