起因:用户 2026-09-17 明确「所有文档都要同步,都放在开发仓库 docs 对应文件夹下」。
判据:工作区根 *.md 中在仓库(git ls-files --quotepath=false)搜不到的那些。
入仓 33 份(一律复制,工作区根原件保留不动,避免引用断链):
- 04-调整方案/113–128(16 份 · 原子占号后落盘):覆盖网络 传输方案取舍 / 应用场景与待完善清单 /
插件化vs改内核 / 问题逐条推演 / 参数表与观测口径;会合中继拆分取证与改造方案;
集群化改造方案 Manager-Worker;跨节点迁移与节点自举;项目代码分层范式与迭代风险评估;
搬运与共享重建方案 guest w47→w106;方案规划方法提炼;文档无效信息审计报告;
会话接续机制复盘与修复;会话接续规范;dsh 客户端化部署方案;dsh 桌面客户端开发方案
- 交接单/archive/交接单-已完成/T09–T21(13 份 · 覆盖网络线已完成单归档)
- ops/(2 份运行态指针:接续入口 / 接续包 · 覆盖网络线)
- archive/(2 份临时与内部简报)
已排除(无需重复入仓):覆盖网络线 10 份方案正文已入档案 103–112(文件名不同)。
登记:INDEX.md §二 新增 04-113–128 共 16 行 + §四 追加 T09–T21 说明 + 机器摘要行刷新
(⛔ 未跑 docs-index-stats.py --write:该脚本会按 \r\n 归一化全文件行尾,故改为字节级单行替换);
README.md 追加 1 条入仓指针;docs-manifest.json 复跑 scripts/docs-manifest.py 刷新。
验收:工作区根 47 份 .md —— 同名已入仓 8 / 本次内容一致 29 / 已知改名映射 10 / 未入仓 0;
git status 待提交清单只含本次新增与登记 3 件(未涉 src/ 与 relay 代码面)。
13 KiB
13 KiB
guest 迁移(w-47 → w-106)与「共享重建」方案
状态:规划稿(未执行) | 立稿:2026-09-15 | 触发:用户要求「规划搬运和重建方案;MCN 依赖应以可共享的方式重建,避免后续搬其他用户重复重建」
0. 一句话
只搬 46.3 MB 不可再生数据;792.7 MB 的 Python 环境 + 362.7 MB 的 Node 依赖改为「平台侧共享目录 + 新机重建」,装一次、全平台用户共用。
1. 事实基础(本轮实测,勿再重测)
| 项 | 数值 / 事实 |
|---|---|
| 必搬(不可再生) | 48,539,522 B = 46.3 MB / 1193 文件 |
| 可重建 / 可丢 | ≈ 2.9 GiB:trash 1379.5 · ws/.local(pnpm store) 732.9 · MCN/.venv 792.7 · home/profiles/web/node_modules 362.7 · tmp 26.4 · 各类缓存 ~36 |
| 47 → 106 直连速率 | ~22 KB/s(实测 5.5 min 走 7.3 MB)⇒ 46.3 MB ≈ 35 min;1.7 G 需 21 h ✗ |
| 106 现状 | dshs-worker(19000) 在跑;无 provisioner、无 pnpm 链路;磁盘余 32 G;已建 OS 账号 uid 100002;无 guest 数据 |
| 平台现成机制 | 实例 bwrap 已有 --ro-bind-try /var/lib/dshs/bundled-skills ⇒ 「平台共享只读目录」这套已经存在,共享 venv 走同一套路 |
| 平台官方口径 | src/supervisor/orchestrator.ts:557:额外依赖走 pip install --target <ws>/.pylibs + PYTHONPATH,或自建 venv(不改平台) ⇒ 现状是每用户一份,正是要改的点 |
必搬口径(可复现):
du -sb <用户目录> --exclude=trash --exclude=tmp --exclude=.venv --exclude=node_modules --exclude=.local --exclude=.cache --exclude=.npm --exclude=.node-compile-cache --exclude=.pnpm-cache --exclude=.pnpm-store --exclude=__pycache__
⚠️ 分项相加会大于总量(pnpm store 与 node_modules 硬链接,du 同一 inode 只计一次)—— 报体积别用分项求和。
2. 依赖分三类 → 共享落点
| 类 | 现状(每用户一份) | 目标 | 落点 |
|---|---|---|---|
| Python:MCN venv | 792.7 MB / 人 ✗ | 全平台一份 | /var/lib/dshs/shared/python/mcn@<版本>/,bwrap --ro-bind-try 进实例 |
| Node:Profile 依赖 | 362.7 MB / 人(pnpm store 697 MB 里大部分可复用) | store 共享;node_modules 按 profile 重建 |
共享 store /var/lib/dshs/shared/pnpm-store + pnpm install --frozen-lockfile |
| 系统库 / 字体 | ws/syslibs 5.24 MB + ws/.fonts 15.68 MB |
一份 | 同共享目录(或纳入平台 syslibs 机制) |
收益:第 2 个及以后用户 ⇒ Python/Node 依赖不再重复下载,省 ≈1.15 GB 与 30+ 分钟/人。
3. 关键设计决定(自决,可推翻)
- 共享目录一律只读挂载(ro-bind)⇒ 用户改不坏、不会被各自的 pip 污染;写操作仍走用户自己的
.pylibs。 - 版本化 + 显式升级:目录名带版本(
mcn@1);升级 = 建新目录 → 切挂载 → 保留旧版供回滚。 - MCN 技能改造:不再自带
.venv,改指向共享解释器(脚本里PYTHON_BIN/PYTHONPATH);playwright浏览器二进制放共享目录并设PLAYWRIGHT_BROWSERS_PATH。 - 清单入库:从现 venv
pip freeze导出固定版本的requirements.txt进仓库 ⇒ 共享环境从此可复现(当前项目里没有任何清单,这是必须先补的前置)。 - 平台改动最小化:只加
--ro-bind-try /var/lib/dshs/shared(一行),不动隔离与权限面(仍是只读)。
4. 执行步骤(每步有验收与回滚)
| # | 动作 | 验收 | 回滚 |
|---|---|---|---|
| 1 | 47 上导出 MCN 依赖清单(pip freeze + playwright --version) |
清单文件生成并入库 | 无副作用 |
| 2 | 搬 46.3 MB(§1 口径)到 106,落地后 chown -R 100002:100002 |
字节数/文件数与 47 一致;属主 100002 | 删 106 目标目录 |
| 3 | 106 建共享目录并重建 MCN venv | python -c "import ctranslate2, av, playwright, pandas" 通过 |
删共享目录 |
| 4 | 平台加一行共享挂载 + build + systemctl restart dshs |
实例内 ls /var/lib/dshs/shared 可见 |
去掉那行重启 |
| 5 | 106 上重建 profile 依赖(pnpm + lock + .dsh-stage/*.tgz) |
node_modules 生成、bundles 完整 |
删 node_modules |
| 6 | 迁移归属:POST /api/admin/users/:id/dsh/migrate {"targetHost":"w-106"} |
host_id=w-106、epoch+1、106 出现 scope、guest 能进且文件在 |
再迁回 w-47(数据仍在) |
| 7 | 源目录打包 → /opt/dsh/backups/migrated/guest-<ts>.tar.gz → 删源 |
归档可解压且清单核对一致 | 从归档恢复 |
5. MCN venv 的建法:选定「在 106 重建」(另一条已否决)
- 选定 A · 在 106 重建:干净、可复现、跨机架构正确。代价:需先有清单(步骤 1)、需外网装 ~800 MB。
- 否决 B · 从 47 直接把 venv 拷进共享目录:虽与现状逐字节一致,但走那条 22 KB/s 的链路搬 792.7 MB ⇒ ≈10 小时,且 venv 内含绝对路径,跨机仍有风险 ⇒ 只有缺点,故自决不采用。
6. 与「备份机制」的衔接
- 归档区:
/opt/dsh/backups/migrated/(已建);源目录先打包保留、再删。 - 策略分离(建议):
- 用户核心数据(46 MB 级) → 高频(每日)备份,直接放归档区/对象存储;
- 共享依赖(版本化目录,百 MB 级) → 按版本备份(升级时留一版即可),不必按日。
- 后续接「备份存储空间」:归档目录可整体同步到对象存储(OSS/COS);挂载点与保留策略一次定好,避免各 worker 各写一套。
7. 红线与「不得净变差」复核(R11)
| 红线 | 结论 |
|---|---|
| R2 不改官方 dsh | ✅ 只改平台自己的 spawn 参数 + 用户数据 |
| R7 批量/别人 lane | 迁移是用户明确指令;平台加一行挂载属我 lane,但先单点验证(步骤 4 先在一台 worker) |
| R8 中断在线用户 | 本服务器为开发环境,可直接做,动手前一句话说明 |
| R10 属主 | 目标侧一律 chown -R 100002:100002(与 47 provision-new-users.sh 同口径) |
| R11 净变差 | 共享化让体积/性能/扩展性都变好(每人省 1.15 GB 与 30 分钟);新增的只有一个只读挂载点 ⇒ 权限面不变 ⇒ 无净变差 |
8. 遗留(本方案不解决,需另立)
- 106 没有账号 provisioner(
dsh-provision.path只在 47)⇒ 新用户被调度到 w-106 时无人建 OS 账号,且 worker agent 里也没有 useradd ⇒ 新用户可能起不来。建议把 provisioner 机制铺到每个 worker(否则「新用户落 w-106」这条设计不成立)。 - MCN 项目里没有任何依赖清单(
requirements.txt/pyproject.toml都没有)⇒ 步骤 1 是硬前置。 - 现有用户的
.venv仍是各自的(本方案只对新迁移/新建生效);存量收敛需单独排期。
9. 决策更新(2026-09-15 20:5x · 用户定,开始执行)
- 那 4 个重包「暂不重建」:
playwright==1.62.0·ctranslate2==4.8.2·onnxruntime==1.30.0·av==18.1.0(合计 ≈ 443 MB)⇒ 新环境先不装(MCN 依赖这几项的功能暂时不可用,后续需要时再单独排期)。其余按本方案处理。 - 依赖清单已导出(硬前置完成):
mcn-req-full.txt(51 包)与mcn-req-no4.txt(47 包 —— 重建用这份),落在工作区根目录。 ⚠️ 口径注意:venv 里没有 pip(pip freeze直接UnicodeDecodeError)⇒ 改为扫site-packages/*.dist-info生成清单(等价且更稳)。 - 共享 venv 的基础运行时:现有 venv 由
/usr/local/bin/python3 -m venv创建,指向/usr/local/dsh-runtime/python-3.12.14/bin/python3.12(平台自带的共享 Python 运行时)⇒ 共享 venv 应基于它建,不要用系统 python。 - 执行进度:核心数据搬运已在 106 后台启动 —— 脚本
/root/migrate-guest.sh,日志/var/log/migrate-guest.log,起于 2026-09-15 20:58:16,预计 ~35 分钟(46.3 MB @ ~22 KB/s)。 ⚠️ 该次搬运已作废:其--exclude写的是$U/node_modules、$U/.venv等顶层路径,而真实依赖在ws/…、home/profiles/web/…之下 ⇒ 等于在传全量 3 G(实测 2h10m 只走 133 MB)⇒ 已停并改走 §10 的路径。
10. 执行实况(2026-09-15 23:15 → 09-16 00:2x)—— 已完成
10.1 带宽实测(决定整条路径)
| 链路 | 实测速率 | 结论 |
|---|---|---|
| 47 → 本机(单流) | 126 kbps ≈ 16 KB/s | 瓶颈在 47 出口 |
| 47 → 本机(8 路并行) | 783 kbps ≈ 98 KB/s | 并行 ≈ 6 倍收益 |
| 47 → 本机(16 路并行) | 1122 kbps ≈ 140 KB/s | 接近饱和 |
| 本机 → 106 | 33.5 Mbps ≈ 4.2 MB/s | 极快 ⇒ 作中转最划算 |
| 47 → 106(直连) | ~22 KB/s(历史实测) | 与单流同量级 |
⇒ 选定路径:47 →(8 路并行拉)→ 本机 →(4.2 MB/s)→ 106。
⚠️ 两个实测坑:① 106 → 47 的 scp 并发超 ~10 会被 47 的 sshd 拒绝(Connection closed);② 即便降到 6 路,部分分片仍会静默中断(只写一半)⇒ 接力脚本必须逐片比对大小并重拉(_relay2.sh:第 1 轮补 5 片,第 2 轮归零)。
10.2 实际搬运量(全部经本机中转 + 逐片校验)
| 项 | 原始 | 压缩后 | 说明 |
|---|---|---|---|
| 用户数据(46.3 MB 口径) | 46.3 MB | 30.1 MB / 15 片 | 与 47 对账真实缺口 = 0 |
| dsh-runtime(python3.12.14 + jq + rg) | 110 MB | 39.1 MB / 10 片 | ffmpeg/ffprobe(344 MB)暂不传 |
| profile node_modules(含 .pnpm 实体) | 362.7 MB | 89.6 MB / 11 片 | 压缩比 4x |
| business-plugins(3 个 tgz) | 44 MB | 44.4 MB / 6 片 | file-preview + mcn-suite + univer |
| bundled-skills | 12 KB | — | 直连管道 |
| 合计 | — | ≈ 203 MB | 单流口径需 ~3.5 小时 |
10.3 106 侧「本地重建」(不占 47 带宽,与搬运并行)
- dsh 主程序:
npm i -g @deepseek-ai/[email protected]→/usr/lib/node_modules/@deepseek-ai/dsh(295 MB,与 47 同版本);并补/usr/local/bin/dsh符号链接(平台默认以dsh命令解析)。 - MCN 的 Python venv:按
mcn-req-no4.txt(47 包)在 106 重建 ⇒ 远优于传 819 MB;pandas/jieba/matplotlib/bs4导入通过。 - whitelist-cache 不传:只被 Manager 侧
src/web/routes/whitelist.ts读取,106 是 worker。 - /var/lib/dshs 顶层对齐:
bundled-skills✅ /business-plugins✅ /secret.key已有 ✅ /dshs.db不传(集群下权威库是 47 的 PG)。
10.4 途中发现的三个「实例起不来」级坑(均已修)
- 🔴 106 上
/var/lib/dshs/users是drwx------(47 是drwx--x--x)⇒setpriv --reuid 100002无法穿越该路径 ⇒ 实例必崩。已chmod 711;/var/lib/dshs755 → 711(收窄,对齐 47)。 - 🔴 106 上没有 dsh 主程序(
/usr/local/bin/dsh不存在)⇒ 已装同版本 + 建链接。 - 🔴 106 上没有
/usr/local/dsh-runtime(python 3.12.14 / jq / rg 全缺)⇒ 已传。
10.5 迁移结果(已验收)
POST /api/admin/users/<guest>/dsh/migrate {"targetHost":"w-106"}⇒{"ok":true,"from":"w-47","to":"w-106","epoch":4,"port":44155}- DB:
host_id=w-106、epoch=4(+1)、folder=/var/lib/dshs/users/4092b965-…/ws✔ - 106:
dsh-100002-43771a07.scoperunning、端口 44155 监听、实例 HTTP 401(存活) - 47:guest 的 scope 已消失(只剩 admin 的)
- 插件:
business-plugins 0.3.23/portal-entry 0.5.5在位,特征串命中,实例日志 0 error
10.6 归档与清理
- 源目录归档:
/opt/dsh/backups/migrated/guest-4092b965-20260916.tar.gz(≈1.1 G,含 trash)⇒ 验证后删除 47 上的源目录。 - 临时物清理:47/106 的
/tmp/{gmig,rt,nm,bp}*已清;106 的/root/*.sh已清;本机的分片目录移入_中间产物_待清理/。 - 可复用脚本(在
_中间产物_待清理/):_relay2.sh(带校验重试的接力搬运)·_relay.sh(无校验版)·_mcn-venv-106.sh(远端重建 venv)·_gmig-pull.sh(初版并行拉取)。
11. 遗留(需另立排期)
106 仍缺 ffmpeg / ffprobe⇒ 2026-09-16 00:2x 已解决:106 上直接dnf install -y ffmpeg jq ripgrep(走内网源mirrors.tencentyun.com,43 MB/s、几十秒),再符号链接进/usr/local/dsh-runtime/bin/,并在 bwrap 沙箱内实测可执行(ffmpeg 7.0.2)。 ⚠️ 教训(重要):先测目标机自己的下载能力,别默认"只能从 47 搬" —— 106 的 dnf 内网源极快,从 47 搬 344 MB(~40 分钟)纯属绕路。- 106 仍无账号 provisioner(
dsh-provision.path只在 47)⇒ 新用户被调度到 w-106 时无人建 OS 账号。本次 guest 的账号是手工useradd -u 100002建的。 - MCN 的 4 个重包未装(playwright / ctranslate2 / onnxruntime / av,≈443 MB):按既定决定暂不重建。
- 存量用户仍是各自一份 venv / node_modules:本方案只把 guest 迁完,共享化(§2 的三类落点)尚未实施。
- 106 上的遗留目录:
41a9480e-…(uid 100008,8.9 M,档案 101 的一次性用户残留,PG 行已删)与两个 0 字节目录(2ade6411/5f4a51d2)。