Files
dsh_shenxian/dsh-server-docs/04-调整方案/80-架构与功能优化评估-保留功能前提下的重构方向.md
T
admin 5ad755116e chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进
1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
2026-09-15 18:47:13 +08:00

101 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 80 · 架构与功能优化评估(**保留现有功能**前提下的重构方向 + 去平台痕迹)
- 日期:2026-09-13
- 状态:📋 **评估中(待用户定范围与优先级)**|**P0(去平台痕迹)已落地并上线**
- 触发(用户原话):
1. 「看看能否彻底抛弃 dshs 的架构 以及跳转 portal.html,不要在本项目中体现 dshs 任何内容,把 admin 的门户管理都放到设置选项中 弹窗展示」
2. 「看看如何优化架构和功能,在保留现有功能的基础上 优化重构后有更好的效果」
> **TL;DR**|**不推倒重来** —— 平台本体(账号 / 审批 / 实例生命周期 / 反代 / 配额 / DB)就是要保留的那部分,重写 = 把已验证的东西再赌一次、且**零收益**。
> 真正该做的是**收口与显式化**:本档列 **9 项优化**,按"**今天真实事故暴露的痛点**"排序;其中 **2 项零重启、5 项合一次重启窗口、2 项长期**。
> 另:用户另外两个诉求(不跳 `portal.html`、admin 管理进设置弹窗)**已并入第 4 项**,并给出 R5 下的可行形态。
---
## 一、为什么不是"抛弃架构"(判断依据)
1. **平台本体就是要保留的功能**:账号与审批、实例生命周期(spawn/reap/配额)、反代与子域、DB、插件候选池 —— 这些是"现有功能"的实体。
2. **今天(09-13)的几次事故,根因全是"层层补丁叠加",不是架构本身**:
| 事故 | 直接根因 | 性质 |
|---|---|---|
| 注入脚本整段不执行(浮层/自愈/助手面板全废) | 模板字面量转义被求值(`.join('\n')`) | **补丁缺校验** |
| 浮层视觉升级把脚本写崩 | 同上 | 同上 |
| guest 实例被 OOM 杀(exitCode 137) | 实例上限 384MB < univer gateway 390MB | **配额与插件集合脱钩** |
| 页面"恢复→起来→又被杀"循环 | 恢复逻辑正常,但实例起不来 | **缺"有界恢复"** |
| 自愈链路 5 代补丁(档案 50→51→72→77→78) | 每代只解决当期症状 | **策略未收口** |
⇒ **结论:优化方向 = 收口 + 显式化 + 构建期校验**,而不是换架构。
3. **R5**:任何"把管理能力搬进实例"的动作都属**扩大可见面** ⇒ 必须单独评估(见第 4 项)。
---
## 二、痛点 → 优化项(9 项,按今天事故排序)
| # | 优化项 | 现状痛点(证据) | 手段 | 收益 | 代价 | 重启 | 优先级 |
|---|---|---|---|---|---|---|---|
| 1 | **注入脚本外置 + 构建期硬校验** | `SESSION_*_JS` 是 TS **模板字面量**,转义被求值 ⇒ 今天两次写崩、且旧校验是假绿 | 把脚本挪到 `assets/inject/*.js` 独立文件,构建时内联;`verify-inject`(已建)纳入 `npm run build` 强制 | 彻底消灭该类事故(今天已出 2 次) | 小 | 需一次 | **P0** |
| 2 | **`npm run verify` 统一校验入口** | 今天临时补了 `verify-inject`;静默页/配额/内存联动仍无校验 | 汇成一条命令:tsc + 单测 + 注入脚本**运行时**校验 + 静态页一致性 + 关键页 curl 冒烟 | 假绿无处藏身 | 小 | 否 | **P0** |
| 3 | **实例配额与插件集合联动(自适应内存)** | guest 上限 384 < univer gateway 390 ⇒ **必被 OOM 杀**(10:03 实测 exitCode 137) | 按已启用插件的**内存预估**(档案 67 已有 UI 预估)自动定 `MemoryMax`;`maxIdleInstances` 与宿主余量联动;V8 堆跟随上限(不再硬编码 160) | 不再"装不下就死";探针仍有意义 | 中 | 需一次 | **P0/P1** |
| 4 | **门户管理就地化(不跳 `portal.html`)** | 现在整页跳门户;`desktop/plugins/skills.html` 是三个跳转桩 | 实例内「设置 → **平台管理**」→ **弹窗 iframe** 嵌 `portal.html?embed=1`(隐去平台头/导航);原跳转降级为兜底新窗口 | 不离开工作区、体验连续 | 小-中 | 需一次 | **P1**(**先 R5 评估**) |
| 5 | **自愈策略收口成一份状态机** | 探活/熔断/恢复/告警分散在 proxy 注入脚本 + orchestrator(5 代补丁) | 一张状态图(探活→判据→恢复→冷却→告警)+ 单测覆盖;前端只留"探针 + 呈现" | 以后只改一处;今天这类事故不再复现 | 中 | 需一次 | **P1** |
| 6 | **有界恢复(放弃无限重试)** | guest 今天"恢复→被杀→再恢复"循环 ~35s/次 | 连续 N 次失败即停在明确失败态 + 手动重试(复用档案 78 熔断信号) | 用户看得懂"为什么不行" | 小 | 需一次 | **P1** |
| 7 | **门户页面结构** | `portal.html` 单页 50KB + 3 个跳转桩页 | 保留单页但去掉桩页;或按分区路由化 | 可维护性 | 中 | 否(静态) | P2 |
| 8 | **可观测性统一** | 崩溃只有 stderr、熔断只有日志、内存只有采样文件 | 统一 `/opt/dsh/state/*.json` 快照 + `/api/dsh/status` 汇总(今天已加 `breaker`) | 排障从"翻 journal"变"读一个接口" | 中 | 需一次 | P2 |
| 9 | **文档/代码双库桥接** | 今天多次"对账/推送/幽灵文件"仪式 | 可选:文档与代码同仓同 PR(或明确只保留单向导出) | 少一半同步仪式 | 大 | 否 | P3 |
### 4 项的补充说明(这两条最像"用户真正想要的")
**第 4 项(门户管理就地化)在 R5 下的可行形态** —— 与档案 05 PoC-2 ① 的既有结论对账:
| 做法 | 权限性质 | 判定 |
|---|---|---|
| 实例前端直调平台 admin API(能力下沉) | **真·扩大** | ❌ 与 05 PoC-2 ① + R5 冲突 |
| **弹窗 iframe 嵌平台页**(推荐) | 代码与数据**仍全在平台域**;跨子域被**同源策略**隔开 ⇒ 实例内 agent **读不到 iframe 内容** | ⚠️ 仍需 R5 确认"实例内出现管理入口"这一可见面扩大;缓解:**仅 admin 可见** + 先只读 |
| 维持整页跳转 | 无变化 | ✅ 最保守 |
**技术可行性实测**:`curl -I https://alotbuy.com/portal.html` ⇒ **无 `X-Frame-Options`、无 CSP `frame-ancestors`** ⇒ 同站子域 iframe 内嵌**可直接做**,无需改安全头。
**第 3 项的证据(今天)**:`RSS=390.4MB`(univer gateway,uid 100002) vs 实例上限 **384MB**;10:00 采样 `当前 384/峰值 384/上限 384(100%)`;10:03:11 崩溃 `exitCode=137`(SIGKILL=OOM)。⇒ **配额必须能跟着插件集合走**,否则"启用某插件"就等于"必然被杀"。
---
## 三、分期路线图(建议)
| 期 | 内容 | 重启 | 备注 |
|---|---|---|---|
| **P0** ✅ 部分已做 | **去平台痕迹**(6 个 title + 门户副标题 + design.css,已上线);第 1 项注入脚本外置、第 2 项 `npm run verify` | 第 1 项需一次 | 都可独立做,风险低 |
| **P1**(建议**合一次窗口**做完) | 第 3 项内存自适应 + 第 4 项门户弹窗 + 第 5 项自愈收口 + 第 6 项有界恢复 | **一次重启**(断在线用户 2–5 s) | 第 4 项**先出 R5 评估** |
| **P2** | 第 7 项页面结构、第 8 项可观测性 | 第 8 项需一次 | 体验/排障向 |
| **P3** | 第 9 项文档/代码同仓 | 否 | 工程仪式向 |
---
## 四、明确"不做"(与既有决策/R 线一致)
- ❌ **重写平台 / 换架构**(平台本体即"现有功能",重写零收益高风险)
- ❌ **把管理 API 下沉进实例**(档案 05 PoC-2 ① 结论 + R5)
- ❌ **改内部命名**(systemd 单元 / 路径 / DB 名):收益仅"看不见",代价是牵动 hooks 绝对路径、同步脚本、文档、自动化、备份脚本
- ❌ **给 univer 加内存上限或禁用**:用户明示它是**内存压力探针**(2026-09-13 原话)
---
## 五、待用户拍板
1. **先做哪几项**?我的建议:**P0 两项先做(1、2)**,P1 四项**合一次重启窗口**做完。
2. 是否要我把其中任一项**落成交接单**(8 段式)交执行会话?(遵循本库"规划与执行分离")
---
## 六、附:P0(去平台痕迹)已落地记录
| 文件 | 改动 |
|---|---|
| `web/index.html` | title → `工作台` |
| `web/login.html` / `register.html` | → `登录` / `注册` |
| `web/portal.html` | → `管理门户`;副标题 `dshs 平台管理` → `平台管理` |
| `web/admin.html` | → `管理台` |
| `web/wake.html` | → `正在启动工作区` |
| `web/design.css` | 首行注释去掉平台名 |
- 部署:7 文件 scp(**静态页免重启**);线上逐个取回 `<title>` 已验证;`portal.html` 渲染串只剩「平台管理」。
- 回滚:`git checkout -- web/<file>`(未 commit)。**仅动文案层,未动服务端、未重启、未改权限。**