Files
dsh_shenxian/dsh-server-docs/04-调整方案/115-覆盖网络-插件化vs改内核-架构判断.md
T
admin 04776af4b1 docs: 工作区根项目文档批量入仓(04-调整方案 113–128 / 交接单 T09–T21 / ops / archive)
起因:用户 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 代码面)。
2026-09-17 18:24:19 +08:00

117 lines
9.0 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.
# 覆盖网络 · 「插件 vs 改内核」架构判断(2026-09-16)
> **性质**:只读架构评估。⛔ 未改任何代码、未动服务器。
> **取证范围**:`D:\github\dsh_shenxian` 工作树(HEAD `4e3a1a4`)—— `src/supervisor/spawner.ts`(全读)· `src/worker/agent.ts`(头部 62 行 + 接口)· `src/` 结构清点 · 会合中继拆分方案 C1–C4。
> **一句话判定**:**主力形态既不是"dsh 插件"也不是"把东西塞进平台主进程",而是"平台内模块化 + 独立进程/单元"** —— 因为要解决的问题(跨机可达、节点身份、寻址)**发生在实例之外**,dsh 插件机制在架构上够不到;而平台**已有**独立组件的先例(Manager / Worker 分体),顺着走即可。
---
## 一、先拆概念:「插件」在这个项目里有两个完全不同的含义
| | (a) **dsh 官方插件**(profile 层业务插件) | (b) **平台自身的模块化** |
|---|---|---|
| 跑在哪 | **用户实例内部**(dsh 进程内) | 平台进程 / 独立进程 |
| 能做什么 | 加 UI 卡片与分区、注册工具、改实例内行为 | 任何事 |
| 够得到 Worker↔Manager 隧道? | ❌ **架构上够不到**(实例是隔离的运行体,看不见宿主网络栈) | ✅ |
| 发版与回滚 | 独立(候选池 → 用户自助启停) | 跟平台版本走 |
| 现有先例 | `@dsh-local/portal-entry`、`business-plugins` | Manager / Worker 分体、`dshs-worker.service` |
**⇒ 概念澄清(很重要)**:覆盖网络**根本不涉及 `@deepseek-ai/dsh` 主程序** ⇒ **红线 R2 不构成约束**,这套东西整个发生在**平台侧**。所以"插件 vs 改代码"的真正对象是**平台自己的代码仓**,不是 dsh。
---
## 二、三层归属:哪块该放哪
| 层 | 内容 | 建议形态 | 理由 |
|---|---|---|---|
| **数据面组件** | 会合(rendezvous)· 中继(relay)· **发布层**(对外服务暴露) | **独立进程 / 独立 systemd 单元**(可多实例、可换机) | ① 跨机、要碰宿主网络栈 ② 需独立扩缩容与**独立安全加固**(发布层要挡 DDoS)③ 塞进主进程 = 与平台同生共死,违反"控制面/数据面分离" |
| **平台侧集成** | 寻址(`via`)· 节点身份与凭据 · 骨干资格签发 · 容量准入 | **改平台代码** | 必须与**归属 / 租约同源**(单点写),外置就是第二个权威源 = 脑裂 |
| **实例内展示与工具** | 「我的网络 / 我的设备」面板 · agent 的文件互传工具 · 网络状态 | **dsh 插件**(唯一真正适合插件的地方) | 纯实例内 UI 与工具,正是插件机制的用途 |
---
## 三、三种形态的优劣
### A · dsh 插件形态(把覆盖网络做成插件)
**优点**:不动平台内核;可独立发版;用户可自助启停;回滚粒度细(禁用即可)。
**缺点**:**能力边界是硬的** —— 插件跑在实例内部,**看不见宿主网络栈、够不到 Worker↔Manager 隧道、无法参与控制面归属与租约**;覆盖网络的核心问题(跨机可达 / 节点身份 / 寻址)**一个都解决不了**;且插件加载失败会把实例拖进崩溃循环(已有探活回滚机制,但仍是额外风险面)。
**⇒ 判定:只能覆盖第三层(实例内展示与工具),不能承担主力。**
### B · 改内核形态(把会合/中继塞进平台主进程)
**优点**:改动集中;复用现有配置与日志;部署单元不增加;短期最快。
**缺点**:与平台**同生共死**(中继挂了平台一起受影响);中继要**独立扩缩容**时做不到;**对外暴露面与内核同进程**(发布层因此无法做独立安全加固);端口空间与 Manager 全局共享(就是现状的 C2 耦合);版本矩阵无法独立演进。
**⇒ 判定:现状就是这个形态,也正是要拆掉的那个问题。**
### C · 独立组件 + 平台内模块化(**推荐主力**)
**优点**:① **顺着现有架构走** —— 平台已有 Manager / Worker 分体与独立 systemd 单元的先例,不是新造范式;② 控制面/数据面**天然分离**,符合既有分层判据;③ 可独立换机、多实例、独立加固(发布层单独处理 DDoS);④ 每一步可独立回滚(S0–S4 已定)。
**缺点**:多一个部署单元与版本矩阵;本机开发环境要能跑起来(本机是 Windows,需容器或远程);会引入"组件间契约"这条新的维护面。
---
## 四、现有项目代码评估:**设计基本合理,且为这个方向留了缝**
### 4.1 合理之处(有代码证据)
| # | 事实 | 为什么关键 |
|---|---|---|
| 1 | `Spawner` 是干净的后端抽象缝(`launch / stop / status / endpointFor / restartAndProbe`,`src/supervisor/spawner.ts:94-149`) | **新增一种节点 = 多一个实现**,不是改内核;route 层只依赖接口 |
| 2 | Worker agent 有**四条协议纪律**(单向拨入 / 幂等键 `operationId` / 最小接口白名单 / self-fencing,`src/worker/agent.ts:10-17`) | 这**就是**现成的"节点契约"—— 客户端节点可直接复用同一套语义 |
| 3 | 归属 / 租约**只有 Manager 能写**(`epoch+1` fencing) | 与"客户端不可信"天然相容 ⇒ 客户端天生只能当数据面,不会有脑裂 |
| 4 | `tunnelTarget === '' ⇒ 完全不建隧道`(`agent.ts:154`) | **扩展点是预留的**:同机形态零影响,跨机才启用 |
| 5 | 全仓仅 **1 处** `process.platform` 分支(`supervisor/firewall.ts:42`) | 跨平台改造成本低 |
| 6 | `instanceHost` 已是参数(注释:"跨机时填内网 IP") | 寻址**已经是参数化的**,不是写死 |
### 4.2 不足(4 处,均为**已知或有据**的具体欠账)
| # | 不足 | 证据 | 影响 |
|---|---|---|---|
| 1 | **寻址只有 `{host, port}`,表达不了"经谁到达"** | `Endpoint = {host, port}`(`spawner.ts:80-83`);`hostsProvider` 把 `dsh_hosts.endpoint` 直接当 `agentUrl` | 换中继时表里无处表达 ⇒ **必须加 `via` 字段**(越晚改越贵) |
| 2 | **共享 bearer token,无法按节点吊销** | `agent.ts:40` 注释自陈:"本版是 bearer 式比较,**HMAC/防重放留待后续**" | 公网上不成立;**这是项目自己记录的已知欠账**,正好是覆盖网络要补的 |
| 3 | **中继与 Manager 同生共死** | 隧道落在 Manager 的 sshd(`32022`),端口空间与 Manager 全局共享 | 中继不可多实例、不可换机、单点 |
| 4 | **控制面 PG 复用同一条隧道** | `DSHS_TUNNEL_STATIC_PORTS`,设计上含控制面 PG | 换中继时 DB 连接一起断 ⇒ **回滚面比看上去大** |
### 4.3 总评
> **合理程度:中上。** 它是"**为多节点预留了缝**"的设计 —— 抽象缝(Spawner)、协议纪律、参数化寻址、开关式隧道,这四样都在。
> **但也正因为缝开对了,改造的成本主要在"补两个字段 + 分两步换绑定",而不是重构内核。**
> 唯一的严肃欠账是**身份**(共享 token),而项目**自己已经在注释里写明了**这是待办 —— 说明设计者是清醒的,不是漏掉。
---
## 五、能否支持这个方向的改造:**能,且不需要重构**
| 需要的改造 | 现有设计支持度 | 落点 |
|---|---|---|
| 新增一种节点类型(客户端/骨干) | ✅ **直接支持** —— 加一个 `Spawner` 实现 + 复用 agent 四纪律 | 新文件,不动内核 |
| 寻址加 `via` | ⚠️ **需加字段**(向后兼容:有默认值,旧代码不受影响) | S2(方案已出) |
| 会合地址出 env | ✅ **易**(`tunnelTarget` 已是配置;再加一个优先项即可) | S1 |
| 中继独立成单元 | ✅ **易** —— 已定"不换协议、只换绑定关系" | S4 |
| 节点身份(一机一钥) | ⚠️ **要新写**,但接口位置清楚(token 校验点集中) | 拆分方案之后 |
| 发布层 | 🆕 **全新**,与平台主进程分开 = 天然适合独立单元 | 新组件 |
**⇒ 结论:改造路径与现有架构**不冲突**,是"顺着缝往下切",不是"推倒重来"。**会合中继拆分方案 S0–S4 已经把顺序定好了(S0 纯新增文件 + 可选字段,零行为变化)。
---
## 六、我选了什么(可推翻)
1. **主力形态 = 独立组件 + 平台内模块化**,不是 dsh 插件、也不是塞进主进程。
2. **dsh 插件只承担第三层**(实例内的"我的网络/我的设备"面板与文件互传工具)—— 这是唯一适合插件的部分。
3. **先"平台内模块化 + 独立 systemd 单元",暂不拆独立仓库** —— 现在只有两台机器,独立仓库会带来版本矩阵与同步成本;而 S0 的接口抽象已经让"以后再拆"变得便宜。
4. **身份(一机一钥)放在拆分之后**,但它**必须排在任何公网暴露之前**。
---
## 七、本次未做
- ⛔ 未改任何代码、未动服务器、未写文档库(全局执行锁被 `修复轮-决策方法-2b` 占用)。
- 📌 未新增上抛项 —— 待拍板仍是:骨干服务范围(A 自用 / B 全网)+ 发布层形态与成本。