From 4e3a1a4a13212558d238c8e0bdc164c62ee489d8 Mon Sep 17 00:00:00 2001 From: maogeigei Date: Wed, 16 Sep 2026 10:25:09 +0800 Subject: [PATCH] =?UTF-8?q?docs(overlay):=20=E8=A6=86=E7=9B=96=E7=BD=91?= =?UTF-8?q?=E7=BB=9C/=E5=AE=A2=E6=88=B7=E7=AB=AF=E5=8C=96=2010=20=E4=BB=BD?= =?UTF-8?q?=E8=A7=84=E5=88=92=E8=BD=AC=E6=AD=A3=E5=BC=8F=E6=A1=A3=E6=A1=88?= =?UTF-8?q?=20103-112=20+=20=E7=99=BB=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 04-调整方案/103-112:可行性评估 · 全球架构复盘 · 骨干层方案 · 百台推演 v2 · 千台全场景推演 · 游戏专项 · 游戏网络与群聊上限调研 · 答疑(群聊/备份/迁移/保密) · 补遗与参考方案 · 九大瓶颈落地方案 - 每份按 交接单/README.md §二 8 段改写(目标/只读前置/范围/决策点/ 步骤/验收/回滚/回报格式)+ 头部状态标注(📋 规划态 · 未实施) - 技术内容不变:附录 A 逐字保留原文全文(仅去其一级标题),已逐份校验字节一致 - 登记:INDEX.md §二 +10 行、03-路线图与待办.md §二 +1 行 - 收尾:docs-audit.py 退出码 0(无 P0)· docs-manifest.py 已刷新 - 本轮零代码、零服务器改动;⛔ 未 push - 占号:103-112(先原子 mkdir .lock- 再写) --- dsh-server-docs/03-路线图与待办.md | 1 + ...103-客户端安装与覆盖网络互联-可行性评估.md | 241 +++++++++++++++ .../04-调整方案/104-覆盖网络-全球架构复盘.md | 266 ++++++++++++++++ .../04-调整方案/105-覆盖网络-骨干层方案.md | 253 +++++++++++++++ .../106-覆盖网络-百台规模推演-v2.md | 254 +++++++++++++++ .../107-覆盖网络-千台全场景推演.md | 289 ++++++++++++++++++ .../108-覆盖网络-游戏专项-MMORPG与MUD.md | 230 ++++++++++++++ ...09-覆盖网络-调研-游戏网络特征与群聊上限.md | 202 ++++++++++++ .../110-覆盖网络-答疑-群聊备份迁移保密.md | 220 +++++++++++++ .../111-覆盖网络-补遗与参考方案.md | 250 +++++++++++++++ .../112-覆盖网络-九大瓶颈落地方案.md | 281 +++++++++++++++++ dsh-server-docs/INDEX.md | 10 + dsh-server-docs/docs-manifest.json | 195 ++++++++++-- 13 files changed, 2670 insertions(+), 22 deletions(-) create mode 100644 dsh-server-docs/04-调整方案/103-客户端安装与覆盖网络互联-可行性评估.md create mode 100644 dsh-server-docs/04-调整方案/104-覆盖网络-全球架构复盘.md create mode 100644 dsh-server-docs/04-调整方案/105-覆盖网络-骨干层方案.md create mode 100644 dsh-server-docs/04-调整方案/106-覆盖网络-百台规模推演-v2.md create mode 100644 dsh-server-docs/04-调整方案/107-覆盖网络-千台全场景推演.md create mode 100644 dsh-server-docs/04-调整方案/108-覆盖网络-游戏专项-MMORPG与MUD.md create mode 100644 dsh-server-docs/04-调整方案/109-覆盖网络-调研-游戏网络特征与群聊上限.md create mode 100644 dsh-server-docs/04-调整方案/110-覆盖网络-答疑-群聊备份迁移保密.md create mode 100644 dsh-server-docs/04-调整方案/111-覆盖网络-补遗与参考方案.md create mode 100644 dsh-server-docs/04-调整方案/112-覆盖网络-九大瓶颈落地方案.md diff --git a/dsh-server-docs/03-路线图与待办.md b/dsh-server-docs/03-路线图与待办.md index 2c0b4d2..7f772cd 100644 --- a/dsh-server-docs/03-路线图与待办.md +++ b/dsh-server-docs/03-路线图与待办.md @@ -104,6 +104,7 @@ | ❌已复核 | ~~Cookie 域收窄~~ | **不做(2026-09-12 用户决定:把这条待办删掉)** —— 共享 Cookie(`Domain=.alotbuy.com`)是**有意设计**:支撑「功能插件 ↔ 门户」**免令牌鉴权**(配合 `server.ts` 的 CORS 白名单),功能插件 v0.2.1 已生产跑通 → **收窄会破坏该链路,收益为零**;结论见档案 05 PoC-2 ② | | 🟡 **待排期** | **T08 集群化的收尾项**(主体与生产切换已完成) | ① `join-worker.sh` 一键装机(现在 join = 装 unit + 起 agent + 注册,三步手工)~~② 隧道服务化~~ ✅ 已收口(本地 20s 定时器自愈,实测 30s 内恢复)③ 集中日志 / metrics ④ `smoke-domain` 定性 ⑤ drop-in 里的 PG 口令建议进一步收权限(现 root 可读)|详见 `交接单/T08 §16.5` | +| 🟡 **待排期** | **覆盖网络 / 客户端化这条线**(**本轮零代码、零服务器改动**) | 已落 **档案 103–112**(10 份规划转正式档案;入口 = 工作区根 `接续入口_覆盖网络线_20260916.md`)。📌 **第一件实事 = 把会合 / 中继从 Manager 里拆成可独立部署的组件**(现为绑在 Manager 上的**单中心 SSH 反向隧道**;所有后续多区域 / 多中心 / 骨干层的前置)。**已定口径**:只做技术实现(跨境合规由使用者自负)· **单机自用 ≠ 不需互联** · 按**异构**设计(中继 45% 设计 / 55% 留余量 + **必须补 443/TCP 兜底**)· 权威状态(归属 / 租约 / 资格)**必须单点控制面** · 游戏重点 = **MMORPG(2D/2.5D) / MUD / 传奇类**。⚠️ **唯一待拍板 = 骨干节点服务范围**(A 只服务自己名下设备 / B 服务全网;**倾向 A→B 渐进**,见档案 105 §七)。之后按 **档案 112「只做三件事」** 开工 | ### 历史决策记录(保留,均已落地) diff --git a/dsh-server-docs/04-调整方案/103-客户端安装与覆盖网络互联-可行性评估.md b/dsh-server-docs/04-调整方案/103-客户端安装与覆盖网络互联-可行性评估.md new file mode 100644 index 0000000..694863d --- /dev/null +++ b/dsh-server-docs/04-调整方案/103-客户端安装与覆盖网络互联-可行性评估.md @@ -0,0 +1,241 @@ +# 103 · 客户端安装与覆盖网络互联 · 可行性评估 +- 日期:2026-09-16 | 状态:📋 **规划态 / 未实施**(本轮零代码、零服务器改动;本档=设计单,尚未开跑) +- 来源:工作区根 `可行性评估_客户端安装与覆盖网络互联_20260916.md`(2026-09-16 转为正式档案,正文见 附录 A) +- 层级:**决策层 · 总纲**(本线其余 9 份档案的共同前置)| 关联:档案 104 · 106–112 +- 触发(用户原话):「当前项目是否可以改造为支持服务部署以及客户端安装(客户端壳套服务器项目),让他们通过覆盖网络互联」 + +> **TL;DR** +> ✅ **可行,且现有架构已给出约 80% 的形状** —— T08 集群化已经把「一台机器 = 一个可被平台拨入的执行体」定义完了, +> 并已有两条现成能力正好解决「没有公网 IP」:① `soft` 隔离模式下实例**只是一个普通子进程**(不需 root / bwrap / systemd); +> ② Worker 用**拨出式 SSH 反向隧道**接入 Manager —— **节点本来就不需要公网 IP**。 +> 真正的缺口 4 条:**客户端运行时落点 · 节点身份(现为共享令牌)· 信任模型反转 · 分发与版本矩阵**。 + +## 一、目标 + +判定「平台能否支持『服务部署 + 客户端安装 + 覆盖网络互联』」,并给出**可增量落地的形态与顺序**、**缺口清单**、**未验证项诚实清单**。 +可判定「做完了没有」= 产出 ① 形态结论(A/B/C 三档取舍)② 缺口 4 条 ③ 若走 B 档的 6 步落地顺序(每步可单独回滚)。 + +## 二、只读前置 + +> 执行前必须先核实的 5 条事实(**均已在本轮取证过,给出可复跑命令**): + +| # | 事实 | 核对方式(期望输出) | +|---|---|---| +| 1 | `soft` 是默认隔离档 ⇒ 实例 = 裸子进程 | `grep -n "isolationMode" src/config.ts` → `'soft' \| 'account'`,默认 `soft` | +| 2 | soft 下不 bwrap / 不 setpriv / 不 systemd-run | `sed -n '660,665p' src/supervisor/orchestrator.ts` → 直接 `spawn(command,args)` | +| 3 | Worker 走**拨出式**反向隧道(节点无需公网 IP) | `sed -n '147,155p' src/worker/tunnel.ts` → `ssh -O forward -R :127.0.0.1:` | +| 4 | 全仓**仅一处**平台分支 | `grep -rn "process.platform" src` → 1 处(`src/supervisor/firewall.ts`) | +| 5 | 节点身份现为**共享令牌 + bearer 比较**(无吊销) | 读 `src/worker/agent.ts` 头部注释(自陈「仅内网 + nft 白名单」) | + +## 三、范围 + +- **改什么**:仅**新增**(新客户端形态 + 新 Spawner 实现 + 新节点身份机制)。**服务端现有路径不动**。 +- **不动什么**:⛔ 不改官方 dsh 主程序与缓存(R2)|⛔ 不改管理面(门户 / DB / 归属 / 租约留在服务器)|⛔ 本轮不动服务器、不改代码。 +- **红线约束**:R5(权限只准收窄 —— 客户端形态下不得下发平台级凭据)|R2|R1(不自动升级 dsh)。 + +## 四、决策点 + +**已定** + +1. **形态已拍板 = 单机自用**(用户原话:「考虑用户自己使用就可以了,不用考虑当作服务器 其他人访问」)⇒ 本档 §三 的 A/C 两档「多人维度」**已放弃**,三档表保留为**历史决策依据**,不再是待拍板项。 +2. **地基 = `soft` 隔离档**(用户已定:「隔离档保持默认 soft」)—— 三份客户端文档同向。 + +**历史决策依据(本档 §三,已不再是开放问题)**:A 只做壳(覆盖网络用不上)|**B 自带实例(本档倾向)**|C 客户端当集群 Worker(需强身份 + 重划合规边界)。 + +**待执行会话复核(非上抛项)**:`soft` 模式在 Windows / macOS 上的实际隔离强度与可运行性 —— **本档已实测修正**:真正的硬阻塞**不在 dsh 运行时**,而在**平台自己的启动方式**(裸名 `spawn('npm')` 在 Windows 报 `ENOENT`;显式 `.cmd` 被 Node 拒 `EINVAL`;改 `cmd.exe /c` 或 `shell: true` 即通)⇒ **代价 = 一处调用方式**。 + +## 五、步骤(若走 B 档;每步自带一次验证) + +1. **验证 dsh 在 Windows / macOS 可运行性**(只读 + 本地装,不动服务器)→ 验证:客户端能起实例 + 实例内 bash 工具可用。 +2. **客户端节点代理**(复用 agent 协议、落 `soft`)—— 先只做 `/healthz` `/launch` `/stop` `/fence` → 验证:台账式幂等(同 `operationId` 重放不产生副作用)。 +3. **通道**:先用现有**拨出式 SSH 反向隧道**打通(零新依赖,当天可验)→ 验证:无公网 IP 的节点可被平台访问。 +4. **身份**:每节点独立凭据 + 吊销(替换共享 bearer)→ 验证:吊销单台后该台拨入被拒,其余不受影响。 +5. **强约束落码**:实例所属 == 客户端主人;**共享密钥不下发客户端**(红线级)→ 验证:断言/测试钉住,构造越权用例必须失败。 +6. **分发与自动升级** + 客户端 × 平台版本兼容矩阵 → 验证:旧客户端连新平台给出可读的「需升级」而非崩。 + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 可行性判定 | 已给出(✅ 可行 + 80% 形状 + 缺口 4 条)—— 本档已交付 | +| B | 形态可选性 | 三档各有优缺、含倾向(B),且**已按用户口径收窄为单机自用** | +| C | 落地可执行性 | 6 步,**每步可单独回滚**,且第 1 步不依赖服务器 | +| D | 未验证项透明 | §五 五条未验证项已列全(Windows/macOS 起实例、soft 实际隔离强度、共享密钥能否按形态裁剪、打洞替换代价、版本矩阵判据) | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- **若按 §五 执行**:全程**只新增**(新客户端形态 + 新 Spawner 实现),**服务端现有路径不动** ⇒ **删客户端即回到现状**。 +- 服务器侧待复核事实(非本档动作):控制面机规格(1.8 GB / 2 核 是 09-08 旧记录);47↔106 跨云实测 **~22 KB/s**。 + +## 八、回报格式 + +执行会话回填:① 每一步的验证命令 + 实际输出 ② 触及的文件清单(应与 §三 一致,多出来的要说明)③ 红线遵守声明(R2 官方包零改动 / R5 未下发平台凭据)④ commit ⑤ 未完成项与卡点(附客观依据)⑥ 若推翻本档任一结论,给出取证。 + +## 九、本档需收口的两处(**未处理,仅报告**) + +1. **双源声明**:`dsh客户端化部署方案_20260916.md`(v3)自称「'客户端化'的**单一来源**」,而 `dsh桌面客户端_开发方案_20260916.md`(v1)与其同日并存且**不同层**(平台侧 vs 交付载体层)⇒ 属「第二个漂移源」风险。建议:v3 定平台侧、v1 定交付层,v3 补一行指针指向 v1。 +2. **判定句互相矛盾**:v3 §12 附录 C 把「官方桌面版(Electron)作为载体」列为**放弃项**,而 v1 恰恰选了这条路(且其「保留壳、换内核」已实际消解该理由)⇒ 并列阅读会读成"同一件事既放弃又采纳"。建议在 v3 §12 该行加注「已被 v1 以'换内核'方式规避,判定失效」。 +> ⚠️ 这两处**不在本档 lane**(两份文档已收口、只读),仅报告不代改。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `可行性评估_客户端安装与覆盖网络互联_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | 状态:**调研稿**(只读取证完成,未改任何代码/服务器) +> 触发:用户问「当前项目是否可以改造为支持服务部署以及客户端安装(客户端壳套服务器项目),让他们通过覆盖网络互联」 +> ⚠️ **本稿落点说明**:文档库(`dsh-server-docs/`)当时被**全局执行锁**占用(持有者 `guest迁移-2307`,09-15 23:08 起)⇒ 按纪律**未写入文档库**,暂落工作区根。锁释放后应转为 `04-调整方案/-*.md` 正式档案并登记。 + +--- + +## TL;DR + +**可行,而且现有架构已经给出约 80% 的形状** —— 因为「一台机器 = 一个可被平台拨入的执行体」这件事,T08 集群化已经定义完了,并且**已经有两条现成能力**正好解决"没有公网 IP": +① `soft` 隔离模式下实例**只是一个普通子进程**(不需要 root / bwrap / systemd); +② Worker 用**拨出式 SSH 反向隧道**接入 Manager —— **节点本来就不需要公网 IP**。 +真正的缺口是 4 条:**客户端运行时落点**、**节点身份(现为共享令牌)**、**信任模型反转**、**分发与版本矩阵**。 + +--- + +## 一、现成资产(可直接复用 · 均带代码坐标,已核实) + +| # | 资产 | 证据 | 为什么关键 | +|---|---|---|---| +| 1 | **`soft` 隔离模式**:实例 = 裸子进程 | `src/supervisor/orchestrator.ts:663` —— `isolationMode !== 'account'` 时直接 `spawn(command, args)`,**无 bwrap / 无 setpriv / 无 systemd-run / 不需要 root**;`src/config.ts:14,180`(`'soft'|'account'`,**默认 `soft`**) | 客户端侧不需要任何特权即可承载实例;Linux 隔离层(bwrap·scope·uid)是**可选增强**,不是前置依赖 | +| 2 | **Worker agent 协议**(≈ 现成的"节点契约") | `src/worker/agent.ts` 头部 4 条纪律:**单向拨入**(不反向连 Manager、不写控制面)· **幂等键 `operationId`** · **最小接口白名单** · **self-fencing(epoch 落后即自停)**;端点:`/healthz` `/launch` `/stop` `/status` `/endpoint` `/fence` `/watchdog` `/fs/*` | 「个人电脑作为节点」所需的核心语义**已经定义并跑通过**(S0–S7 全绿 + 真跨机演练) | +| 3 | **拨出式反向隧道**(解决无公网 IP) | `src/worker/tunnel.ts:152` —— `ssh -O forward -R :127.0.0.1:`;含 20 s 本地定时器自愈(T08 §16.5 ②) | 节点**主动拨出**即可被平台访问,**无需公网 IP、无需端口映射** —— 这正是覆盖网络"中继支"的等价物 | +| 4 | **归属/租约分层判据** | 集群化设计 §1.3:**归属与租约只有 Manager 能写**;Worker 自有本地库 | 客户端天生**只能是数据面**,不会出现"客户端写权威状态"的脑裂 —— 与"个人电脑不可信"天然相容 | +| 5 | **Spawner 接口已抽象** | `src/supervisor/spawner.ts`(`launch / stop / list`)+ `local-*` / `remote-*` 两个实现 | 新增一种"客户端节点"= **多一个 Spawner 实现**,不是改内核 | +| 6 | **平台无跨平台分支** | 全仓仅 `src/supervisor/firewall.ts:42` 一处 `process.platform === 'linux'`(且仅用于 nft 联网护栏) | 除隔离与防火墙外,**代码本身跨平台** | + +**结论**:能移植的不是"平台",而是**实例运行时 + 节点代理**这两块;管理面(门户/DB/归属/租约)留在服务器不动。 + +--- + +## 二、缺口(4 条,按必须先解决排序) + +### 缺口 1 · 客户端运行时落点(技术,自决范围) +- Linux 侧原语分布(已清点):`bwrap`(`orchestrator.ts` / `spawner.ts` / `agent.ts` / `cli.ts` / `routes/admin.ts`)· `systemd-run`(`cli.ts` / `orchestrator.ts`)· `setpriv`(`cli.ts` / `config.ts` / `orchestrator.ts` / `routes/business-plugins.ts`)· `nft`(`cli.ts` / `config.ts` / `orchestrator.ts` / `agent.ts`)· 绝对路径 `/var/lib/dshs` `/opt/dshs` `/usr/local/dsh-runtime`。 +- ⇒ 客户端侧需要一套**平台无关的落点**:Node + `dsh` 可执行 + profile + 工作区目录(Windows 用 `%LOCALAPPDATA%`、macOS 用 `~/Library/Application Support`)。 +- ⚠️ **未验证(须实测)**:`dsh` 自身在 Windows / macOS 上的**沙箱后端行为**。Linux 侧注释显示 dsh 有"沙箱后端探针",探针失败会 `refusing to run the command unconfined`(实例内 bash 被整体拒绝)—— Windows / macOS 上走哪条后端、是否可用,**尚无证据**。 + (验收口径 L2 起:客户端上起一个实例 → `curl` 实例页 200 + 实例内跑一次 bash 工具。) + +### 缺口 2 · 节点身份(现在是共享令牌,公网上不成立) +- 现状自陈(`agent.ts` 头部):token 是**共享密钥 + bearer 式比较**,"仅内网 + nft 白名单";HMAC / 防重放**留待后续**。 +- 个人电脑在公网 ⇒ 共享令牌**无法吊销单个节点**、无法抗重放、一台泄露等于放行全部。 +- ⇒ 必须升级为**每节点独立身份**(客户端证书 / 独立密钥对)+ 准入与吊销,且**通道本身要端到端加密**。 + +### 缺口 3 · 信任模型反转(最重要的一条,不是技术问题而是边界问题) +- 现平台假设:**宿主机由我们掌控**(所以用 uid 隔离"用户 A 防用户 B")。 +- 客户端形态下:**宿主机由用户掌控** ⇒ 原有隔离语义在"防机器主人"这一维上**直接失效**(机器主人本来就能读自己机器上的一切)。 +- ⇒ 必须新增硬约束:**一台客户端上的实例只能属于该客户端的主人**;平台**不得**把别人的实例、别人的数据、或平台级凭据下发到客户端。 + - ⚠️ 现状反例:平台会把**共享模型密钥**注入实例(档案 85/87 的两层密钥中的"共享"那一层)—— 下发到用户掌控的机器等于**把平台密钥交给用户**。 + - ⇒ 客户端形态**必须只用"用户自己的密钥"这一层**;共享层只在服务端实例上使用。 + +### 缺口 4 · 分发与版本矩阵(运维) +- 客户端安装包 + 自动升级 + **客户端版本 × 平台版本兼容矩阵**(现有 `plugin-compat` / `dsh-install.ts` 是同类问题的服务端解,需要客户端版对应物)。 +- 客户端一多,**故障面从"我们的机器"扩到"用户的机器"**(系统时间、磁盘、杀软、代理),排障成本上升。 + +--- + +## 三、形态三档(**真取舍,需用户拍板**) + +> 判据:三档的**最终效果**对用户完全不同(数据在哪、算力归谁、谁能调度),属"业务目标与优先级",不能由技术标准裁决。 + +**A 档 · 客户端只做"壳"(远程访问)** +- 优点:改动最小;安全模型**零变化**;不引入任何跨租户风险;沿用现有实例与全部隔离。 +- 缺点:个人电脑**不成为节点**,算力仍在服务器;离线不可用;覆盖网络在这一档**没有实际用途**。 + +**B 档 · 客户端自带"自己的实例"(平台退化为控制面 + 中继 + 目录)** +- 优点:数据与算力都在用户自己机器上,**服务器成本大降**;离线可用;能用到本机文件与本地软件;不引入跨租户风险(每位用户只碰自己的机器)。 +- 缺点:`soft` 模式隔离强度**低于**现在的 `account` 模式(本机场景可接受,但需明确边界);Windows / macOS 运行时**未验证**;平台对实例的可控性下降(升级、清理、取证都要客户端配合)。 + +**C 档 · 客户端作为集群 Worker(平台可把实例调度到用户机器)** +- 优点:算力可横向扩张且复用**已跑通的集群协议**(agent 四纪律 + 归属/租约分层已就位);对平台运营方收益最直接。 +- 缺点:**信任模型反转**(别人的代码、别人的数据、平台凭据落到用户掌控的机器上);必须有节点准入 + 吊销 + 强身份;**合规与责任边界要重新界定**;Windows / macOS 的隔离层基本**要从零做**(无 bwrap / 无 systemd / 无 uid 隔离)。 + +**我的倾向:先做 B**(唯一一档能"增量落地 + 不引入跨租户风险",且正好吃满资产 1/3/4 的现成能力)。A 档价值有限(覆盖网络用不上);C 档应等服务端能力与合规边界都清楚后再谈。 + +--- + +## 四、若走 B 档:落地顺序(每步可单独回滚) + +1. **验证 dsh 在 Windows / macOS 的可运行性**(只读 + 本地装,不动服务器)——产出:能否起实例 + 实例内 bash 工具是否可用(L2/L4)。 +2. **客户端节点代理**(复用 agent 协议,落 `soft` 模式):先只做 `/healthz` + `/launch` + `/stop` + `/fence`,台账式幂等。 +3. **通道**:先用现有**拨出式 SSH 反向隧道**打通(零新依赖,当天可验),再评估换"打洞优先 + 中继兜底"。 +4. **身份**:每节点独立凭据 + 吊销(替换共享 bearer)。 +5. **强约束落码**:实例所属 == 客户端主人;共享密钥不下发客户端(**红线级**,须有断言/测试钉住)。 +6. 分发与自动升级。 + +**回滚**:全程只新增(新客户端形态 + 新 Spawner 实现),**服务端现有路径不动** ⇒ 删客户端即回到现状。 + +--- + +## 五、未验证 / 待确认(诚实清单,勿当已知) + +| # | 项 | 状态 | +|---|---|---| +| 1 | `dsh` 在 Windows / macOS 起实例 + 实例内 bash 是否可用 | ⚠️ **未验证**(本轮无对应环境) | +| 2 | `soft` 模式下实例的实际隔离强度(能读到宿主什么) | ⚠️ **未验证**(本轮只读了代码分支,未实测) | +| 3 | 客户端形态下"共享密钥不下发"是否已有现成开关 | ⚠️ **待查**(档案 85/87 是两层密钥,需确认能否按形态裁剪) | +| 4 | 打洞优先方案与现有隧道的替换代价 | 📋 方案调研(见同日讨论结论:自托管 NetBird / headscale + 自建中继) | +| 5 | 客户端 × 平台版本兼容矩阵的判据 | 📋 待设计(可仿 `plugin-compat`) | + +--- + +## 附:本轮取证命令(可复跑) + +```bash +cd /d/github/dsh_shenxian +sed -n '660,665p' src/supervisor/orchestrator.ts # soft 模式 = 裸 spawn +grep -n "isolationMode" src/config.ts # 'soft'|'account',默认 soft +sed -n '1,30p' src/worker/agent.ts # 节点四条协议纪律 +sed -n '147,155p' src/worker/tunnel.ts # -R 反向转发(拨出式) +grep -rn "process.platform" src # 全仓仅 1 处(firewall.ts) +``` + +--- + +## 六、与另两份客户端文档对账(2026-09-16 08:5x 追加) + +> 对账对象(同为大工作区根,**均晚于本稿 8 小时**,08:06 产出): +> `dsh客户端化部署方案_20260916.md`(v3 · 单机自用 · 自称「客户端化」的单一来源) +> `dsh桌面客户端_开发方案_20260916.md`(v1 · 基于官方 Electron 壳 · 独立仓库) + +### 6.1 结论:**不冲突,是互补;但两处需要收口** + +| 维度 | 本稿 | 部署方案 v3 | 桌面客户端 v1 | 判定 | +|---|---|---|---|---| +| 形态选择 | 三档 A/B/C,倾向 **B** | **单机自用**(用户原话已定,§12) | 单机自用为默认,域名可切多人 | ✅ **同向**(本稿的 B 即其单机自用;三档问题已被用户拍板,见 6.2) | +| 地基 | 资产 1:`soft` 默认、无需 root | 明确"隔离档保持默认 soft" | 同 | ✅ 互相印证 | +| 平台改动面 | 资产 6:仅 firewall 一处平台分支 | "唯一硬阻塞 = spawn 方式" | P1 同一条 | ✅ 不同维度,可并存 | +| 分发与版本 | 缺口 4 | — | §3.4 上游同步 / §4.6 自动更新 / §6 打包 | ✅ 已被其覆盖 | + +### 6.2 本稿需修正的两点(**如实记录,勿当原判**) + +1. **缺口 1 的位置标错了**:本稿把"客户端运行时"列为缺口、并怀疑 `dsh` 在 Windows 的**沙箱后端**不可用。部署方案 v3 **已在本机 Windows 实测**:真正的硬阻塞是**平台自己的启动方式** —— 裸名 `spawn('npm')` 在 Windows 报 `ENOENT`(全局包是 `.cmd`),显式 `.cmd` 被 Node 拒(`EINVAL`),改用 `cmd.exe /c` 或 `shell: true` 即通。⇒ **阻塞点在平台调用层,不在 dsh 运行时**,且**代价很小**(一处调用方式)。 +2. **三档"需用户拍板"已不再是开放问题**:用户此前已定「考虑用户自己使用就可以了,不用考虑当作服务器 其他人访问」⇒ **A/C 两档的多人维度已被放弃**。本稿第五节的三档保留为**历史决策依据**,不再是待拍板项。 + +### 6.3 仅本稿覆盖、另两份未涉的:**覆盖网络**(用户最初问题里的那一项) + +- 两份文档的"多人形态"路线 = **内网 DNS 泛解析 + 域名**(局域网内多机访问),与"覆盖网络"是**同一需求的两种替代实现**: + - 局域网 + 域名:只能在同一内网;跨公网不行;需要域名与 DNS 泛解析。 + - 覆盖网络:跨公网可直连(打洞优先、中继兜底);不需要域名;但需要客户端常驻 + 节点身份。 +- ⇒ **本稿与另两份文档在"能力面"上不冲突,但在"要不要跨公网互连"上是分叉**;两份文档默认不跨公网。若确定不做跨公网,本稿的缺口 2/3 可整体降级为"不适用"。 +- 📄 **百台规模的逻辑预演见 `覆盖网络_百台规模推演_20260916.md`**(2026-09-16):结论 = 100 台规模下**控制面不是瓶颈,中继带宽与"大流量过网"才是**(实例首屏含 ≈10.8 MB 客户端脚本);而"单机自用"天然把大流量留在回环上 ⇒ 该形态在 100 台规模下是**正确版而非妥协版**。 + +### 6.4 两处需收口的隐患(**建议进文档库时一并处理**) + +1. **双源声明**:部署方案 v3 自称「'客户端化'的**单一来源**」,而桌面客户端 v1 与其**同日并存**且内容不同层(平台侧 vs 交付载体层)⇒ 属项目明令禁止的"第二个漂移源"风险。建议:**v3 定平台侧、v1 定交付层,v3 里补一行指针指向 v1**,或合并。 +2. **判定句互相矛盾**:v3 §12 附录 C 把「官方桌面版(Electron)作为载体」列为**放弃项**(理由:换载体会丢掉门户能力),而 v1 **恰恰选了这条路**。v1 的"保留壳、换内核为我们的平台"已实际**消解**该理由(门户能力并未丢),但 **v3 的判定句未更新** ⇒ 并列阅读时会读成"同一件事既放弃又采纳"。建议在 v3 §12 该行加注"已被 v1 以'换内核'方式规避,判定失效"。 + +### 6.5 本稿的**缺口 3 仍然有效,且是"切多人形态时的前置门禁"** + +- 部署方案 v3 §1.3 明确写:切多人形态**零代码**(只配域名),且**多人时隔离档仍是 `soft` ⇒ 用户之间无隔离**;桌面客户端 v1 §4.7 进一步要求"**客户端 spawn 平台时不要清理环境变量、不要白名单化**"(为透传域名)。 +- 这两条与本稿缺口 3 的硬约束**正面相交**: + - ① **实例只能属于机器主人** —— 单机自用下天然成立;一旦配域名多人用,**立刻不成立**(soft 档无隔离)。 + - ② **平台级共享模型密钥不得随客户端分发** —— 与"环境变量原样继承"相冲。**建议改为白名单透传**,只放形态开关三项(`DSHS_BASE_DOMAIN` / `DSHS_COOKIE_DOMAIN` / `DSHS_SECURE_COOKIES`),模型密钥只走"用户自己的密钥"那一层。 +- ⇒ 结论:**不是"不兼容",而是"范围收窄把风险面暂时关掉了、但开关就在配置里"**。建议把上述两条写成**切多人形态的前置检查项**(而非留在散文里)。 diff --git a/dsh-server-docs/04-调整方案/104-覆盖网络-全球架构复盘.md b/dsh-server-docs/04-调整方案/104-覆盖网络-全球架构复盘.md new file mode 100644 index 0000000..b54b267 --- /dev/null +++ b/dsh-server-docs/04-调整方案/104-覆盖网络-全球架构复盘.md @@ -0,0 +1,266 @@ +# 104 · 覆盖网络 · 全球架构复盘 +- 日期:2026-09-16 | 状态:📋 **规划态 / 未实施**(架构复盘稿;未接入任何机器、零代码改动) +- 来源:工作区根 `覆盖网络_全球架构复盘_20260916.md`(正文见 附录 A) +- 层级:**决策层 · 架构总纲**(五层架构 + 风暴类型学 + 流量组织)| 承接:档案 103 · 106;被 107 · 108–112 引用 +- 触发(用户原话):要**覆盖全球、用户之间互联互通**的完整架构;**重点:避免网络流量风暴 + 有效组织流量上传与接收** + +> **TL;DR** +> ✅ **有完整可循的工程路径** —— Tailscale / ZeroTier / Nebula / libp2p / BitTorrent 已反复验证过,**关键是照抄它们踩过的坑,而不是自己发明**。 +> 五层架构(控制面 / 会合 / 骨干·中继 / 数据面 / 观测)+ **10 类风暴类型学** + **流量组织五原则** + 7 步落地顺序。 +> 🔑 三句结论:**控制面与数据面必须彻底分离**;**失败不要变成重试**(退避 + 抖动 + 判死);**放大点必须前置治理**。 + +## 一、目标 + +给出「全球覆盖 + 用户间互联」的完整架构与**防风暴**的组织方式。可判定「做完了没有」= 五层职责明确、10 类风暴各有处置、流量预算表可算、落地顺序可排。 + +## 二、只读前置 + +| # | 事实 | 核对方式(期望输出) | +|---|---|---| +| 1 | 现有中继 = **绑在 Manager 上的 SSH 反向隧道(单中心)** ⇒ 必须先拆组件 | 读 `src/worker/tunnel.ts`(`ssh -O forward -R`)+ 集群化方案 §1.3 | +| 2 | 节点身份现为**共享密钥**(不满足「一机一身份 + 可吊销」) | 读 `src/worker/agent.ts` 头部自陈 | +| 3 | 现有心跳 **20 s** 正好落在 NAT 老化安全区间内 | 读 `src/worker/tunnel.ts` 自愈定时器 | +| 4 | 客户端首屏 bundle **≈10.8 MB**(实测 `11,363,655 B`)⇒ 冷启动风暴的量级来源 | 抓壳页 `/plugins/` 产物计字节(档案 97 同源) | +| 5 | 归属 / 租约 / 骨干资格**只能单点控制面写** | 集群化设计 §1.3(权威状态单点) | + +## 三、范围 + +- **改什么**:⏳ 尚未开跑。方案面 = 拆会合/中继为独立组件 · 换传输 · 换身份 · 补 443/TCP 兜底 · 上参数表 · 内容寻址 + 分级缓存 · 骨干层 + 观测。 +- **不动什么**:⛔ 官方 dsh 主程序(R2)|⛔ 单点控制面语义(归属/租约/资格签发**必须单点**,不得下放)|⛔ 本轮不动服务器。 +- 🟢 **范围声明(2026-09-16 用户定)**:**本方案只考虑技术实现;跨境数据合规由使用者自行考虑。** + ① 技术选型**不为合规让路**(多区域就近部署是**性能**最优的结果,不是合规动作); + ② 跨境**不设限**(不做地域封禁、不做数据落地/留存约束); + ③ **后续读者 ⛔ 不要再把合规 / 数据主权 / 备案当作本方案的前置条件、约束或上抛项**。 + +## 四、决策点 + +**已定** + +1. **只做技术实现,合规由使用者自负**(用户原话,见 §三 范围声明)⇒ ⛔ 不得再上抛合规项。 +2. **控制面 / 数据面彻底分离**(业内实测支撑:控制面挂掉时节点用内存 netmap 继续跑,已有连接不断)。 +3. **骨干/中继是限额资源**(预约 + TTL + 配额),不可无限使用。 +4. **可见性默认最小**(接入 ≠ 可见)。 + +**待拍板(唯一一项,真取舍)**:**骨干节点的服务范围** —— A 只服务自己名下设备(优点:无资源/计费纠纷、权限面不变;缺点:骨干少、冗余低)| B 服务全网(优点:骨干多、可用性高、中继容量易满足;缺点:他人流量跑在你的机器上、元数据暴露、被攻破影响面大)。**倾向 A→B 渐进**。详见档案 105 §七。 + +## 五、步骤(§八 落地顺序,每步自带一次验证) + +1. **拆出会合 / 中继为独立组件**(脱离 Manager)→ 验证:Manager 重启不影响已有数据面连接。 +2. 换传输:SSH 隧道 → **单进程多对端**隧道 → 验证:常驻内存下降 1–2 个数量级。 +3. 身份:**一机一钥 + 吊销 + 自报网络画像** → 验证:吊销单台生效、其余不受影响。 +4. 补 **443/TCP 兜底**通道 → 验证:封 UDP 环境(企业网/校园网)下仍能接入。 +5. 上**限流与退避参数表**(§5.2)+ 连接水位/宽限期/扇出上限 → 验证:压测下无重试风暴。 +6. **内容寻址 + 分级缓存** → 验证:版本发布时回源字节数 ≈ 1 份 × 组数。 +7. 骨干层(多中心 + 选择性加入,见档案 105)+ **观测与容量告警**。 + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 12 条必须内建特性 | 逐条可对照(本档 §2 已列);实施后逐条给证据 | +| B | 10 类风暴 | 每类有「成因 → 触发 → 处置」,且处置落到参数与上限 | +| C | 流量预算表 | 每类流量有「频率 / 单次 / 放大后 / 上限手段」四列,可算 | +| D | 直连成功率 | 作为一等指标被采集(业内口径 >90–94%,本环境未实测) | +| E | 未验证项透明 | §九 六条已列全(网络类型占比、打洞成功率、自有中继收益、中继出口带宽、控制面规格、~~合规~~已出范围) | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- **执行期**:按 §五 顺序,**每步可单独回滚**(拆组件 / 换传输 / 换身份 / 补兜底各自独立);⛔ 但**归属/租约单点语义不得回滚**(那是红线,不是开关)。 + +## 八、回报格式 + +执行会话回填:① 每步验证命令 + 实际输出 ② 参数表落地值(并与 §5.2 逐项对照)③ 红线遵守声明(R2 / 单点控制面 / 接入≠可见)④ commit ⑤ 未完成项与卡点 ⑥ 若实测推翻推演数字,给出实测口径。 + +## 九、未验证项(勿当结论) + +各网络类型实际占比(推演设定)|本环境实测打洞成功率(未实测)|自有中继的性能收益(业内 −150 ms / 12.5×,**本环境未复现**)|中继出口带宽与链路质量(未实测,跨云 22 KB/s 只能作下界)|控制面机规格(1.8 GB / 2 核,**待复核**)|~~跨境传输合规口径~~ ⏹ **已出范围**。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `覆盖网络_全球架构复盘_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | 性质:**架构复盘稿**(调研 + 推演,未接入任何机器) +> 承接:`覆盖网络_百台规模推演_20260916.md`(v2)· `覆盖网络_骨干层方案_20260916.md` +> 用户要求:**覆盖全球、用户之间互联互通**的完整架构;**重点:避免网络流量风暴 + 有效组织流量上传与接收** + +--- + +## 0. 判定与目标 + +✅ **有完整可循的工程路径** —— 这套东西在 Tailscale / ZeroTier / Nebula / libp2p / BitTorrent 上已被反复验证,**关键是照抄它们踩过的坑,而不是自己发明**。 + +**目标形态**:任何用户在任何网络(服务器 / 家宽 / 共享 IP / 移动网 / 企业网 / VPN)里的设备,都能与自己的其他设备、以及授权的他人设备互通;**全球可接入**,且**网络在规模化时不产生风暴**。 + +> 🟢 **范围声明(2026-09-16 用户定)**:**本方案只考虑技术实现;跨境数据合规由使用者自行考虑。** +> 因此:① 技术选型**不为合规让路** —— 多区域就近部署是**性能**最优的结果,不是合规动作;② 跨境**不设限**(不做地域封禁、不做数据落地/留存约束);③ **后续读者 ⛔ 不要再把合规 / 数据主权 / 备案当作本方案的前置条件、约束或上抛项**。 + +--- + +## 1. 架构分层(五层) + +| 层 | 职责 | 关键要求 | +|---|---|---| +| **控制面** | 身份、授权、归属/租约、网络地图(netmap)分发 | **承载几乎零流量**;**挂了不影响已建立的数据面**(节点内存缓存状态) | +| **会合层** | 交换候选地址、协助打洞、签发骨干目录 | 多区域、多实例、可缓存 | +| **骨干 / 中继层** | 打洞失败时转发密文;可选做区域汇聚 | **限额资源**(预约制 + TTL + 配额),**不可无限使用** | +| **数据面** | 端到端加密的节点间直连/中继传输 | 直连优先;**空闲不建连**;扇出设上限 | +| **观测层** | 路径类型(直连/中继)、时延、重连次数、带宽 | 没有它,容量规划与排障只能靠猜 | + +**全球布局要点**:会合与中继按区域就近部署(业内做法:DERP 覆盖 **20+ 区域**,每区域多台冗余);跨洲回源要显式避免。 + +--- + +## 2. 必须内建的特性清单(12 条) + +1. **控制面 / 数据面彻底分离** —— 业内实测:控制面挂掉时,节点用内存里的网络地图**继续跑**,已有连接不断。 +2. **连接总是"先中继、再升级直连"** —— 先保证能连上,再后台升级到直连(Tailscale 的路径:**直连 → 自有中继 → 共享中继**)。 +3. **直连成功率要作为一等指标** —— 业内 >90–94%(UDP 打洞成功率约 94%),**自有节点做中继**时实测 **延迟降 ~150 ms、吞吐提升 12.5×**。 +4. **空闲不建连(懒建连)** —— WireGuard 对空闲 peer **不握手、不维护状态**:拓扑是"潜在可达",不是"常连"。 +5. **中继是稀缺资源,要准入** —— 限额中继协议(预约 + TTL + 单次最大时长/数据量)是标准做法。 +6. **失败要能"判死"** —— 判定"不可打洞的节点"直接降级中继,**不要反复重试**。 +7. **端到端加密 + 中继不解密** —— 中继只见元数据(谁连谁、量多大)。 +8. **一机一身份 + 可吊销**(现有共享密钥不满足)。 +9. **自报网络画像** —— 路径类型 / NAT 类型 / 是否 VPN / 上行带宽。 +10. **内容寻址 + 分级缓存** —— 同一份静态资源全网只取一次。 +11. **统一限流与退避参数表**(下一节的"预算表")。 +12. **可见性默认最小**(接入 ≠ 可见)。 + +--- + +## 3. 技术选型对照(照抄成熟做法) + +| 维度 | 成熟做法 | 出处 | +|---|---|---| +| 隧道 | WireGuard(内核态或用户态) | Tailscale / NetBird | +| 打洞 | STUN + 同时发包;**先经中继交换信息再升级直连** | Tailscale DERP / libp2p **DCUtR** | +| 中继 | 限量中继(预约 + TTL + 配额);自有节点可当专用中继 | libp2p **relay v2** / Tailscale **Peer Relays** | +| 兜底通道 | **HTTPS/443**(UDP 全被封时仍能通) | DERP over TLS 443 | +| 连接管理 | 低/高水位 + **宽限期** + 按连接价值衰减裁剪 | libp2p Connection Manager(100 / 400 / 1 min) | +| 拨号限流 | **每对端最多 4 个并发拨号**、总并发 100、超时 30 s | libp2p Dialer 默认值 | +| 资源上限 | 连接数 / 流数 / 每协议流数 / 内存上限 + 自动伸缩 | libp2p Resource Manager | +| 中继自荐节流 | 服务广告**延迟 15 min、TTL 30 min** | libp2p HOP relay advertise | +| 中继数量上限 | 每节点最多预约 **2** 个中继 | libp2p `autoRelay.maxListeners` | +| 上传调度 | **同时上传对象上限 4**、10 s 重评、**30 s 随机试新对端** | BitTorrent choking | +| 分发调度 | **稀有优先**(+ 新人先随机易得)、末段加速、哈希校验 + 封禁 | BitTorrent | + +--- + +## 4. ⚡ 流量风暴类型学(**重点一**) + +> 每一类都给出:成因 → 触发 → 处置。**风暴的本质是"放大"**:一个事件被 N 个节点同时响应,就被放大了 N 倍。 + +| # | 风暴 | 成因 | 典型触发 | 处置 | +|---|---|---|---|---| +| 1 | **冷启动拉取风暴**(flashcrowd) | 大量节点同时拉同一份大资源 | 新版本发布(100 台 × 10.8 MB = **1.08 GB**) | 内容寻址 + 分级缓存 + **错峰启动** + 令牌桶 + 拉取而非推送 | +| 2 | **重连风暴 / 惊群** | 控制面或中继抖动 ⇒ 全体同时重连 | 控制面重启、中继切换 | **指数退避 + 随机抖动**;数据面不依赖控制面存活 | +| 3 | **保活风暴(N²)** | 全互联逐对保活 | 节点数增长(100 台全互联 = 4,950 对) | **禁全互联**;懒建连;**按需激活**;保活预算表 | +| 4 | **重试 / 重传风暴** | 打洞反复失败仍重试 | 对称 NAT / CGNAT 节点 | **失败预算**(每对端并发拨号 ≤4)+ 退避 + **判定即降级中继** | +| 5 | **同步 / 对账风暴** | 全量状态对账 | 状态变更或周期任务 | 增量 + 摘要比对 + 周期错峰 + 限速 | +| 6 | **探测风暴** | 每节点探测全部对端 | 监控过密 | 抽样探测 + 只在有流量时探测 + 结果缓存 | +| 7 | **NAT 表溢出** | 同 NAT 后多台同时向同一目标打洞 | 同一办公室多台设备 | **每 NAT / 每子网打洞并发上限** + 分散端口 | +| 8 | **中继过载 → 抖动放大** | 中继打满 ⇒ 超时 ⇒ 重试 ⇒ 更堵 | 突发流量 | 中继侧**准入 + 背压**;**超时不要立刻重试**;预约制配额 | +| 9 | **广播 / 泛洪风暴** | L2 广播或 gossip 无上限扩散 | 错误的二层拓扑 / 无 fanout 限制 | 覆盖层坚持 **L3**;gossip **限制扇出**或改拉取式 | +| 10 | **元数据 / 目录风暴** | 所有节点同时拉目录与 ACL | 目录更新 | 签名目录 + **TTL 缓存** + 多镜像 + 不推送 | + +### 4.1 三条治风暴的总原则 + +1. **放大点前置** —— 任何"会被 N 个节点同时响应"的事件,都要在第一跳就被**限流 + 错峰 + 缓存**。 +2. **失败不要变成重试** —— 重试是风暴的最大推手;必须"退避 + 抖动 + 判死"。 +3. **数据面与控制面解耦** —— 控制面抖动不该引起数据面重连;否则一次发布 = 一次全局风暴。 + +--- + +## 5. 📊 流量的组织:上传与接收(**重点二**) + +### 5.1 五条原则 + +1. **拉优先于推**:所有"广播"改为带 TTL 的本地缓存轮询 —— 服务器主动推 N 份 = 天然的放大。 +2. **懒建连 + 按需激活**:连接由"有数据要发"驱动,不由"拓扑完整"驱动(WireGuard 对空闲 peer 零状态是这条的现成地基)。 +3. **限制扇出**:任何节点**同时上传/转发的对象数设硬上限**(BitTorrent 是 4),否则上行带宽被稀释。 +4. **直连优先、中继兜底且中继准入**:中继是稀缺资源,用预约 + TTL + 配额管住。 +5. **内容寻址 + 分级缓存**:同一份 bundle 全网只该被取一次(把 100×10.8 MB 压成 1 份 + 99 次命中)。 + +### 5.2 流量预算表(什么频率、多大、放大后多少、用什么管住) + +| 流量 | 频率 | 单次 | 100 台放大 | 上限手段 | +|---|---|---|---|---| +| 控制面心跳 | 20 s | ~100 B | **5 req/s**(可忽略) | 懒心跳(有变化才发)+ 合并上报 | +| 归属 / 状态同步 | 事件驱动 | 小 | 低 | 增量 + **单点写** | +| 打洞尝试 | 建连时 | 小 | 受并发约束 | **每对端 ≤4 并发** + 每 NAT 上限 | +| **客户端 bundle 首屏** | 版本变化时 | **10.8 MB** | **1.08 GB** | **内容寻址 + 边缘/本地缓存 + 局域网共享**;已加载走 **304** | +| 工作区文件传输 | 用户驱动 | 可变 | 不可预测 | 分片 + 断点续传 + 背压 + 后台限速 | +| 版本 / 目录分发 | 发布时 | 大 | 爆炸 | **分层拉取**(骨干 → 区域 → 边缘 → 节点),不推送 | + +### 5.3 借鉴 BitTorrent 的调度(可直接搬的四件事) + +| 机制 | 作用 | 对我们的用途 | +|---|---|---| +| **同时上传上限(4)** | 防止带宽稀释,逼出互惠 | 节点/中继的并发上传上限 | +| **随机试新对端(30 s)** | 跳出局部最优;让新人拿到第一份数据 | 新节点快速进入"可交换"状态 | +| **稀有优先** | 让资源分布**均匀化** ⇒ 最大化并发可交换性 | 大文件/多副本资源的分片调度 | +| **校验 + 封禁** | 防恶意节点反复喂坏数据浪费带宽 | 客户端版本包与资源包的完整性 | + +⚠️ 一条已实测的坑(学术结论):**单纯按速率互惠对低带宽节点不公平**(高带宽节点上传量可达下载量的 7 倍);改为**配对块级记账**(`已上传 ≤ 已下载 + Δ`)能显著改善公平性且不损失利用率。 + +### 5.4 针对我们那份 10.8 MB 首屏的专项处置 + +1. **内容寻址 + 不可变缓存**:版本号即内容指纹 ⇒ 可以永久缓存、跨节点复用。 +2. **分级缓存**:区域边缘缓存一份,局域网内**互相共享**(办公室/家庭多台设备只回源一次)。 +3. **已加载走 304**(平台已有此能力)。 +4. **错峰 + 令牌桶**:版本发布时不要 100 台同时拉。 +5. ⇒ 把"跨机冷加载 10.8 MB"从**常态**降成**例外**。 + +--- + +## 6. 全球规模的额外约束 + +| 约束 | 影响 | 处置 | +|---|---|---| +| **RTT 与带宽时延积** | 跨洲 RTT 200 ms,单条 TCP 吞吐受窗口限制 | 调大窗口 / 用 QUIC 多流;避免跨洲回源 | +| **区域就近** | 跨区域中继 = 白付延迟与带宽 | GeoDNS / anycast 落地会合与中继 | +| ~~数据主权与合规~~ | **不在本方案范围**(见 §0 范围声明) | 由使用者自行考虑 —— 技术上不做地域封禁、不做数据落地约束 | +| **时钟** | 签名 / 证书校验依赖时间 | 强制时间同步 + 容忍窗口 | +| **观测** | 全球分布后本地排障失效 | 集中指标 + 每节点自报画像 | + +--- + +## 7. 与现平台的结合点 + +| 项 | 判定 | +|---|---| +| 归属 / 租约 / 资格签发 | ⛔ **必须单点控制面**(现架构已如此,继续沿用) | +| 会合 / 中继多实例 | ✅ 属数据面,**架构本来就允许** | +| 客户端形态 | ✅ 单机自用 + 覆盖网络互联**不矛盾**(租户维度收窄 ≠ 网络维度收窄) | +| 现有中继 | ⚠️ 现在是**绑在 Manager 上的 SSH 反向隧道(单中心)** ⇒ **必须先拆成可独立部署组件** | +| 现有 20 s 心跳 | ✅ 正好落在 NAT 老化的安全区间内 | +| 共享密钥 | ❌ 必须换成一机一钥 + 可吊销 | +| 11 MB bundle + ETag/304 | ✅ 已有基础,需补**内容寻址与分级缓存** | + +--- + +## 8. 落地顺序 + +1. 拆出**会合 / 中继**为独立组件(脱离 Manager)。 +2. 换传输:SSH 隧道 → **单进程多对端**隧道(内存差 1–2 个数量级)。 +3. 身份:一机一钥 + 吊销 + 自报网络画像。 +4. 补 **443/TCP 兜底**通道(治封 UDP 的企业网/校园网)。 +5. 上**限流与退避参数表**(§5.2)+ 连接水位/宽限期/扇出上限。 +6. 内容寻址 + 分级缓存(治 10.8 MB 首屏)。 +7. 骨干层(多中心 + 选择性加入,见骨干层方案);观测与容量告警。 + +--- + +## 9. 未验证项(勿当结论) + +| # | 项 | 状态 | +|---|---|---| +| 1 | 各网络类型实际占比 | ⚠️ 推演设定(决定中继容量) | +| 2 | 本环境实测打洞成功率 | ⚠️ 未实测(业内 90–94% 只能作参考) | +| 3 | 自有中继的性能收益(延迟/吞吐) | 📋 业内实测 −150 ms / 12.5×,**本环境未复现** | +| 4 | 中继出口带宽与链路质量 | ⚠️ 未实测(跨云 22 KB/s 只能作下界) | +| 5 | 控制面机规格 | ⚠️ 旧记录 1.8 GB / 2 核,**待复核** | +| 6 | ~~跨境传输合规口径~~ | ⏹ **已出范围**(2026-09-16 用户:「方案只考虑技术实现,跨境数据合规是谁用谁自己考虑」)—— **不再作为方案约束或上抛项** | diff --git a/dsh-server-docs/04-调整方案/105-覆盖网络-骨干层方案.md b/dsh-server-docs/04-调整方案/105-覆盖网络-骨干层方案.md new file mode 100644 index 0000000..6f04b85 --- /dev/null +++ b/dsh-server-docs/04-调整方案/105-覆盖网络-骨干层方案.md @@ -0,0 +1,253 @@ +# 105 · 覆盖网络 · 骨干层方案 +- 日期:2026-09-16 | 状态:📋 **规划态 / 未实施**(设计稿;未接入任何机器) +- 来源:工作区根 `覆盖网络_骨干层方案_20260916.md`(正文见 附录 A) +- 层级:专项设计(承接档案 **106** §7 P0-1 的展开)|关联:档案 104 §7 落地顺序第 7 步 +- 触发(用户原话):**有公网 IP 的节点是否可以设置专门的网络服务,让其他有公网 IP 的节点加入形成专门的覆盖网络,其他用户节点可以选择性加入** + +> **TL;DR** +> ✅ **可以,而且是成熟系统里的标准模式** —— 业内叫「**超级节点 / 骨干层(supernode / backbone)**」(ZeroTier Moon · Nebula Lighthouse · Tailscale DERP · libp2p AutoRelay · 早期 Skype supernode)。 +> 它解决的正是推演里最贵的那条:**中继容量要按 45–55% 的 L3 占比预留**,靠一台中心服务器扛不住 —— 而网络里本来就躺着现成的公网出口。 +> 🔑 三条硬约束:**接入 / 成员 / 可见三分离**;**骨干资格只能控制面签发**;**骨干不得被默认征用**。 + +## 一、目标 + +把「有公网 IP 的节点组成骨干层、其他节点选择性加入」设计成可落地方案。可判定「做完了没有」= 形态(多中心)· 成员上限 · 三条硬约束 · 容量数字 · 兼容性判定 · 落地 5 步 齐备。 + +## 二、只读前置 + +| # | 事实 | 核对方式(期望输出) | +|---|---|---| +| 1 | 骨干 = **一种新的 host 类型**,与 T08 host/lease 模型兼容(属新增能力标签) | 读 `src/db/`(lease)与集群化设计 §1.3 | +| 2 | 会合 / 中继**属数据面,架构本来允许多实例**;**归属/租约/资格必须单点控制面** | 集群化设计 §1.3 | +| 3 | 现有中继实现 = **挂在 Manager 上的 SSH 反向隧道(单中心)** ⇒ 落地第一步就是拆组件 | `sed -n '147,155p' src/worker/tunnel.ts` | +| 4 | 打包与分发可复用桌面客户端独立仓库的打包/更新链 | 见 `dsh桌面客户端_开发方案_20260916.md` §3.4/§6 | +| 5 | 骨干全靠**用户态 UDP/TCP**,**不需要特权** | 本档 §1 表「骨干承担」行 | + +## 三、范围 + +- **改什么**:⏳ 未开跑。方案面 = ① 拆会合/中继为独立可部署组件 ② 控制面签发骨干资格 + 下发**签名目录** ③ 骨干互认心跳(≤10 成员全互联)④ 接入选路(主/备,秒级迁移)⑤ 接入与可见解耦 ⑥ 可选「贡献带宽给全网」开关。 +- **不动什么**:⛔ 权威状态(归属 / 租约 / 资格)**不得由骨干自行批准**|⛔ 本轮不动服务器、不改代码。 +- **红线约束**:R5(骨干若默认替全网转发 = **扩大权限面 + 占用他人资源**,命中 R5 与边界外 ⇒ 必须显式开关)。 + +## 四、决策点 + +**已定** + +1. **形态 = 多中心骨干**(取代单中心星型):骨干成员上限 **≤10–20**(10 个 = 45 条;20 个 = 190 条;50 个 = 1,225 条)。 +2. **普通节点每台只连 1–2 个骨干**(主用 + 备用)⇒ 100 台 = 100–200 条常连,完全可控。 +3. **资格只能由控制面签发**(不得由骨干节点自行批准,否则出现第二个权威源、骨干沦为公网跳板)。 + +**待拍板(唯一一项,真取舍 —— 与档案 104 §四 同一项)** + +**骨干节点的服务范围**: + +- **A · 只服务自己名下的设备(自用骨干)** + 优点:无合规与计费问题;不占用他人资源;**权限面不变(不命中 R5)**;实现最简单,节点只认自己的主人。 + 缺点:骨干数量受限于「有几个用户有公网 IP 的机器」;跨用户无法互相兜底,冗余度低。 +- **B · 服务全网(共享骨干)** + 优点:骨干多、冗余好、可用性高;单个骨干挂了影响小;对 L3 那 40–55 台的中继容量最容易满足。 + 缺点:**他人的流量跑在你的机器上**(资源与计费要立规矩);骨干会看到流量元数据(谁连谁、流量大小);节点被攻破的影响面变大。 + +**倾向 A→B 渐进**:先把骨干做成「自用骨干」跑通(零合规风险、可立刻验证),把「是否贡献带宽给全网」做成**显式开关**,等 A 稳了再逐个放开。 + +## 五、步骤(§8 落地顺序;每步自带一次验证) + +1. **把会合 / 中继从 Manager 里拆出来**,做成可独立部署的组件 → 验证:Manager 重启不影响骨干侧已有转发。 +2. **控制面签发骨干资格 + 下发签名目录**(骨干之间只校验,不自行批准)→ 验证:未签发的公网 IP 无法成为骨干。 +3. **骨干互认与心跳**(≤10 个成员,全互联)→ 验证:45 条常连心跳 ≈ 2.3 req/s(可忽略)。 +4. **接入选路**(节点就近选主/备骨干,支持秒级迁移)→ 验证:掐掉主骨干,节点秒级迁到备用。 +5. **接入与可见解耦**(默认只见自己名下设备)→ 验证:借骨干转发时**不暴露对端清单**。 +6. 可选:开放「贡献带宽给全网」开关(= §四 的 B 档)。 + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 骨干规模与常连数 | 10 个骨干 ⇒ 骨干内 **45** 条常连;每骨干接入 10–20 个节点 | +| B | 中继容量摊开 | 稳态 20–27 Mbps 摊到**多个**骨干,而非一台 | +| C | 单点故障收敛 | 骨干挂 1 个 ⇒ 受影响 = 接入它的 10–20 台,**秒级迁到备用**(不是全网掉线) | +| D | 目录可用性 | 骨干目录不可达时**用本地缓存的签名目录**继续选路(目录不能是单点) | +| E | 故障影响面 | 骨干被攻破 ⇒ 影响面 = 接入它的那批节点(**不是全网**) | +| F | 未验证项透明 | §九 四条已列全(网络类型占比、家宽上行是否够、全互联收敛开销、SSH 隧道改造工作量) | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- **执行期**:5 步各自独立可回滚 —— 拆组件(回退到 Manager 内置隧道)|签发资格(停发即回到无骨干态)|互认心跳(关服务)|选路(回落到单骨干)|解耦(关开关)。 +- ⛔ **不可回滚项**:控制面签发资格这一条是**红线**(一旦下放给骨干自行批准即产生第二权威源)—— 不是开关。 + +## 八、回报格式 + +执行会话回填:① 每步验证命令 + 实际输出 ② 骨干清单与上限实际取值 ③ 服务范围决策落地形态(A / A→B / B) ④ 红线遵守声明(R5 未默认征用他人带宽 / 资格由控制面签发) ⑤ commit ⑥ 未完成项与卡点。 + +## 九、未验证项(勿当结论) + +各网络类型实际占比(决定骨干数量需求,**推演设定**)|骨干节点上行带宽是否够(**家宽上行常远小于下行,未实测**)|骨干全互联在 ≤10 成员时的实际收敛开销(量级推算 2.3 req/s)|现有 SSH 隧道改造为独立组件的具体工作量(**待评估,未读该模块全量代码**)。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `覆盖网络_骨干层方案_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | 性质:**设计稿**(承接 `覆盖网络_百台规模推演_20260916.md` **P0-1** 的展开) +> 用户提出:**有公网 IP 的节点是否可以设置专门的网络服务,让其他有公网 IP 的节点加入形成专门的覆盖网络,其他用户节点可以选择性加入** +> 🟢 **范围**:**只考虑技术实现,跨境数据合规由使用者自行考虑**(同 `覆盖网络_全球架构复盘_20260916.md` §0 范围声明) + +--- + +## 0. 判定 + +✅ **可以,而且这是成熟系统里的标准模式** —— 业内叫「**超级节点 / 骨干层(supernode / backbone)**」,不是新造东西。 + +| 先例 | 骨干层是什么 | +|---|---| +| ZeroTier | Planet(官方根)+ **Moon(自建公网节点)** | +| Nebula | **Lighthouse**(有公网 IP 的会合点,可多台冗余) | +| Tailscale | **DERP 中继** + exit node / subnet router("提供服务的节点") | +| libp2p | **relay v2 + AutoRelay**(有公网 IP 的节点自动成为中继候选) | +| 早期 Skype | **supernode**(有公网 IP 的节点自动升格) | +| EasyTier / 自建方案 | 指定"公网节点"作为中继与路由 | + +**它解决的正是推演 v2 里最贵的那条**:中继容量要按 45%–55% 的 L3 占比预留 —— 靠一台中心服务器扛不住,而网络里本来就躺着现成的公网出口。 + +--- + +## 1. 形态:**多中心骨干**(取代单中心星型) + +``` + ┌──────── 骨干层(有公网 IP,互相可直接连)────────┐ + │ S1 ── S2 ── S3 ── … ── Sn (全互联或有界互联) │ + └───┬──────┬──────┬───────────────┬───────────────┘ + │ │ │ │ ← 选择性加入 + ┌─────┴─┐ ┌──┴───┐ ┌┴────┐ ┌────┴───┐ + │家宽节点│ │移动网 │ │企业网│ │ VPN 节点│ ← L2/L3 层节点 + └───────┘ └──────┘ └─────┘ └────────┘ +``` + +| 项 | 取值 | 理由 | +|---|---|---| +| 骨干成员 | **有公网 IP 的节点**(服务器 / 专属 IP) | 互相可直接连,无需打洞 | +| 骨干互联 | **全互联,但成员数设上限** | 10 个 = 45 条;20 个 = 190 条;50 个 = 1,225 条 ⇒ **建议 ≤10–20** | +| 普通节点接入 | 每台只连 **1–2 个骨干**(主用 + 备用) | 100 台 ⇒ 100–200 条常连,完全可控 | +| 骨干承担 | 会合(rendezvous)· 中继(relay)· 可选 STUN-like 探测 | 都是用户态 UDP/TCP,**不需要特权** | + +--- + +## 2. 一个骨干节点要跑什么(可以打成一个独立组件) + +| 服务 | 作用 | 流量特征 | +|---|---|---| +| **会合** | 把两个节点的候选地址互相告诉对方 | 极小 | +| **中继** | 打洞失败时转发密文 | **大**(按 L3 占比算) | +| **NAT 探测** | 帮节点判断自己的映射类型 | 极小 | +| **目录镜像**(可选) | 分发"有哪些骨干可用"的**签名目录** | 小 | + +⇒ 这四样打包成一个「节点服务」,**正好可以放进桌面客户端那个独立仓库**(复用打包与更新链),不需要碰平台主进程。 + +--- + +## 3. 三条必须钉住的设计约束 + +### 3.1 「选择性加入」必须拆成三个独立概念(否则一定出事) + +| 层 | 含义 | 归属 | +|---|---|---| +| **接入**(connectivity) | 我能通过谁到达别人 | 节点自选(就近 / 按容量) | +| **成员**(membership) | 我在不在网里、谁批准 | **控制面签发 + 可吊销** | +| **可见**(visibility) | 我能看到/访问谁 | **ACL,默认最小** | + +⚠️ **最危险的默认**是"加入骨干 ⇒ 能看见骨干上所有人"。那会变成一张巨型扁平网,与项目"**权限只准收窄**"直接冲突。 +⇒ **接入与可见必须解耦**:可以借骨干做**转发通道**,而不暴露对端清单。 + +### 3.2 骨干资格:**只能由控制面签发**(不得由骨干节点自行批准) + +- 若骨干节点能自行批准新成员 ⇒ 出现**第二个权威源**(违反单一来源),且**任何人开个公网 IP 就能进骨干** ⇒ 骨干沦为公网跳板。 +- 正确形状:**控制面签发骨干成员资格(可吊销)+ 骨干之间只做"校验签名"**,不自行决策。 +- 与平台既有分层判据完全一致:**会合/中继可以多实例(数据面),权威状态必须单点**。 + +### 3.3 骨干节点**不能**被默认征用去转发别人的流量 + +- 骨干节点的带宽可能属于**贡献者本人**。若默认"为全网转发" ⇒ **扩大权限面 + 占用他人资源**(命中 R5 与边界外)。 +- ⇒ 必须显式:**服务范围**(只服务自己名下设备 / 服务全网)+ **带宽上限** + **随时退出**。 +- 这一条需要用户定,见 §7。 + +--- + +## 4. 容量与数字(沿用推演 v2 的分层口径) + +| 项 | 取值 | +|---|---| +| 100 台构成 | L1 有公网 IP **10** | L2 可打洞 **30** | **L3 只能中继 40–55** | +| 骨干规模 | 10 个 ⇒ 骨干内 **45** 条常连 | +| 每骨干接入 | **10–20** 个节点(100 / 10 上限) | +| 骨干心跳 | 45 条 × 1/20 s ≈ **2.3 req/s** ⇒ 可忽略 | +| 中继稳态 | 20–27 Mbps 总量,**摊到多个骨干**而非一台 | +| 骨干挂 1 个 | 受影响 = 接入它的那 10–20 台 ⇒ **秒级迁到备用骨干**(不是全网掉线) | + +⇒ 相对单中心,**多中心骨干把"中继带宽"与"单点故障"同时摊开了** —— 这是它最大的收益。 + +--- + +## 5. 故障与运维面 + +| 场景 | 期望行为 | +|---|---| +| 骨干 S2 挂 | 接入它的节点秒级迁到备用骨干;正在进行的连接会断一下 | +| 骨干目录不可达 | **用本地缓存的签名目录**继续选路(目录不能是单点) | +| 骨干被攻破 | 影响面 = 接入它的那批节点(**不是全网**)⇒ 优于单中心 | +| 骨干换 IP / 身份轮换 | 由控制面更新目录,节点热切换 | +| 节点从骨干 A 迁到 B | 新旧路径短暂并存,避免"先断后连"的可见中断 | + +--- + +## 6. 与现平台架构的兼容性(**这是能不能落地的前提**) + +| 项 | 判定 | +|---|---| +| 骨干 = 一种新的 **host 类型**(有公网 IP、可做中继) | ✅ 与 T08 的 host / lease 模型兼容,属**新增能力标签** | +| 会合 / 中继多实例 | ✅ 属数据面,**架构本来就允许多实例** | +| 归属 / 租约 / 骨干资格 | ⛔ **必须单点控制面** —— 客户端与骨干一律不得持有权威状态 | +| 现有中继实现 | ⚠️ 现在是**挂在 Manager 上的 SSH 反向隧道**(单中心)⇒ 落地第一步就是**把它拆成可独立部署的组件** | +| 打包与分发 | ✅ 复用桌面客户端独立仓库的打包/更新链 | + +--- + +## 7. 需用户拍板的一项(真取舍) + +**骨干节点的服务范围**:是只服务自己名下的设备,还是替全网(含其他用户)转发流量。 + +**A · 只服务自己名下的设备(自用骨干)** + +优点:无合规与计费问题;不占用他人资源;权限面不变(不命中 R5);实现最简单,节点只认自己的主人。 +缺点:骨干数量受限于"有几个用户有公网 IP 的机器";跨用户无法互相兜底,冗余度低。 + +**B · 服务全网(共享骨干)** + +优点:骨干多、冗余好、可用性高;单个骨干挂了影响小;对 L3 那 40–55 台的中继容量最容易满足。 +缺点:**他人的流量跑在你的机器上**(资源与计费要立规矩);骨干会看到流量元数据(谁连谁、流量大小);节点被攻破的影响面变大。 + +**我倾向 A→B 渐进**:先把骨干做成"自用骨干"跑通(零合规风险、可立刻验证),把"是否贡献带宽给全网"做成**显式开关**,等 A 稳了再逐个放开。 + +--- + +## 8. 落地顺序(每步可单独回滚) + +1. **把会合 / 中继从 Manager 里拆出来**,做成可独立部署的组件(当前是绑定在 Manager 上的 SSH 隧道)。 +2. **控制面签发骨干资格 + 下发签名目录**(骨干之间只校验,不自行批准)。 +3. **骨干互认与心跳**(≤10 个成员,全互联)。 +4. **接入选路**(节点就近选主/备骨干,支持秒级迁移)。 +5. **接入与可见解耦**(默认只见自己名下设备)。 +6. 可选:开放"贡献带宽给全网"开关(= §7 的 B 档)。 + +--- + +## 9. 未验证项 + +| # | 项 | 状态 | +|---|---|---| +| 1 | 各网络类型实际占比(决定骨干数量需求) | ⚠️ 推演设定 | +| 2 | 骨干节点的上行带宽是否够(家宽上行常远小于下行) | ⚠️ 未实测 | +| 3 | 骨干全互联在 ≤10 个成员时的实际收敛开销 | 📋 量级推算(2.3 req/s) | +| 4 | 现有 SSH 隧道改造为独立组件的具体工作量 | 📋 待评估(未读该模块全量代码) | diff --git a/dsh-server-docs/04-调整方案/106-覆盖网络-百台规模推演-v2.md b/dsh-server-docs/04-调整方案/106-覆盖网络-百台规模推演-v2.md new file mode 100644 index 0000000..29dc0eb --- /dev/null +++ b/dsh-server-docs/04-调整方案/106-覆盖网络-百台规模推演-v2.md @@ -0,0 +1,254 @@ +# 106 · 覆盖网络 · 百台规模推演-v2 +- 日期:2026-09-16 | 版本:**v2**(09:3x 按用户纠正重写前提与结论)| 状态:📋 **规划态**(**纯文字推演**,纸面演算,未接入任何机器) +- 来源:工作区根 `覆盖网络_百台规模推演_20260916.md`(正文见 附录 A) +- 层级:规模推演(第一版)| 承接档案 103 §六;上级 = 档案 104;被 105(P0-1 展开)· 107(扩到 1000 台)承接 + +> ⚠️ **本档含一次前提级纠错(v1 作废),务必先读 §0 修正声明** +> 用户纠正原话:**「单机用也要互联,这正是建立覆盖网络的目的」**,且 **100 台是各种网络情况,不是全都是单机**。 +> v1 错在**把「租户维度收窄」误当成「网络维度收窄」**(平台只有我一个用户 ≠ 我只有一台机器、不需要跨机)。 + +> **TL;DR(v2)** +> 租户维度只有一个人,**不影响**网络维度有 100 台设备要互通 ⇒ **覆盖网络正是为「同一个人/团队的多台设备散落在各种网络里」而存在**。 +> 异构网络最直接的后果:**中继占比远高于同构假设**(不是 15%,基准 **40–45%**、最坏 **55%**)⇒ 中继容量必须按最坏情况预留, +> 并**先把网络里现成的公网节点(L1)用起来当会合/中继**。拓扑不用换(仍是星型/分组星型),要换的是**三件**:传输、身份、**443/TCP 兜底**。 + +## 一、目标 + +对「**同一个人/团队名下 100 台异构设备**经覆盖网络互联」做纸面推演:节点画像 · 中继容量 · 拓扑 · 分场景判读 · 瓶颈排序 · P0/P1/P2 前置项。 +可判定「做完了没有」= 上述六项齐备,且**每条数值都标注是「推演设定」还是「实测锚点」**。 + +## 二、只读前置 + +| # | 事实(实测锚点,非推演) | 核对方式(期望输出) | +|---|---|---| +| 1 | 跨机访问实例 UI 首屏 **≈10.8 MB**(实测) | 抓壳页 `/plugins/` 合并脚本计字节(档案 97 同源,实测 `11,363,655 B`) | +| 2 | 跨云链路 **~22 KB/s**(下界参考) | 47↔106 实测记录(见档案 110 §三) | +| 3 | 心跳间隔 **20 s** | `src/worker/tunnel.ts` 自愈定时器 | +| 4 | 归属/租约**必须单点 Manager**;会合/中继**可多实例** | 集群化设计 §1.3 | +| 5 | 节点身份现为**共享密钥**(无法吊销单台)⇒ 一机一钥是硬前置 | `src/worker/agent.ts` 头部自陈 | + +## 三、范围 + +- **改什么**:⏳ 未开跑。本档只输出推演与 P0/P1/P2 前置清单,不含实施。 +- **不动什么**:⛔ 权威状态单点语义|⛔ 本轮不动服务器、不改代码。 +- **前提口径(用户纠正后)**:100 台 = **异构**(服务器 / 家宽 / 共享 IP·CGNAT / 移动网 / 企业校园网 / VPN 全隧道),**不是同构单机**。 + +## 四、决策点 + +**已定(v2 重写后的口径)** + +1. **单机自用 ≠ 不需要互联** —— **租户维度收窄 ≠ 网络维度收窄**(用户原话)。⛔ 不得再用「单机自用所以没流量要互联」当前提。 +2. **中继按 45% 设计 / 55% 留余量**(乐观 30% / 基准 40–45% / 悲观 55%)—— ⛔ 不得再用同构假设的 15%。 +3. **必须补 443/TCP 兜底通道**(否则封 UDP 的企业/校园网整类节点进不来)。 +4. **L1(有公网 IP)自动升格为中继候选池**。 +5. **拓扑仍是星型 / 分组星型 + 按需建连 + 懒保活**(⛔ 不建全互联:100 台全互联 4,950 条 vs 星型 100 条,差 49.5 倍)。 + +**未定 / 待复核**:控制面机规格(1.8 GB / 2 核 系 09-08 旧记录);各网络类型实际占比(推演设定,需按真实设备池校准)。 + +## 五、步骤(§7 前置项,按 P0/P1/P2) + +**P0(不做就走不通)** +1. 中继容量按 **45–55% L3 占比**设计 + **L1 自动升格** → 验证:中继容量不随玩家/设备数漂移。 +2. **443/TCP 兜底通道** → 验证:封 UDP 环境仍能接入。 +3. **一机一钥 + 可吊销 + 限流** → 验证:吊销单台生效。 +4. **SSH 反向隧道换成单进程多对端方案** → 验证:常驻内存下降 1–2 个数量级。 + +**P1(不做会出事)**:中继 ≥2 台且**与控制面分开部署** + 秒级切换|跨机大流量直连优先 + 10.8 MB 首屏就近/本地缓存|保活 ≤25 s;VPN/代理类**检测即降级中继**(不重试)|重连指数退避 + 抖动 + 控制面令牌桶。 + +**P2**:节点自报网络画像(路径类型 / NAT 类型 / 是否 VPN / 上行带宽)|客户端 × 平台版本兼容矩阵。 + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 分层数字 | L1 **10** / L2 **30** / **L3 需中继 40–55**;稳态中继 **20–27 Mbps** | +| B | 拓扑对比 | 全互联 4,950 条 vs 星型 100 条 ⇒ 明确**不建全互联** | +| C | 分场景判读 | S1–S9 逐条给出判读(含 **S4 定性从「危险」修正为「核心用例」**) | +| D | 瓶颈排序 | 7 条按「先炸顺序」排(中继带宽第一) | +| E | 未验证项透明 | §九 七条已列全 | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- ⚠️ **v1 的前提已被推翻**:本档**取代 v1**,⛔ 不得再引用 v1 §0 的结论("100 台没有流量要互联")。v1 全文保留在 附录 A 的 §0 修正声明中(作为错误样本)。 + +## 八、回报格式 + +执行会话回填:① 校准后的网络类型实际占比(与 §2 表对照)② 实测打洞成功率(分层)③ 中继出口带宽与 jitter 实测 ④ 控制面规格复核结果 ⑤ 若推翻本档任一数字,给出实测口径与取数时间。 + +## 九、未验证项(勿当结论) + +各网络类型**实际占比**(推演设定,需按真实设备池校准)|打洞成功率(分层:家宽 / CGNAT / 移动网 / 企业网,**未实测**)|**VPN 全隧道是否真的破坏打洞**(未实测,推演按"会破坏"保守处理)|企业网封 UDP 的比例(未实测)|中继出口带宽与链路质量(未实测,仅有跨云 22 KB/s 作下界)|控制面机规格(1.8 GB / 2 核,**待复核**)|单条 SSH 隧道常驻内存 3–5 MB(量级估计)。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `覆盖网络_百台规模推演_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | **版本:v2**(09:3x 按用户纠正重写前提与结论)| 性质:**纯文字推演**(纸面演算,未接入任何机器) +> 配套:`可行性评估_客户端安装与覆盖网络互联_20260916.md` §六|`dsh客户端化部署方案_20260916.md`|`dsh桌面客户端_开发方案_20260916.md` +> 📄 **本文的上一级(全球级复盘,含风暴类型学与流量组织)见 `覆盖网络_全球架构复盘_20260916.md`** + +--- + +## 0. 修正声明(v1 的第 0 节被判定为错误) + +> ⚠️ **用户纠正(2026-09-16 09:3x,原话要点)**:**「单机用也要互联,这正是建立覆盖网络的目的」**;且 **100 台是各种网络情况,不是全都是单机** —— 有服务器、有单机、有局域网、有互联网、有专属外网 IP、有共享外网 IP、有固定宽带、有移动网、有 VPN 等各种情况。 + +**v1 错在哪**:v1 断言"按单机自用形态,100 台之间根本没有流量要互联 ⇒ 覆盖网络无事可做"。 +**错因**:把 **租户维度的收窄**(平台只有我一个用户)误当成 **网络维度的收窄**(我只有一台机器、不需要跨机)。 + +| 维度 | 单机自用是否收窄 | 说明 | +|---|---|---| +| **租户维度**(有几个人用) | ✅ **收窄为 1** | 形态开关决定 | +| **网络维度**(要连几台机器) | ❌ **完全不收窄** | **同一个人也有多台设备**,分布在家里宽带 / 移动网 / 公司网 / 云主机上 —— **这正是覆盖网络存在的理由** | + +⇒ 修正后:**"单机自用"与"需要互联"不矛盾,而是同一条路线的两个正交面。** v2 据此重写。 + +--- + +## 1. 前提(v2) + +| 项 | 取值 | +|---|---| +| 角色 | **同一个人(或同一个团队)名下的 100 台设备**,经覆盖网络互相可见 | +| 目标流量 | ① 跨机访问彼此的实例/工作区 ② 跨机文件与数据交换 ③ 平台侧的控制与调度 | +| 中心 | 控制面(会合点)+ 中继 —— **数量与落点见 §3(不再假设只有 1 台)** | +| 节点构成 | **异构**,见 §2 | + +--- + +## 2. 节点构成:100 台的异构画像(**这是 v1 缺失的核心**) + +> 台数为推演设定(可按实际调),**关键结论对比例敏感、对绝对值不敏感**。 + +| 类 | 场景 | 台数 | 公网可达 | NAT 行为 | 打洞前景 | +|---|---|---|---|---|---| +| A | **云服务器**(专属公网 IP) | 10 | ✅ 可直接拨入 | 无 NAT | 不需要打洞 | +| B | **家庭固定宽带** | 30 | ❌ | 多为锥形/受限锥形 | ✅ 最好 | +| C | **共享公网 IP / CGNAT**(含运营商大内网) | 20 | ❌ | 多用户共享同一出口,端口映射冲突 | ⚠️ 差 | +| D | **移动网**(4G/5G) | 15 | ❌ | **对称 NAT + CGNAT 居多** | ❌ 基本失败;且切基站就换 IP | +| E | **企业 / 校园局域网** | 15 | ❌ | 对称 NAT,**常封 UDP**,可能强制 HTTP 代理 | ❌ 差 | +| F | **VPN 用户**(全隧道) | 10 | 取决于 VPN | VPN 把流量全隧道化 ⇒ 映射被破坏 | ❌ 差 | + +### 2.1 按可达性分三层(**决定谁是直连、谁是中继**) + +| 层 | 定义 | 台数 | 在方案里的角色 | +|---|---|---|---| +| **L1** | 可直接拨入(有公网 IP) | **10** | **天然的会合点 / 中继候选** | +| **L2** | 能打洞(锥形类) | **30** | 直连主体,流量不过中心 | +| **L3** | **只能走中继** | **40–55**(C/D/E/F 中打洞失败的部分) | **中继容量必须按这一层算** | + +> ⚠️ **v1 假设"15% 需中继",对异构网络严重偏低。** +> 保守口径:**按 45% 设计中继容量,按 55% 留余量。**(乐观 30% / 基准 40–45% / 悲观 55%) + +### 2.2 三类"特殊网络"的处置要求(缺一样就有整类节点进不来) + +| 情况 | 现象 | 处置 | +|---|---|---| +| **封 UDP**(企业网/校园网) | 打洞与 UDP 中继全失败 ⇒ 该类节点**完全看不见** | 必须提供 **443/TCP 兜底通道**(TLS 伪装),否则 E 类 15 台直接出局 | +| **全隧道 VPN** | 反复尝试打洞、每次失败、白白抖动 | **检测到即直接降级中继**,不要重试 | +| **移动网** | 切基站换 IP,直连秒断 | 保活更密(≤20 s)+ 重打洞要快,且**中继常驻为该类兜底** | + +--- + +## 3. 中继容量:按最坏情况排(v1 的数字作废) + +| 项 | v1(同构假设) | **v2(异构)** | +|---|---|---| +| 需中继的台数 | 15 | **40–55**(按 45 设计 / 55 留余量) | +| 稳态占用(按 0.5 Mbps/台) | 7.5 Mbps | **20–27 Mbps** | +| 跨机首屏突发(≈10.8 MB/台) | 165 MB | 同口径:**3 台同时冷加载 ≈ 32 MB;10 台 ≈ 108 MB** | + +**由此得出 v2 的第一条新设计点**: + +> 🔑 **让 L1 层(有公网 IP 的 10 台)自动升格为中继候选池。** +> 异构网络里本来就躺着现成的公网出口 —— 不利用它,就等于用一台小服务器去扛 40+ 台的流量。**同构假设下想不到这一条。** + +⚠️ 但有一条硬边界(与平台既有分层判据一致): +- **会合点 / 中继:可以多实例**(谁有公网 IP 谁就能当); +- **权威状态(归属 / 租约):必须单点 Manager** —— 客户端节点永远不得持有权威状态,否则就是脑裂。 + +--- + +## 4. 拓扑:仍然**不能建全互联**(这条 v1 正确,保留) + +全互联 = 100×99/2 = **4,950** 条;星型 = **100** 条 ⇒ 差 **49.5 倍**。 +⇒ **星型 / 分组星型 + 按需建连 + 懒保活**。跨机通信由中心或直连路径承担,不靠"每对都常连"。 + +--- + +## 5. 分场景推演 + +| # | 场景 | 判读 | +|---|---|---| +| S1 | 逐台加入(1→10→50→100) | 心跳 0.1→0.5→2.5→**5 req/s**;控制面无压力 | +| S2 | 稳态一小时 | 控制面 5 req/s;中继常驻 **20–27 Mbps**(45 台口径) | +| S3 | **家宽笔记本换网**(家→公司) | 秒级重打洞;失败切中继。保活 ≤25 s 才不会表现为"随机断网" | +| S4 | **跨机访问对方实例 UI**(真实需求,非假设) | 首屏 **≈10.8 MB**(实测值):**直连**(30 台上行 20–50 Mbps)≈ **2–4.5 s ✅**;**走中继**(100 Mbps)≈ 1 s/台但并发即叠加 ⇒ **必须直连优先** | +| S5 | **移动网节点切基站** | IP 变 ⇒ 直连断 ⇒ 回中继;该类节点**在中继上是常态而非例外** | +| S6 | **企业网节点**(封 UDP) | 打洞全败 ⇒ 必须走 **443/TCP 兜底**;否则整类不可用 | +| S7 | **中继 A 挂掉** | 受影响的是 L3 那 45 台 → 必须秒级切 B;**控制面与中继分开部署**(合并 = 挂了全员失联) | +| S8 | 控制面重启 / 早高峰 100 台同上线 | 瞬时 **100 并发** ⇒ 指数退避 + 抖动 + 令牌桶 | +| S9 | 异常节点 | 现状是**共享密钥**(无法吊销单台)⇒ 一机一钥是硬前置 | + +**S4 的定性变了**:v1 把它当"要规避的危险场景",v2 认定它是**核心用例** ⇒ 结论从"大流量绝不能过网"**修正为**: +> **大流量优先直连、中继兜底,且中继容量按几十台常驻来配**;同时把 10.8 MB 首屏做**就近/本地缓存**(同版本复用 + 已有 ETag/304),把跨机冷加载从常态降为例外。 + +--- + +## 6. 瓶颈排序(v2,按先炸顺序) + +| 序 | 瓶颈 | 触发条件 | 量级 | +|---|---|---|---| +| 1 | **中继带宽** | L3 占 45%(v1 只算 15%) | 稳态 20–27 Mbps + 突发叠加 | +| 2 | **443/TCP 兜底通道缺失** | 企业网/校园网封 UDP | 整类节点(E: 15 台)完全进不来 | +| 3 | **控制面机内存** | 若沿用 SSH 隧道(每连接一进程) | 100 × 3–5 MB = **300–500 MB** | +| 4 | 控制面单点 | 重启/升级 | 100 并发重连风暴 | +| 5 | 共享密钥 | 无法吊销、可整片放行 | 一机一钥是硬前置 | +| 6 | VPN / 代理类节点 | 反复打洞失败 | 白抖动,需检测即降级 | +| 7 | 版本碎片 | 客户端 × 平台 | 排障成本随台数线性涨 | + +--- + +## 7. 要扩到 100 台必须先做的(v2 修订) + +**P0(不做就走不通)** +1. **中继容量按 45%–55% 的 L3 占比设计**,且**让有公网 IP 的节点自动成为中继候选**(不能只有一台中心)—— 具体设计见 **`覆盖网络_骨干层方案_20260916.md`**(多中心骨干 + 选择性加入 + 资格由控制面签发)。 +2. **443/TCP 兜底通道**(治封 UDP 的企业网/校园网)——否则整类节点进不来。 +3. **一机一钥 + 可吊销 + 限流**(替换共享密钥)。 +4. **把 SSH 反向隧道换成单进程多对端方案**(内存差 1–2 个数量级)。 + +**P1(不做会出事)** +1. 中继 ≥2 台、就近选择、**与控制面分开部署**、秒级切换。 +2. **跨机大流量直连优先** + 10.8 MB 首屏就近/本地缓存。 +3. 保活 ≤25 s;VPN / 代理类节点**检测即降级中继**(不重试)。 +4. 重连指数退避 + 抖动 + 控制面令牌桶。 + +**P2** +1. **节点自报网络画像**(路径类型 直连/中继、NAT 类型、是否在 VPN、上行带宽)——没有它,容量规划与排障只能靠猜。 +2. 版本兼容矩阵(客户端 × 平台)。 + +--- + +## 8. 结论(v2,三句) + +1. **单机自用与互联是两件事**:租户维度只有一个人,**不影响**网络维度有 100 台设备要互通 —— **覆盖网络正是为"同一个人/团队的多台设备散落在各种网络里"而存在的**。v1 把这两维混为一谈,是本次推演最根本的错误。 +2. **异构网络最直接的后果是"中继占比远高于同构假设"**(不是 15%,基准 40–45%、最坏 55%)⇒ **中继容量必须按最坏情况预留**,并且**要先把网络里现成的公网节点用起来当会合/中继**。 +3. **拓扑不用换(仍是星型/分组星型),要换的是三件**:传输(SSH → 多对端隧道)、身份(共享密钥 → 一机一钥)、**兜底通道(补 443/TCP)** —— 第三件在 v1 里完全没出现,是异构网络画像逼出来的。 + +--- + +## 9. 本推演的未验证项(勿当结论) + +| # | 项 | 状态 | +|---|---|---| +| 1 | 各网络类型的**实际占比** | ⚠️ 推演设定(§2 表),需按真实设备池校准 | +| 2 | 打洞成功率(分层:家宽 / CGNAT / 移动网 / 企业网) | ⚠️ 未实测 | +| 3 | **VPN 全隧道是否真的破坏打洞** | ⚠️ 未实测(推演按"会破坏"保守处理) | +| 4 | 企业网封 UDP 的比例 | ⚠️ 未实测 | +| 5 | 中继出口带宽与链路质量 | ⚠️ 未实测(仅有跨云 22 KB/s 作为下界参考) | +| 6 | 控制面机规格(1.8 GB / 2 核) | ⚠️ 来自 2026-09-08 旧决策记录,**需复核** | +| 7 | 单条 SSH 隧道常驻内存 3–5 MB | 📋 量级估计 | diff --git a/dsh-server-docs/04-调整方案/107-覆盖网络-千台全场景推演.md b/dsh-server-docs/04-调整方案/107-覆盖网络-千台全场景推演.md new file mode 100644 index 0000000..68c8b44 --- /dev/null +++ b/dsh-server-docs/04-调整方案/107-覆盖网络-千台全场景推演.md @@ -0,0 +1,289 @@ +# 107 · 覆盖网络 · 千台全场景推演 +- 日期:2026-09-16 | 状态:📋 **规划态**(**文字推演**;纸面演算,未接入任何机器) +- 来源:工作区根 `覆盖网络_千台全场景推演_20260916.md`(正文见 附录 A) +- 层级:规模推演(第二版 · 千台)| 承接档案 **106**(v2) · 104 · 108 · 109;被 **112**(瓶颈落地)承接 +- 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +> **TL;DR** +> 1000 台异构设备 × 11 个场景的流量推演。**控制面在 1000 台规模仍不是瓶颈**(50 req/s); +> 🔥 **先炸的是 presence**(1000 人大房 ≈ **16,700 次/秒**,是其消息扇出 1,000/s 的 **16 倍**); +> 💰 **「游戏服放在哪里」是本方案最大的成本杠杆**:放有公网 IP 的节点 ⇒ 中继承载 **0**;放家宽 ⇒ **600 Mbps 常驻**。 + +## 一、目标 + +把推演从 100 台扩到 **1000 台**,给出:设备构成 × 应用构成 · 11 个分场景推演 · **流量预算总表** · 瓶颈排序 · 五条结论。 +可判定「做完了没有」= 上述五项齐备,且**关键实测锚点与推算值被明确区分**。 + +## 二、只读前置 + +| # | 事实(**关键实测锚点,非推算**) | 核对方式(期望输出) | +|---|---|---| +| 1 | 实例首屏含客户端合并脚本 **11,363,655 B ≈ 10.8 MB**(含 ETag/304 短路) | 抓壳页 `/plugins/` 计字节(档案 97) | +| 2 | 跨云链路实测 **~22 KB/s** | 47↔106 实测(档案 110 §三) | +| 3 | 心跳间隔 **20 s** | `src/worker/tunnel.ts` 自愈定时器 | +| 4 | 不可再生数据 **46.3 MB** / 可重建 **2.9 GiB** | 备份口径(档案 110 §二) | +| 5 | 归属/租约单点;会合/中继可多实例 | 集群化设计 §1.3 | + +## 三、范围 + +- **改什么**:⏳ 未开跑。本档只输出推演与瓶颈排序,**不含实施**。 +- **不动什么**:⛔ 权威状态单点语义|⛔ 本轮不动服务器、不改代码。 +- **推演设定**:1000 台异构(A 云 100 / B 家宽 300 / C CGNAY 200 / D 移动网 150 / E 企业校园 150 / F VPN 100); + 应用 = 40 游戏服 × 300 玩家(玩家为**外部客户端,不计入这 1000 台**)+ 200 房 × 50 人 + 1 个 1000 人大房 + 2000 agent + 200 台每日增量备份。 + +## 四、决策点 + +**已定** + +1. **中继容量按 48.5% 实测口径排、按 55% 预留**(区域性网络突变会让某类节点同时回中继 ⇒ 中继瞬时翻倍)。 +2. **游戏服一律放有公网 IP 的节点(L1)** ⇒ 中继流量从 600 Mbps 降到 0(**收益最大的一次选择**)。 +3. **一次性大流量只有两处**(首屏 10.8 GB / 次、备份 10 GB / 晚)——**都用「分级缓存 + 错峰 + 低优先级」治,不用加带宽治**。 +4. **游戏的真正门槛是抖动(<20 ms),不是带宽** —— 中继链路选型要按**抖动**评估。 +5. **agent 是本方案独有的放大源**,必须独立预算;**单房间实际上限 = min(扇出预算, presence 预算, agent 预算)**。 + +**未定**:各类设备**打洞成功率**(本推演用估值表,未实测);中继链路 jitter 是否满足 <20 ms(**决定游戏可玩性,最该先测**)。 + +## 五、步骤(承接本档 §4 瓶颈排序;每步自带一次验证) + +1. **presence 改造**(订阅裁剪 + 批合并 + 大房降频)→ 验证:1000 人大房广播**从 ~16,700/s 降到 <2,000/s**。 +2. **游戏服部署规范(放 L1)** → 验证:新开服默认落 L1;中继出口带宽与「服数」关系**可预测**。 +3. **内容寻址 + 分级缓存**(治首屏 10.8 GB)→ 验证:版本发布时回源字节 ≈ 1 份 × 组数。 +4. **重连治理**(指数退避 + 全抖动 + 重试预算 + 令牌桶)→ 验证:拔掉一台中继后重连曲线**平滑爬升**而非尖峰。 +5. **备份抖动窗口 + 低优先级队列** → 验证:备份期间聊天与游戏 **p95 延迟不变**。 +6. **jitter 度量与按抖动选路** → 验证:jitter 直方图 + 超阈值自动切路径并告警。 +7. **agent 四条硬约束 + 独立配额** → 验证:注入「回声型 agent」压测,房间消息量**有上限、不增长**。 +8. **每子网打洞并发上限 + 收敛探测** → 验证:同一办公室 20 台同时上线,NAT 不丢线。 +9. **协议版本治理**(协商 + 灰度 + 相邻版本互通)→ 验证:各版本节点数与错误率**按版本切分**可观测。 + +> 📌 具体做法(含 Slack / SCCM 官方照抄点)见 **档案 112**;若只做三件:**presence + 游戏服放 L1 + 块级内容寻址**。 + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 流量预算总表 | 每类流量有「频率 / 单次 / 1000 台放大 / 上限手段」四列 | +| B | 瓶颈排序 | 9 条按「先炸顺序」排(presence 第一) | +| C | 杠杆数字 | 游戏服放 L1 ⇒ 中继 **0**;放家宽 ⇒ **600 Mbps 常驻**(峰值 1.2–2.0 Gbps) | +| D | 结论可判定 | 五条结论均可被第三方复算 | +| E | 未验证项透明 | §六 五条已列全 | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- **执行期**:§五 九步各自独立可回滚(presence 改造 / 部署规范 / 缓存 / 退避 / 队列 / 选路 / 配额 / 并发上限 / 版本治理均为独立开关或参数)。 + +## 八、回报格式 + +执行会话回填:① 每步验证命令 + 实际输出 ② 实测的打洞成功率与 jitter 分布(**与 §0.1/§6 估值表对照**) ③ presence 收敛实际降幅 ④ agent 放大系数实测 ⑤ 1000 并发重连压测结果 ⑥ commit ⑦ 未完成项与卡点。 + +## 九、未验证项(勿当结论) + +各类设备**打洞成功率**(估值表,未实测)|中继链路 **jitter** 是否满足 <20 ms(**决定游戏可玩性,最该先测**)|presence 收敛(订阅裁剪)实际降幅(未实测,业界口径可达 5×)|agent 参与的放大系数(未实测)|1000 并发重连时控制面/中继实际表现(未压测)。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `覆盖网络_千台全场景推演_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | 性质:**文字推演**(纸面演算,未接入任何机器;数值标"实测"的除外,其余为推算) +> 承接:`覆盖网络_百台规模推演_20260916.md`(v2) · `覆盖网络_全球架构复盘_20260916.md` · `覆盖网络_游戏专项_MMORPG与MUD_20260916.md` · `覆盖网络_调研_游戏网络特征与群聊上限_20260916.md` +> 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +--- + +## 0. 推演设定 + +### 0.1 设备构成(1000 台,异构) + +| 类 | 场景 | 台数 | 打洞成功率(估) | 可直连 | **需中继** | +|---|---|---|---|---|---| +| A | 云服务器(**专属公网 IP**) | 100 | 不需打洞 | 100 | 0 | +| B | 家庭固定宽带 | 300 | ~90% | 270 | 30 | +| C | 共享公网 IP / CGNAT | 200 | ~40% | 80 | 120 | +| D | 移动网(4G/5G) | 150 | ~10% | 15 | 135 | +| E | 企业 / 校园局域网(常封 UDP) | 150 | ~20% | 30 | 120 | +| F | VPN 全隧道 | 100 | ~20% | 20 | 80 | +| | **合计** | **1000** | | **515** | **485(48.5%)** | + +⇒ 与"按 **45%** 设计中继容量、按 **55%** 留余量"的口径吻合。 + +### 0.2 应用构成(跑在这 1000 台上) + +| 应用 | 规模设定 | +|---|---| +| **游戏服**(MMORPG/传奇/MUD) | **40 服**,每服 300 玩家(玩家为**外部客户端,不计入这 1000 台**) | +| **群聊房间** | 200 个房间 × 平均 50 人;**另有 1 个 1000 人大房**(压测极端) | +| **Agent** | 平均每台 2 个 ⇒ **2000 个 agent** | +| **备份** | 200 台做每日增量 | +| **迁移** | 每月数次,单次 ~46.3 MB(不可再生数据口径) | + +### 0.3 关键实测锚点(非推算) + +- 实例首屏含客户端合并脚本 **11,363,655 B ≈ 10.8 MB**(含 ETag/304 短路) +- 跨云链路实测 **~22 KB/s**(下界参考) +- 心跳间隔 **20 s**(沿用现有隧道自愈定时器) + +--- + +## 1. 设备类型 × 应用 的分工矩阵 + +| 设备类型 | 台数 | 典型角色 | 关键约束 | +|---|---|---|---| +| **云服务器(专属 IP)** | 100 | **骨干 / 中继 / 游戏服 / 备份汇聚** | 上行按量计费 ⇒ 别当默认中继 | +| **家庭固定宽带** | 300 | 常用客户端 / **服主** / 备份目标 | **上行小(20–50 Mbps)**、IP 会变 | +| CGNAY / 共享 IP | 200 | 常用客户端 | **必走中继** | +| 移动网 | 150 | 移动端客户端 | **抖动大**、切网频繁 | +| 企业 / 校园网 | 150 | 办公客户端 | **封 UDP ⇒ 必须有 443/TCP 兜底** | +| VPN 全隧道 | 100 | 远程办公 | 打洞被破坏 ⇒ 检测即降级中继 | + +--- + +## 2. 分场景推演 + +### S1 · 冷启动(1000 台加入) + +| 项 | 数值 | 判读 | +|---|---|---| +| 控制面心跳(稳态) | 1000 / 20 s = **50 req/s** | 可忽略 | +| **同时上线(惊群)** | 瞬时 **1000 并发** | 必须**令牌桶**(如 10/s ⇒ 100 s 接纳完)+ 退避抖动 | +| **首屏 bundle** | 1000 × 10.8 MB = **10.8 GB** | ⚠️ **单次最大流量** ⇒ 内容寻址 + 分级缓存(区域边缘 + 局域网共享);已加载走 304 | + +⇒ 冷启动的唯一大坑是 **10.8 GB 一次性拉取**,不是心跳。 + +### S2 · 稳态(无大任务) + +| 流量 | 计算 | 结果 | +|---|---|---| +| 控制面心跳 | 1000 / 20 s | **50 req/s** | +| **presence(200 房 × 50 人)** | `200×50×49 / 60` | **≈8,200 次/秒** | +| **presence(那个 1000 人大房)** | `1000×1000 / 60` | **≈16,700 次/秒** | +| 群聊消息(全局 50 msg/s,均扇出 50) | `50×50` | 2,500 投递/秒 | +| 大房消息(1 msg/s) | `1×1000` | 1,000 投递/秒 | + +> ⚠️ **本轮最重要的量化结论之一**:**presence 比消息早爆一个量级** —— +> 1000 人大房的 presence(**16,700/s**)是其消息扇出(1,000/s)的 **16 倍**;连"200 个普通房加起来"(8,200/s)都被它一个人超过。 +> ⇒ **第一瓶颈是 presence,不是消息**;大房必须**单独策略**(只推在线/离线态 + 批合并 + 降频)。 + +### S3 · 游戏(40 服 × 300 玩家)——**"服放哪"决定中继成本差一个数量级** + +| 部署方式 | 每服上行 | 中继承载 | 结论 | +|---|---|---|---| +| **服放有公网 IP 的节点(L1)** | 300 × 10 KB/s = **24 Mbps** | **0** | ✅ **玩家直连,中继完全不承载** | +| 服放家宽 / CGNAT 后(假设 40 服中 25 服) | 同上 | **25 × 24 Mbps = 600 Mbps 常驻** | ⚠️ 单台 1 Gbps 中继都不够,还要留峰值 | + +- 峰值(攻城战):带宽翻倍 ⇒ 48–80 Mbps/服 ⇒ 25 服同时攻城 = **1.2–2.0 Gbps** ⇒ 必须错峰 + 配额。 +- 抖动门槛:**jitter < 20 ms**,否则位置与战斗 desync ⇒ **中继路径必须按抖动评估,不能只看带宽**。 + +> ⭐ **结论:把游戏服放在有公网 IP 的节点上(= 骨干层),是本方案里收益最大的一次选择** —— 中继流量从 600 Mbps 直接降到 0。 + +### S4 · 群聊极端房(1000 人) + +| 项 | 数值 | +|---|---| +| presence | **16,700 次/秒** ← 瓶颈 | +| 消息扇出(1 msg/s) | 1,000 投递/秒(可承受) | +| 必须做的 | presence 只推在线/离线 + 批合并 + 降频;消息**切游标拉取**;**慢速模式**;RBAC 缓存 | + +⇒ 单房间建议上限按**扇出预算**定义,而不是人数(见调研稿 §2.4)。 + +### S5 · Agent 风暴(**本方案独有的放大源**) + +- 2000 个 agent(平均每台 2 个)。若那个 1000 人房里聚集 200 个 agent: + - 无约束 ⇒ agent 互相激发 ⇒ 消息量**指数增长**(A 说 → B 回 → …)⇒ 房间被瞬间打满。 +- 必需四条硬约束:**① 禁止 agent 直接触发 agent(只有人的消息能触发)② 每 agent 每 N 分钟最多 M 条 ③ 发言后静默期 ④ 房间级 agent 数上限**(建议 ≤ 房间人数 / 10)。 + +> ⇒ **对本方案而言,单房间的实际上限由「presence + agent 预算」决定**,消息扇出还在其次。 + +### S6 · 备份窗口(每晚 02:00) + +| 口径 | 计算 | 结果 | +|---|---|---| +| 200 台 × 增量 50 MB | 10 GB | — | +| 摊到 1 小时 | 10 GB / 3600 s | **22 Mbps**(可接受) | +| **集中在头 10 分钟** | 10 GB / 600 s | **136 Mbps** ⚠️ 会挤占游戏与聊天 | + +⇒ 必须**抖动窗口 + 低优先级队列**(交互流量优先)。 + +### S7 · 迁移(大文件) + +- 单次 46.3 MB;若链路只有 22 KB/s ⇒ **35 min**(这是慢链路下界)。 +- 手段:分片多流 / 先压缩 / 惰性拉取 / 经对象存储中转。 +- 10 台同时迁移 ⇒ 必须配额,不能占满中继。 + +### S8 · 中继故障 + +- 中继 A 挂 ⇒ 其承载部分(假设 485 的 1/3 ≈ **160 台**)需切换。 +- **160 并发重连** ⇒ 无退避就会打垮备用中继 ⇒ 必须**指数退避 + 抖动**。 +- 若全网只 2 台中继:切换后单台要扛 485 台 ⇒ **必须 N+1 且有余量**,最好由 L1 节点组成中继池。 + +### S9 · 控制面重启 + +- 1000 台重连 ⇒ **1000 并发** ⇒ 令牌桶 + 退避。 +- **数据面必须独立存活**(已建立的连接不受影响)—— 这是控制面/数据面分离的核心价值。 + +### S10 · 区域性网络突变 + +- 某运营商调 NAT / 某区域断网 ⇒ 整类节点同时回中继 ⇒ **中继瞬时翻倍**。 +- ⇒ 中继容量必须按 **55%(而不是 48.5%)** 预留,且要能在数分钟内横向加中继。 + +### S11 · NAT 表溢出 + +- 同一企业网 / 同一家庭多台设备同时向同一目标打洞 ⇒ 该 NAT 表被打满 ⇒ 全屋(全办公室)掉线。 +- ⇒ **每 NAT / 每子网打洞并发上限** + 分散端口 + 收敛探测频率。 + +--- + +## 3. 1000 台流量预算总表(**全案最重要的一张表**) + +| 流量 | 频率 | 单次 | 1000 台放大 | 上限手段 | +|---|---|---|---|---| +| 控制面心跳 | 20 s | ~100 B | **50 req/s** | 懒心跳 + 合并上报 | +| **presence(普通房)** | 变化驱动 | 小 | **≈8,200 次/s** | 订阅裁剪(只推可见)+ 批合并 | +| **presence(1000 人大房)** | 变化驱动 | 小 | **≈16,700 次/s** | **只推在线态 + 降频 + 批合并** | +| 群聊消息 | 50 msg/s | 小 | 2,500 投递/s | 大房切**游标拉取** | +| **游戏流量** | 持续 | 24–80 Mbps/服 | **0(服放 L1)** / **600 Mbps(服放家宽)** | **把游戏服放到有公网 IP 的节点** | +| **首屏 bundle** | 版本发布 | 10.8 MB | **10.8 GB** | 内容寻址 + 分级缓存 + 错峰 | +| 备份 | 每晚 | 50 MB/台 | 10 GB/晚(集中时 **136 Mbps**) | 抖动窗口 + **低优先级** | +| 迁移 | 每月 | 46.3 MB/次 | 视并发 | 分片多流 + 配额 + 惰性拉取 | +| 打洞尝试 | 建连时 | 小 | 受并发上限 | **每对端 ≤4 并发** + 每 NAT 上限 | +| 更新/目录分发 | 发布时 | 大 | 爆炸 | **分层拉取**,不推送 | + +--- + +## 4. 瓶颈排序(1000 台,按"先炸顺序") + +| 序 | 瓶颈 | 量级 | 主要处置 | +|---|---|---|---| +| 1 | **presence** | 8.2k–16.7k 次/秒 | 订阅裁剪 + 批合并 + 大房降频 | +| 2 | **游戏服放家宽时的中继带宽** | **600 Mbps 常驻**、峰值 1.2–2.0 Gbps | **把游戏服放 L1 节点** + 错峰 + 配额 | +| 3 | **首屏 bundle 冷启动** | **10.8 GB 一次性** | 内容寻址 + 分级缓存 + 令牌桶 | +| 4 | **中继抖动**(游戏可玩性) | jitter 需 <20 ms | 中继链路质量选型 + 就近 | +| 5 | 备份窗口挤占 | 集中 136 Mbps | 抖动窗口 + 低优先级 | +| 6 | 中继 / 控制面故障重连 | **160 / 1000 并发** | 退避 + 抖动 + N+1 | +| 7 | **agent 自激** | 指数级(本方案独有) | 四条硬约束 + 房间 agent 上限 | +| 8 | NAT 表溢出 | 整屋/整办公室掉线 | 每子网打洞并发上限 | +| 9 | 版本碎片 | 排障成本 | 协议版本协商 + 灰度 | + +--- + +## 5. 推演结论(五条) + +1. **控制面在 1000 台规模仍不是瓶颈**(50 req/s);**先炸的是 presence**(16.7k 次/秒),它比消息扇出早爆一个量级。 +2. **"游戏服放在哪里"是本方案最大的成本杠杆**:放有公网 IP 的节点 ⇒ 中继承载 **0**;放家宽 ⇒ **600 Mbps 常驻**。⇒ 应把骨干层与游戏服合并设计。 +3. **一次性大流量只有两处**:首屏 bundle(10.8 GB/次)与备份(10 GB/晚)——**都用"分级缓存 + 错峰 + 低优先级"治,不用加带宽治**。 +4. **游戏的真正门槛是抖动(<20 ms),不是带宽** —— 中继链路选型要按抖动评估。 +5. **agent 是本方案独有的放大源**,必须独立预算;**单房间实际上限 = min(扇出预算, presence 预算, agent 预算)**。 + +--- + +## 6. 未验证项(勿当结论) + +| # | 项 | 状态 | +|---|---|---| +| 1 | 各类设备的**打洞成功率**(本推演用的是估值表) | ⚠️ 未实测 | +| 2 | 中继链路 **jitter** 是否满足 <20 ms | ⚠️ **决定游戏可玩性,最该先测** | +| 3 | presence 收敛(订阅裁剪)的实际降幅 | ⚠️ 未实测(业界口径可达 5×) | +| 4 | agent 参与的放大系数 | ⚠️ 未实测 | +| 5 | 1000 并发重连时控制面 / 中继的实际表现 | ⚠️ 未压测 | diff --git a/dsh-server-docs/04-调整方案/108-覆盖网络-游戏专项-MMORPG与MUD.md b/dsh-server-docs/04-调整方案/108-覆盖网络-游戏专项-MMORPG与MUD.md new file mode 100644 index 0000000..47819bd --- /dev/null +++ b/dsh-server-docs/04-调整方案/108-覆盖网络-游戏专项-MMORPG与MUD.md @@ -0,0 +1,230 @@ +# 108 · 覆盖网络 · 游戏专项-MMORPG与MUD +- 日期:2026-09-16 | 状态:📋 **规划态 / 未实施**(专项设计稿) +- 来源:工作区根 `覆盖网络_游戏专项_MMORPG与MUD_20260916.md`(正文见 附录 A) +- 层级:专项设计| 承接档案 **111 §一**(其修正点);配套 **109**(游戏网络参数与群聊上限) +- 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +> ⚠️ **本档含一次判定修正**:此前按 **3D 大世界强实时竞技**评估,结论是"不合适"; +> 用户明确重点是 **MMORPG(2D/2.5D)· MUD · 传奇类** —— 这三类**恰好是覆盖网络最匹配的应用**,甚至比群聊更契合。 + +> **TL;DR** +> 这三类游戏的架构(**服务端权威 + tick 驱动 + AOI 九宫格广播 + 分区/分线**)**本身就是覆盖网络友好型的**, +> 不需要为它改造什么,只需提供「到达游戏服的可靠低延迟路径」。 +> ⭐ **最重要的简化:玩家之间不需要互联**(服务端权威,玩家只与游戏服通信)⇒ **中继容量按「服数」算,不按「玩家数」算**。 + +## 一、目标 + +把「覆盖网络上的 MMORPG(2D/2.5D) / MUD / 传奇类」设计成可落地方案:流量画像 · 与覆盖网络的映射 · 12 条关键设计细节 · 参考方案对照 · 反模式 · 游戏线落地顺序。 +可判定「做完了没有」= 上述六项齐备,且**最匹配判定的依据(五条特征对照)已给出**。 + +## 二、只读前置 + +| # | 事实 | 核对方式(期望输出) | +|---|---|---| +| 1 | 玩家与游戏服是**长连接**(TCP/WebSocket/自定义 UDP)且**断线重连不踢人** | 本档 §3.1 第 2 条(设计要求) | +| 2 | 「房间」抽象**平台尚不存在**(现在是「每用户一个实例 + 会话」) | 档案 110 §五(群聊需新建,无房间抽象) | +| 3 | 存档 = **不可再生数据** ⇒ 直接套备份三层 | 档案 110 §二(不可再生 46.3 MB 口径) | +| 4 | 有公网 IP 的节点天然就是**游戏服 / 中继候选** | 档案 105 §1 | +| 5 | AOI 是控带宽的杀手锏:扇出从 O(N) 降到 O(k) | 本档 §1(九宫格,k≈20–80) | + +## 三、范围 + +- **改什么**:⏳ 未开跑。方案面 = 服主接入(拨出 + 中继)· 房间层(组队/行会/频道)· 存档备份 · 跨区/跨线路由 · 会话恢复 + 连接迁移 · 副本临时实例。 +- **不动什么**:⛔ 官方 dsh 主程序(R2)|⛔ 不把玩家连成 P2P 网状(**毫无必要**且徒增连接数)|⛔ 本轮不动服务器、不改代码。 +- **明确排除**:❌ 3D 大世界强实时竞技(FPS / MOBA 64+)—— 需专用服务端 + 权威模拟,中继多一跳,P2P 无法反作弊。 + +## 四、决策点 + +**已定** + +1. **游戏重点是 MMORPG(2D/2.5D) / MUD / 传奇类**(用户明确定调)⇒ 判定上修为「**最匹配**」,非 3D 强实时竞技。 +2. **服务端权威不可让**(P2P 无法防作弊;且这类游戏天生服务端权威 ⇒ 反作弊问题自然解决)。 +3. **对外降频 + 按变化发送**(⛔ 别把服务端内部帧率直接当对外频率)。 +4. **社交功能直接复用「房间层」**(队伍/行会/世界频道/副本组 = 房间)⇒ 一次建房,聊天 + 组队 + 行会 + 频道全都有。 +5. **反模式硬拦**:全图广播 · 信任客户端时间 · 对外频率=服务端帧率 · 每 tick 落盘 · 世界频道无限制推送 · 玩家 IP 一变就断线 · 单区无限扩容 · 把玩家连成 P2P 网状。 + +**未定**:会话恢复窗口(断线多久内可无缝续上,参数待定)。 + +## 五、步骤(§6 游戏线落地顺序;每步自带一次验证) + +1. **服主接入**:无公网 IP 的机器能开服并被外网访问(拨出 + 中继)—— **最小可用形态** → 验证:外网玩家可连上 NAT 后的游戏服。 +2. **房间层**(组队/行会/频道,与聊天共用)→ 验证:一次建房,四类社交容器同时可用。 +3. **存档备份**(套用备份三层,**只备存档与配置**,不备可重建的客户端资源)→ 验证:恢复演练通过。 +4. **跨区/跨线路由**(骨干节点承担)→ 验证:跨地图/跨线/合服有可用路径。 +5. **会话恢复 + 连接迁移**(移动端体验)→ 验证:Wi-Fi↔蜂窝切换不掉线。 +6. 副本临时实例、合服。 + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 每玩家带宽 | MUD **<5 KB/s** | 传奇 **10–50 KB/s** | 2D/2.5D MMO **20–80 KB/s** | +| B | 单节点承载 | MUD 数百人 | 传奇 100–300 人 | 2D/2.5D 300–500 人 | +| C | ⭐ 关键简化生效 | 中继容量**按服数算**(一个服 1~N 条中继,几百玩家不各占一条) | +| D | AOI 生效 | 扇出从 O(N=500) 降到 **O(k≈20–80)**(差 10 倍以上) | +| E | 反模式零命中 | §5 八条反模式逐条对照,无命中 | +| F | 未验证项透明 | §7 四条已列全 | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- **执行期**:§五 六步各自独立可回滚;⛔ **服务端权威不可回滚**(一旦允许客户端持有权威状态 = 可作弊,属红线)。 + +## 八、回报格式 + +执行会话回填:① 每步验证命令 + 实际输出 ② 本环境实测:中继承载 100–300 人游戏服的实际**带宽与抖动** ③ 443/TCP 兜底下长连接稳定性 ④ 会话恢复窗口实际取值 ⑤ 跨区转发延迟增量 ⑥ commit ⑦ 未完成项与卡点。 + +## 九、未验证项(勿当结论) + +本环境实测:中继承载 100–300 人游戏服的实际带宽与抖动(**未实测**)|443/TCP 兜底通道下长连接的稳定性(UDP 封禁的企业网,**未实测**)|会话恢复窗口(**待定参数**)|跨区转发的延迟增量(**待实测**)。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `覆盖网络_游戏专项_MMORPG与MUD_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | 性质:**专项设计稿**(细化 `覆盖网络_补遗与参考方案_20260916.md` §一) +> 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +--- + +## 0. 判定修正(此前按 3D 强实时竞技评估,结论要改) + +> 前文说"大规模 MMORPG 不合适" —— **那是针对 3D 大世界强实时**。用户明确重点是 **MMORPG(2D/2.5D)· MUD · 传奇类**,这三类**恰好是覆盖网络最匹配的应用**,甚至比群聊更契合。 + +| 特征 | FPS / MOBA(不适合) | **MMORPG / MUD / 传奇(适合)** | +|---|---|---| +| 权威归属 | 实时模拟需专用服,P2P 反作弊难 | **天生服务端权威** ⇒ 反作弊问题自然解决 | +| 延迟敏感 | <50 ms | **几百 ms 无感**(tick 驱动) | +| 广播方式 | 全员高频状态 | **AOI 视野广播(九宫格)** ⇒ 天然不放大 | +| 每玩家带宽 | 数十–数百 Kbps 且要求抖动小 | **数 KB/s ~ 数十 KB/s** | +| 扩展方式 | 单局 | **分区 / 分线** ⇒ 天然水平切分 | + +**一句话**:这三类游戏的架构(服务端权威 + tick + AOI + 分区)**本身就是覆盖网络友好型的**,我们不需要为它改造什么,只需要提供"到达游戏服的可靠低延迟路径"。 + +--- + +## 1. 流量画像(决定容量与选路) + +| 类型 | tick / 广播频率 | 每玩家带宽 | 单节点可承载 | 覆盖网络压力 | +|---|---|---|---|---| +| **MUD(文字)** | tick 0.25–1 s(文本行) | **< 5 KB/s** | 数百人 | **极轻**,中继也够 | +| **传奇类(2.5D 俯视)** | 服务端 20–50 Hz 内部;对外按变化/降频 | **10–50 KB/s** | 100–300 人 | 轻 | +| **2D/2.5D MMORPG** | 同上 + 技能/特效事件 | **20–80 KB/s** | 300–500 人 | 轻–中 | + +**两处关键的省带宽机制(这类游戏的标准做法,直接沿用)**: + +1. **AOI / 兴趣区域广播(九宫格)**:只广播**视野内**实体 ⇒ 扇出从 O(N=500) 降到 **O(k≈20–80)**,差 **10 倍以上**。这就是为什么 MMORPG 不会出现"广播风暴"。 +2. **对外降频 + 按变化发送**:服务端内部 20–50 Hz 模拟,对客户端只发**变化**且可降到 5–10 Hz ⇒ 再省一半到八成。 + +--- + +## 2. 与覆盖网络的映射(**关键简化**) + +``` + 玩家(任意网络) 游戏服(服主的机器) + ┌──────────────┐ ┌──────────────────────┐ + │ 玩家 A 家宽 │──直连──────▶│ │ + │ 玩家 B 移动网 │──中继──────▶│ 服务端权威 + 分区/分线 │ + │ 玩家 C 企业网 │──443/TCP──▶│ 存档 / AOI / tick │ + └──────────────┘ └──────────────────────┘ +``` + +> ⭐ **最重要的简化**:**玩家之间不需要互联**(服务端权威,玩家只与游戏服通信)。 +> ⇒ 覆盖网络在这一场景里**只需解决一件事:让玩家可靠地到达游戏服**,而**不是**把玩家连成网。 +> ⇒ 直接后果:**中继容量按"服数"算,不按"玩家数"算** —— 一个服只需要 1~N 条中继,几百个玩家不各占一条。 + +### 2.1 三类角色的接入需求 + +| 角色 | 需求 | 覆盖网络的作用 | +|---|---|---| +| **服主(无公网 IP)** | 让外网玩家能连进来 | **必须有**(拨出 + 中继/反向隧道)—— 这是核心价值 | +| **服主(有公网 IP)** | 直接开放端口 | 可选(只为跨地域优化) | +| **玩家** | 连上游戏服 | 直连为主;跨地域或对端在 NAT 后时走中继 | + +⇒ 与"骨干层"完美衔接:**有公网 IP 的节点天然就是游戏服/中继候选**。 + +--- + +## 3. 关键设计细节(12 条) + +### 3.1 网络与同步 + +1. **服务端时间权威**:一切 tick、冷却、移动校验以**服务端时钟**为准,**不信任客户端时间** ⇒ 这是防"加速外挂"的唯一正解(传奇私服最常见的作弊就是改本地时间/加速)。 +2. **长连接 + 心跳**:这类游戏是**长连接**(TCP/WebSocket/自定义 UDP)。心跳要能区分"卡"与"断",且**断线重连不踢人**(回放窗口 + 状态快照)。 +3. **连接迁移**:玩家 Wi-Fi ↔ 蜂窝切换会换 IP ⇒ 用**会话 token 恢复**而不是"IP 变了就当新连接"(否则玩家一走动就掉线)。 +4. **对外降频 + 变化优先**:见 §1.2;**别把服务端内部帧率直接当对外频率**。 +5. **AOI 用成熟算法**:九宫格(最常用)/ 十字链表 / 四叉树。⚠️ **不要用全图广播** —— 那是这类游戏唯一的"自找风暴"。 + +### 3.2 世界结构 + +6. **分区 / 分线(zone / shard)**:地图或线路 = 独立的模拟单元 ⇒ 天然的水平扩展点,也天然对应"一台机器跑一个区"。 +7. **跨区 / 跨线转发**:玩家跨地图、跨线、跨服(合服)时需要转发 ⇒ **由骨干节点做跨区路由**(这部分流量是小头,但必须有一条路径)。 +8. **副本 / 独立实例**:副本可以**临时开进程**(用完即销毁)—— 资源模型与"实例"一致。 + +### 3.3 数据与持久化 + +9. **存档策略**:热数据在内存 + **定期落盘/写日志**(不要每 tick 落盘);冷数据(离线玩家)批量归档。 +10. **持久化与备份衔接**:这类游戏的存档是**不可再生数据** ⇒ 直接套用备份三层(本地快速恢复 + 对象存储主备份 + 网内第三副本),且**只备存档与配置,不备可重建的客户端资源**。 +11. **节点故障的玩家恢复**:游戏服挂 ⇒ 玩家应能**落到另一个节点继续**(配合 tick 存档 + 会话恢复);这正是"迁移提速"那条在游戏场景的直接应用。 + +### 3.4 社交与复用 + +12. ⭐ **社交功能直接复用「房间层」**:**队伍 = 房间、行会 = 房间、世界/交易频道 = 房间、副本组 = 房间**。 + ⇒ 前面"群聊房间与游戏对局是同一个抽象"的结论在这里第二次兑现:**一次建房,聊天 + 组队 + 行会 + 频道全都有**。 + ⚠️ 但要注意**世界频道的扇出**:它是唯一"一人发、全网收"的点 ⇒ **必须限频 + 分片 + 拉取式**,否则就是唯一的风暴源。 + +--- + +## 4. 参考方案对照(这类游戏生态很成熟,别自研) + +| 方向 | 参考方案 | 借什么 | +|---|---|---| +| **MUD 服务端** | **Evennia**(Python,现代)、FluffOS / LPMud、CircleMUD、Ranvier(JS) | tick 驱动世界模型、房间/对象/指令体系 | +| **传奇类(Mir2)服务端** | 开源 **Mir2 服务端模拟器**(多份社区实现)、HeroM2 类引擎 | 格子地图、服务端权威移动校验、封包协议 | +| **2D/2.5D MMO 服务端框架** | **Skynet**(Lua,分区分服经典)、**Pomelo**(Node.js 分布式)、**KBEngine**、**ET**(C# 双端)、Colyseus、**Orleans**(虚拟 Actor) | 分区分线、跨服路由、actor/实体模型 | +| **通用游戏后端** | **Nakama**(房间 + 匹配 + 持久化 + 排行,开源) | 直接可用的社交/账号/存储能力 | +| **AOI 算法** | 九宫格 / 十字链表 / 四叉树 / R-tree | 视野广播的成熟实现 | +| **联机传输** | KCP / enet / QUIC;WebRTC DataChannel(不可靠模式) | 类 UDP 的低延迟可靠传输 | +| **客户端** | Cocos / LayaAir / Phaser / Godot(2D) | 与 Web 客户端壳集成的天然选择 | + +**国内生态提示**:传奇/2D MMO 的"一台机器一个区 + 分线"是**行业标准做法**,与我们"用户自己开服 + 骨干中继让外网可达"的模型天然契合 —— 不需要发明新范式。 + +--- + +## 5. 反模式(这类游戏特别容易踩的) + +| # | 反模式 | 后果 | +|---|---|---| +| 1 | **全图广播**(不做 AOI 裁剪) | 唯一的自找广播风暴 | +| 2 | **信任客户端时间** | 加速外挂横行 | +| 3 | **对外频率 = 服务端帧率** | 带宽浪费数倍 | +| 4 | **每 tick 落盘** | IO 打满 | +| 5 | **世界频道无限制推送** | 一人发言全员收 = 放大点 | +| 6 | **玩家 IP 一变就断线** | 移动玩家体验崩塌 | +| 7 | **单区无限扩容** | 该分区就分区,别硬撑单进程 | +| 8 | **把玩家连成 P2P 网状** | 毫无必要(服务端权威)且徒增连接数 | + +--- + +## 6. 落地顺序(游戏线) + +1. **服主接入**:无公网 IP 的机器能开服并被外网访问(拨出 + 中继)—— **这是最小可用形态**。 +2. **房间层**(组队/行会/频道,与聊天共用)。 +3. **存档备份**(套用备份三层,只备存档与配置)。 +4. **跨区/跨线路由**(骨干节点承担)。 +5. **会话恢复 + 连接迁移**(移动端体验)。 +6. 副本临时实例、合服。 + +--- + +## 7. 未验证项 + +| # | 项 | 状态 | +|---|---|---| +| 1 | 本环境实测:中继承载 100–300 人游戏服的实际带宽与抖动 | ⚠️ 未实测 | +| 2 | 443/TCP 兜底通道下长连接的稳定性(UDP 封禁的企业网) | ⚠️ 未实测 | +| 3 | 会话恢复窗口(断线多久内可无缝续上) | 📋 待定参数 | +| 4 | 跨区转发的延迟增量 | 📋 待实测 | diff --git a/dsh-server-docs/04-调整方案/109-覆盖网络-调研-游戏网络特征与群聊上限.md b/dsh-server-docs/04-调整方案/109-覆盖网络-调研-游戏网络特征与群聊上限.md new file mode 100644 index 0000000..1dc2759 --- /dev/null +++ b/dsh-server-docs/04-调整方案/109-覆盖网络-调研-游戏网络特征与群聊上限.md @@ -0,0 +1,202 @@ +# 109 · 覆盖网络 · 调研-游戏网络特征与群聊上限 +- 日期:2026-09-16 | 状态:📋 **规划态**(**全网调研稿**;数值均标注来源口径,未在本环境实测的一律标出) +- 来源:工作区根 `覆盖网络_调研_游戏网络特征与群聊上限_20260916.md`(正文见 附录 A) +- 层级:专项调研(**数值底座**)| 配套档案 **108**(游戏专项)· 104(全球架构复盘) +- 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +> **TL;DR** +> 两部分:① **这类游戏的网络特征**(传奇 / MMORPG / MUD 的每玩家带宽、同步间隔、承载、延迟/丢包门槛); +> ② **单房间群聊的人数上限** —— 🔑 关键结论:**上限不是「人数」而是「扇出预算」**,且 **presence(N²)比消息更早爆**(1000 人房 ≈16,700 次/秒)。 +> 给我们场景特有的上限:**单房间实际上限由「presence + agent 预算」决定**,不是由消息扇出决定。 + +## 一、目标 + +为容量规划提供**可引用的数值底座**:游戏侧(每玩家 2–20 KB/s、jitter<20 ms 等)与群聊侧(产品上限对照、三种分发模型的爆炸点、分档建议)。 +可判定「做完了没有」= 两部分数值齐备 + **每条标注是行业资料口径还是本环境实测** + 结论可换算到本方案。 + +## 二、只读前置 + +| # | 事实 | 核对方式(期望输出) | +|---|---|---| +| 1 | 本档全部游戏数值均为**行业资料口径**,非本环境实测 | 逐条对照 §1.1/§1.2/§1.3 的来源标注 | +| 2 | 本环境唯一相关实测 = 跨云 **~22 KB/s**(只能作下界) | 47↔106 实测(档案 110 §三) | +| 3 | 我们场景的 presence 量级可与 §2.2 公式对齐 | `1000 × 1000 / 60` ≈ **16,700 次/秒** | +| 4 | 平台现**无「房间」抽象** ⇒ 群聊属新增能力,不是开关 | 档案 110 §五 | +| 5 | 抖动门槛 **>20 ms 即 desync** 是选路的判据来源 | 本档 §1.2 与 §1.4 第 2 条 | + +## 三、范围 + +- **改什么**:⏳ 无实施动作 —— 本档是**调研**,产出为数值与判据,供 104/107/108/112 引用。 +- **不动什么**:⛔ 本轮不动服务器、不改代码、不改文档库其它文件。 +- 🟢 边界:⛔ **不得把本档的行业口径数字当作本环境实测结论**(每条均已标注)。 + +## 四、决策点 + +**已定(本档给出的判据,已被后续档案采纳)** + +1. **容量按「服」算,不按「玩家」算**(服务端权威 ⇒ 玩家之间不互联)⇒ 中继需求 = 服数 × 1~N。 +2. **游戏侧要盯的是「抖动」不是「带宽」**(jitter > 20 ms 即 desync)⇒ 中继链路质量差(如跨云 22 KB/s)**延迟低也没用**。 +3. **上行是主方向**(服务器 → 玩家)⇒ 规划时看服务器上行。 +4. **单房间上限定义为「扇出预算」而不是人数** ⇒ 先定"单节点每秒可承受投递数",再反推人数上限(可随架构演进变大,而不是魔法数字)。 +5. **混合模型**(小群扇出 / 大群拉取)—— Telegram 实际做法,服务端只维护**消息时序 + 版本游标**。 +6. **presence 收敛 = 只订阅「当前可见成员列表」**(Slack 做法)⇒ 流量降 5 倍。 +7. **压测必须用攻城场景**(数百人同屏、带宽翻倍、同步间隔收紧到 50–100 ms),不能用平峰。 + +**未定**:本环境能否满足 jitter<20 ms(**未实测,且这是游戏可玩性的决定项**)。 + +## 五、步骤 + +**本档无实施步骤**(调研稿)。其**结论已被下列档案转化为可执行步骤**: +- 游戏侧 → **档案 108 §五**(服主接入 → 房间层 → 存档备份 → 跨区路由 → 会话恢复 → 副本/合服) +- presence 与群聊上限 → **档案 112 §1**(presence 七条落地做法 + 大房特殊策略) +- 数值校准 → **档案 107 §六**(未验证项转为实测项) + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 游戏数值可引用 | 传奇每人 0.5–20 KB/s;MMORPG 80–800 Kbps;MUD <1 KB/s —— 均标来源 | +| B | 群聊上限对照 | Telegram 200,000 | WhatsApp 2,048 | Discord 单频道 100K+ 在线 | +| C | 分档建议 | ≤100 / 100–2,000 / 2,000–50,000 / >50,000 四档,各有架构要求与判据 | +| D | 本方案特有上限 | 明确「presence + agent 预算」比消息扇出更早触顶 | +| E | 未验证项透明 | 第三部分五条已列全 | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- ⛔ **不得作为实测依据被引用**:本档数值是**行业资料口径**,任何"已经达标"的结论都必须另有本环境实测支撑。 + +## 八、回报格式 + +执行会话(或后续校准会话)回填:① 自建服实测的每玩家带宽与同步间隔(与 §1.1 对照)② 中继链路 jitter 分布 ③ 攻城战压测结果 ④ presence 收敛实际降幅(5× 是否可达)⑤ agent 放大系数实测 ⑥ 取数时间与命令。 + +## 九、未验证项(勿当结论) + +上述游戏数值均为**行业资料口径**,非本环境实测(**需按自建服实测校准**)|中继链路能否满足 **jitter < 20 ms**(比带宽更关键,**未实测,且这是游戏可玩性的决定项**)|攻城战(数百人同屏)在本方案的压测结果(**未做**)|presence 在本方案下的实际收敛效果(5× 是否可达,**未实测**)|agent 参与的放大系数实测(**未实测**)。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `覆盖网络_调研_游戏网络特征与群聊上限_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | 性质:**全网调研稿**(数值均标注来源口径;未在本环境实测的一律标出) +> 配套:`覆盖网络_游戏专项_MMORPG与MUD_20260916.md`|`覆盖网络_全球架构复盘_20260916.md` +> 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +--- + +## 第一部分 · 这类游戏的网络特征 + +### 1.1 传奇类(中文运维资料口径,最具体) + +| 参数 | 数值 | +|---|---| +| **每人带宽** | **文字聊天 0.5 KB/s | 普通战斗 2–5 KB/s | 攻城战 10–20 KB/s**;另一口径:单用户平均上行 **10–20 KB/s** | +| **带宽估算公式** | `所需带宽 = 玩家数 × 100 Kbps ÷ 8`;100 人 ≥ 2 Mbps | 500 人 ≥ 10 Mbps | 1000 人 ≥ 50 Mbps | +| **实战推荐带宽** | 50 人 5 Mbps | 200 人 10 Mbps | 500 人 20 Mbps+(均含冗余) | +| **同步间隔** | 常规 **100–200 ms(5–10 Hz)**;**攻城/大型团战 50–100 ms(10–20 Hz)** | +| **引擎帧数设置** | <100 人 20 帧 | ≤200 人 25–30 帧 | ≈300 人 35–40 帧 | +| **发送间隔 / 缓存** | 网络发送间隔 20–30 ms;发送缓存 4096 B;接收缓存 8192 B;最大接收 1024–2048 KB/s | +| **承载** | 单区常规 **1000–5000 人**(TCP 并发 2000–10000;TPS 500–2000) | +| **延迟 / 丢包** | 延迟 ≤ **50 ms**,丢包 < 1% | +| **内存经验值** | 每 50 名玩家 ≈ 1 GB(+20% 缓冲);1000 人区服建议 16 GB | +| **峰值场景** | **攻城战:数百玩家同屏**,带宽翻倍至 **80–100 Mbps**(1000 人口径),CPU/内存压力最大 | + +### 1.2 MMORPG(英文资料口径,含 3D 参照) + +| 参数 | 数值 | +|---|---| +| **每玩家带宽** | 同步 **10–20 Hz**;兴趣域实体 **50–100 个**;每实体 **20–50 B**;每包 **1–5 KB** ⇒ **单客户端 80–800 Kbps**(该上限是 3D 现代 MMO 口径;**2D/传奇类取低段**) | +| **500 人峰值** | **200–500 Mbps**;端口最低 **1 Gbps**,500+ 用 10 Gbps | +| **延迟门槛** | **< 100 ms**;⚠️ **抖动(jitter)> 20 ms 就会造成位置与战斗 desync** | +| 数据库 | MNORPG 是**持续写入**(每次拾取/战斗/交易都写)⇒ **DB I/O 是隐藏瓶颈**,>500 人建议数据库独立机器 | +| 优化 | **兴趣域(AOI)是控制带宽的"杀手锏"**;delta 压缩可再减 **50%+** | + +### 1.3 MUD(文字) + +- 纯文本行 ⇒ 每玩家 **< 1 KB/s**(与棋牌/回合制同档);瓶颈是**并发连接数**(内存与文件句柄),不是带宽。 +- tick 0.25–1 s;**延迟容忍度最高**,跨洲也可玩。 + +### 1.4 对覆盖网络的五条推论(这一节才是我们要的) + +1. **带宽量级很小**:这类游戏单玩家 **2–20 KB/s**,1000 人也就 **20–100 Mbps** —— **中继扛得住**,不像视频/大文件。 +2. ⚠️ **真正要盯的是"抖动",不是"带宽"** —— 业界口径 **jitter > 20 ms 就会 desync**。⇒ 中继路径的价值不是省带宽,而是**抖动是否可控**;中继链路质量差(如实测那条 22 KB/s 的跨云)**延迟低也没用**。 +3. **上行是主方向**(服务器 → 玩家),下行只是操作指令 ⇒ 规划时**看服务器上行**。 +4. **容量按"服"算,不按"玩家"算**(服务端权威 ⇒ 玩家之间不互联)⇒ 中继需求 = 服数 × 1~N,而不是玩家数。 +5. **攻城战就是压测基准**:数百人同屏、带宽翻倍、同步间隔收紧到 50–100 ms ⇒ **压测必须用攻城场景**,不能用平峰。 + +--- + +## 第二部分 · 单房间群聊的人数上限 + +### 2.1 产品上限对照(真实产品,可作为能力标尺) + +| 产品 | 单房间上限 | 备注 | +|---|---|---| +| **Telegram 群组** | **200,000** 成员(频道无限) | 十万级群**切换为拉取模型**;慢速模式间隔 10 s–1 h | +| **WhatsApp 群** | **2,048** 成员 | fanout = 2047,典型"纯扇出"上限 | +| **Discord** | 单频道 **100K+ 在线**;单 guild **25M 成员**(2025-09) | 1M 并发/guild(72 台 ScyllaDB 存万亿消息) | +| 国内 IM | 数百 → 两千量级 | 口径随产品变化,此处不列精确值 | + +### 2.2 为什么上限不是"人数"而是"扇出预算" + +**三种模型与各自的爆炸点**: + +| 模型 | 写放大 | 读放大 | 结论 | +|---|---|---|---| +| **纯扇出**(服务端逐人推送) | **极高**:20 万人群一条消息 = 20 万次写入 | 低 | **小群王道,大群自杀** | +| **纯拉取**(只存一份,各端按游标读) | 极轻 | **高**:20 万人同时上线打穿热点 | 实时性差,需长连接通知配合 | +| **混合(Telegram 实际做法)** | 小群扇出 / 大群拉取 | 中 | **推荐**:服务端只维护**消息时序 + 版本游标**,客户端按游标增量拉 | + +**两个必须算的放大点(附实际数字)**: + +1. **消息扇出**:20 万人 × 500 条/分钟 = **1 亿次推送/分钟** ⇒ 纯扇出不可能。 + Discord 口径:单频道 **30K 在线 × 10 msg/s = 30 万次"权限校验后的投递"/秒** —— 注意**权限检查(RBAC)是 CPU 热路径**。 +2. **在线状态(presence)是 N² 问题**:每人订阅所有可见成员的状态,每次变化扇出给所有订阅者。 + ⚠️ **算一下就发现它比消息更早爆**:1000 人房、每人每分钟变化一次 ⇒ `1000 × 1000 / 60` = **≈16,700 次/秒** —— **千人房就已经是热点**。 + ✅ 业界解法(Slack):**只订阅"当前可见成员列表"** ⇒ presence 流量降 **5 倍**。 + +### 2.3 关键工程机制(可直接照抄) + +| 机制 | 作用 | +|---|---| +| **pub/sub 聚合** | 一条消息**每个 relay/gateway 节点只推一次**,而不是每个接收者一次 —— 这是把 30,000 次推送降下来的关键 | +| **版本游标 + 增量拉取** | 客户端只拉游标之后的增量;翻历史才回溯 | +| **presence 收敛** | 订阅范围裁剪(只可见者)+ 批量合并 + 降频 + 最终一致 | +| **RBAC 缓存 + 版本化失效** | 权限检查在热路径 ⇒ 必须缓存,且要能失效 | +| **慢速模式(slow mode)** | 把限流产品化(大群必备) | +| **客户端侧** | 本地 SQLite 缓存、成员**懒加载**、消息合并/分片渲染(防界面卡死)、多设备靠 sequence 对齐 | +| **三平面分离** | 连接平面(gateway)/ 协调平面(房间进程)/ 存储平面(写重型库 + 搜索)各自独立扩展 | +| **一致性取舍** | **最终一致(1–2 s 窗口可接受)+ 房间内严格有序** | + +### 2.4 给我们的**分档建议**(回答"单房间上限") + +| 房间规模 | 架构要求 | 判据 | +|---|---|---| +| **≤ 100 人** | 纯扇出即可 | 无压力 | +| **100 – 2,000 人** | **纯扇出可行**,但必须:presence 合并 + 消息限频 + 权限缓存 | 千人房的 presence 已是热点(≈1.6 万次/秒) | +| **2,000 – 50,000 人** | **必须混合**:pub/sub 聚合 + 游标拉取 + presence 只推可见者 + 慢速模式 | 扇出成本随人数线性,聚合后按节点数而非人数 | +| **> 50,000 人** | **只能拉取模式**,公告/只读为主,presence 大幅弱化 | Telegram 20 万即此档 | + +> **建议把上限定义为"扇出预算"而不是人数**:先定"单节点每秒可承受的投递数",再由它反推房间人数上限 —— 这样上限可以随架构演进(加 gateway)而变大,而不是一个魔法数字。 + +### 2.5 我们场景特有的上限(**比技术扇出更早触顶**) + +- **agent 入群后,真正的放大点不是消息,而是"agent 之间的互相激发"**: + 一个房间若有 K 个 agent,且不加约束 ⇒ 消息量可指数增长。 +- ⇒ 必须按 **`agent 数 × 触发频率`** 单独设预算(每 agent 每 N 分钟最多 M 条 + 静默期 + **禁止 agent 直接触发 agent**)。 +- ⇒ 结论:**对我们而言,单房间的实际上限由"presence + agent 预算"决定,而不是由消息扇出决定** —— 后者在千人量级还远远不是瓶颈。 + +--- + +## 第三部分 · 未验证项(勿当结论) + +| # | 项 | 状态 | +|---|---|---| +| 1 | 上述游戏数值均为**行业资料口径**,非本环境实测 | ⚠️ 需按自建服实测校准 | +| 2 | 中继链路能否满足 **jitter < 20 ms**(比带宽更关键) | ⚠️ **未实测,且这是游戏可玩性的决定项** | +| 3 | 攻城战(数百人同屏)在本方案的压测结果 | ⚠️ 未做 | +| 4 | presence 在本方案下的实际收敛效果(5× 是否可达) | ⚠️ 未实测 | +| 5 | agent 参与的放大系数实测 | ⚠️ 未实测 | diff --git a/dsh-server-docs/04-调整方案/110-覆盖网络-答疑-群聊备份迁移保密.md b/dsh-server-docs/04-调整方案/110-覆盖网络-答疑-群聊备份迁移保密.md new file mode 100644 index 0000000..351bc43 --- /dev/null +++ b/dsh-server-docs/04-调整方案/110-覆盖网络-答疑-群聊备份迁移保密.md @@ -0,0 +1,220 @@ +# 110 · 覆盖网络 · 答疑-群聊备份迁移保密 +- 日期:2026-09-16 | 状态:📋 **规划态**(技术答疑稿;未实施) +- 来源:工作区根 `覆盖网络_答疑_群聊备份迁移保密_20260916.md`(正文见 附录 A) +- 层级:专项答疑(四问)| 承接档案 104;被 108(房间层)· 111 · 112(备份/保密)引用 +- 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +> **TL;DR** +> 四问四答:① **群聊 + agent 入群** = ✅ 可实现(群聊是**应用层**的事,覆盖网络只解决「可达」);② **备份** = **主备份优先对象存储**, +> 覆盖网络只当**搬运通道与第三副本**(P2P 副本无 SLA、可误删,**不适合当存档**);③ **迁移提速** = 按收益 7 条, +> **最大那一招是「不搬可重建的」**(46.3 MB vs 2.9 GiB ⇒ 约 64×);④ **保密** = 三层加密 + 元数据保护,**当前最大缺口是身份(共享令牌 → 一机一钥)**。 + +## 一、目标 + +回答四个具体问题(群聊与 agent 参与 / 服务器用户数据备份方案 / 迁移服务器速度优化 / 传输保密性),每问给出**可执行做法与判据**。 +可判定「做完了没有」= 四问各有明确结论 + 可落地手段 + 与现有平台的「现成度」判定。 + +## 二、只读前置 + +| # | 事实 | 核对方式(期望输出) | +|---|---|---| +| 1 | 平台**没有「房间」抽象**(现在是「每用户一个实例 + 会话」)⇒ 群聊 = 新增能力 | 读平台现状 / 档案 108 §2.1 | +| 2 | 备份基础已有:`backup.sh` + cron + `/opt/dsh/backups/` + 恢复演练 | 读 `scripts/` 与 `02-运维手册.md` | +| 3 | 不可再生 **46.3 MB** / 可重建 **2.9 GiB** | 备份口径实测记录 | +| 4 | 47→106 直连实测 **~22 KB/s**(46.3 MB 需 ~35 分钟) | 跨云实测记录 | +| 5 | 节点身份现为**共享 bearer**(无法吊销单台)⇒ 保密层最大缺口 | `src/worker/agent.ts` 头部自陈 | + +## 三、范围 + +- **改什么**:⏳ 未开跑。方案面 = 群聊房间层 + agent 成员类型 · 备份补「对象存储主层 + 只备不可再生」· 迁移补「多流并行 + 惰性迁移」· 身份换一机一钥 + E2EE。 +- **不动什么**:⛔ 官方 dsh 主程序(R2)|⛔ 本轮不动服务器、不改代码。 +- **明确不做**:⛔ 不用那条慢链路(22 KB/s)当备份/迁移通道 —— 备份上传应走**各自到公网/对象存储**的路径。 + +## 四、决策点 + +**已定** + +1. **群聊 = 应用层的事**,覆盖网络只提供「可达」,**不提供**「有序、去重、不丢」⇒ 群聊必须自带:消息 ID(内容寻址/哈希)· 因果/逻辑时钟 · 送达确认 + **离线补拉(拉取式)**· 房间级权限。 +2. **✅ 用户选:备份主层用对象存储**(自建 MinIO 或云 OSS/COS),**覆盖网络只当搬运通道与第三副本**。 +3. **只备不可再生数据**(+ 附一份重建清单)⇒ 体积降一个数量级。 +4. **上传前先加密**(服务端/对象存储不持有明文);**校验和 + 版本化 + 防误删**;**恢复演练自动化**。 +5. **传输保密 = 三层加密 + 元数据保护**,**一句话判据:中继只能看到密文与元数据,控制面只能看到密文与身份** —— 任何一条不满足即视为不合格。 +6. **agent 四条硬约束**:⛔ 禁止 agent 直接触发 agent(只有**人的消息**能触发)· 每轮发言预算 · 静默期 · 房间级全局速率上限 + 排队。 + +**未定**:群聊/agent 的具体成员类型与发言预算参数(M / N / 房间上限,需压测标定)。 + +## 五、步骤(每条自带一次验证) + +**A · 群聊与 agent** +1. 选分发拓扑(**推荐混合**:小群网状 / 大群区域汇聚 / 离线补拉)→ 验证:大群**禁止「每人每条广播给全体」**。 +2. 群聊自带四项(消息 ID / 逻辑时钟 / 送达确认 + 补拉 / 房间权限)→ 验证:去重与乱序场景可正确收敛。 +3. agent 作为**独立对等成员**(有自己的密钥与地址,身份绑定主人、权限可单独授)→ 验证:agent 四条硬约束在压测下生效。 + +**B · 备份** +4. 三层组合(本地快速恢复 / **对象存储主备份** / 网内第三副本)→ 验证:RTO 与不可变性达标。 +5. 只备不可再生 + 增量去重 + 上传前加密 → 验证:备份集体积降一个数量级。 +6. 恢复演练自动化 → 验证:演练通过。 +7. 备份走各自到对象存储的路径(**不走慢链路**)→ 验证:备份期间交互流量 p95 延迟不变。 + +**C · 迁移提速**(按收益排序) +8. 不搬可重建的(~64×,已在做)→ 9. 分片并行 + 多流 → 10. 先压缩再传 → 11. 增量/块级 diff → 12. 多路径并行 → 13. 惰性迁移 → 14. 经公网对象存储中转。**断点续传是前提**。 + +**D · 保密** +15. 三层加密(隧道层 / 应用层 E2EE / 静态层)→ 16. 一机一钥 + 密钥轮换吊销 + 群密钥轮换 + **校验控制面签名** → 17. 元数据保护(最小网络地图 / 不透明 ID / 隐私模式强制走中继)。 + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 群聊拓扑 | 已选一种(推荐混合)且说明取舍 | +| B | 备份主层 | **对象存储**为主;覆盖网络=通道+第三副本(非主备份) | +| C | 迁移 | 以**实测吞吐**为准,目标把 22 KB/s 提到链路可支持的量级 | +| D | 保密判据 | 「中继只见密文与元数据 / 控制面只见密文与身份」两条均满足 | +| E | 现成度透明 | §五 五条已判定(群聊❌需新建 / agent⚠️部分 / 备份✅基础已有 / 迁移⚠️部分 / 保密⚠️缺口在身份) | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- **执行期**:四块(群聊 / 备份 / 迁移 / 保密)互相独立,各自可回滚;⚠️ **备份改造**须保留旧路径直到恢复演练验证通过。 + +## 八、回报格式 + +执行会话回填:① 每步验证命令 + 实际输出 ② 群聊拓扑选型与理由 ③ 备份三层落点与恢复演练结果 ④ 迁移实测吞吐(与 22 KB/s 基线对比的倍数) ⑤ 加密三层各自的落地位置与判据验证 ⑥ commit ⑦ 未完成项与卡点。 + +## 九、未验证项 / 待办 + +群聊房间层的具体成员模型与发言预算参数(**待压测标定**)|E2EE 的实现路径(**需新增**)|多路径并行与惰性迁移的实际收益(**待评估**)|一机一钥迁移期间的兼容期处理(**待设计**)。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `覆盖网络_答疑_群聊备份迁移保密_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | 性质:**技术答疑**(承接 `覆盖网络_全球架构复盘_20260916.md`) +> 🟢 **范围**:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +--- + +## 一、群聊 + 「用户配置的 agent 也在群里互动」——✅ 可以实现 + +**关键判断**:群聊**不是覆盖网络的机制**,它是**应用层**的事。覆盖网络只解决"参与者散在各种网络里也能互相到达"——而这恰好是群聊最麻烦的那一半。所以两者是**互补**,不是一回事。 + +### 1.1 三种分发拓扑(必须选一种,推荐第三种) + +| 拓扑 | 优点 | 缺点 | +|---|---|---| +| 中心房间(消息过服务端) | 简单、天然全序、易持久化 | 中心带宽与单点;隐私面大 | +| 网状(成员间直连分发) | 省中心 | N²、顺序与送达确认难做 | +| **混合(推荐)** | 小群网状 / 大群走区域汇聚节点;离线补拉 | 实现复杂度最高,但可控 | + +### 1.2 覆盖网络给不了的,必须在应用层补 + +覆盖网络只提供"**可达**",**不提供**"有序、去重、不丢"。所以群聊必须自己带: + +1. **消息 ID**(内容寻址/哈希)⇒ 去重 +2. **因果/逻辑时钟** ⇒ 排序(无需全局时钟) +3. **送达确认 + 离线补拉**(**拉取式**,不是推送式) +4. **房间级权限**:加入房间才可见 —— 与"接入 ≠ 可见"一致 + +### 1.3 Agent 作为群成员的四个要点 + +- **身份**:agent 是一个**独立的对等成员**(有自己的密钥与地址),但**身份绑定其主人**、**权限可单独授**(可只读、可仅在被 @ 时发言)。 +- **运行位置决定数据面**:跑在用户自己机器上 ⇒ 消息不出去;跑在服务器 ⇒ 平台要路由给它。 +- ⚠️ **最大的坑 = agent 互相激发造成无限循环**(A 说 → B 回 → A 再说)。**必须内建四条硬约束**: + 1. **禁止 agent 直接触发 agent** —— 只有**人的消息**能触发 agent 发言(切断自激环); + 2. **每轮发言预算**(每个 agent 每 N 分钟最多 M 条); + 3. **静默期**(发言后冷却); + 4. **房间级全局速率上限** + 排队(多 agent 同时发言时按序,不刷屏)。 +- **风暴防护**:群聊是典型"推送放大点"(1 条消息 × N 成员)⇒ 大群**禁止"每人每条广播给全体"**,改"摘要比对 + 按需拉取"。 + +--- + +## 二、服务器用户数据备份 —— **主备份优先对象存储,覆盖网络只当搬运通道与第三副本** + +> 用户问「优先还是云存储方案」。**答案是分层组合,不是二选一**;但从"备份的本质指标"看,**主备份应当优先对象存储**。 + +### 2.1 三层组合(推荐) + +| 层 | 落点 | 作用 | 为什么 | +|---|---|---|---| +| **快速恢复层** | **本地盘** | 最近 N 份,恢复最快 | RTO 最短、零流量 | +| **主备份层** | **对象存储**(自建 MinIO 或云 OSS/COS) | 长期、异地、**不可变** | 备份的核心是**可恢复性 + 不可变**,对象存储天然给 SLA、版本化、生命周期 | +| **第三副本 / 通道** | **覆盖网络内的自有节点** | 异地冗余 + 搬运 | 零月费、跨地域;但**没有 SLA** | + +### 2.2 为什么"覆盖网络不适合当主备份" + +P2P/网内副本的根本弱点:**对端是否在线不由你控制**,没有 SLA、没有不可变、容易被误删或版本混乱。**它适合"搬运",不适合"存档"。** + +### 2.3 工程要点(决定成本与可用性) + +1. **只备不可再生数据**:已有实测口径 —— 不可再生 **46.3 MB**、可重建 **2.9 GiB** ⇒ **只备前者 + 附一份重建清单**,体积降一个数量级。 +2. **增量 + 内容寻址去重**(同一份只存一次)。 +3. **上传前先加密**(服务端/对象存储不持有明文)。 +4. **校验和 + 版本化 + 防误删**(对象存储的 lifecycle / 不可变桶)。 +5. **恢复演练自动化**(现有平台已有恢复演练先例,保持)。 +6. ⚠️ **别用那条慢链路当备份通道**:跨云实测 **22 KB/s** —— 备份上传应走**各自到公网/对象存储**的路径,而不是两地直连。 + +--- + +## 三、迁移服务器速度优化 + +**现状痛点**:47→106 直连实测 **~22 KB/s**(46.3 MB 需 ~35 分钟)。 + +**按收益排序的手段**: + +| 序 | 手段 | 收益 | +|---|---|---| +| 1 | **不搬可重建的**(只搬 46.3 MB,而非 2.9 GiB) | **~64×** —— 已在做,最大的那一招 | +| 2 | **分片并行 + 多流** | 单流受 BDP(带宽时延积)限制;多流才能吃满链路 —— 实测脚本已在用分片 | +| 3 | **先压缩再传** | 文本/JSON 常见 10:1 | +| 4 | **增量 / 块级 diff**(rsync 式或内容寻址) | 只传变化块 | +| 5 | **多路径并行**(直连 + 中继同时传) | 覆盖网络带来的新能力;⚠️ 需给中继留额度,别打满 | +| 6 | **惰性迁移**(内容寻址 + 按需拉取) | 把"前置全量"变成"用哪个拉哪个" —— 体验上最优 | +| 7 | **经公网对象存储中转** | 两地直连慢时,各自到云的带宽往往更快 | + +**断点续传是前提**(不追求一次传完;分块落盘、可续)。**验收**:以实测吞吐为准,目标把 22 KB/s 提到链路可支持的量级。 + +--- + +## 四、如何确保用户信息在覆盖网络传输中的保密性 + +### 4.1 三层加密(缺一层都不算保密) + +| 层 | 机制 | 防谁 | +|---|---|---| +| **隧道层** | WireGuard / Noise 端到端加密;**中继只转发密文、不解密** | 中间网络、中继运营者 | +| **应用层(E2EE)** | 消息在应用层再加一层;密钥只在成员间分发 | **连自己的控制面/中继也读不到内容** | +| **静态层** | 磁盘与备份加密(上云前先加密) | 存储侧泄露 | + +### 4.2 身份与密钥(当前最大的缺口) + +1. **一机一钥**替换共享令牌(现状是共享 bearer,无法吊销单台)。 +2. **密钥轮换与吊销**(会话密钥定期 rekey —— WireGuard 已有基础)。 +3. **群聊的群密钥轮换**:成员变更即轮换 ⇒ **前向保密**。 +4. **必须校验控制面签名**:否则可以下发假的网络地图(假身份)⇒ 中间人。 + +### 4.3 元数据保护(最容易忽略的一层) + +隧道只保护**内容**,控制面与中继仍能看到**谁连谁、何时、流量多大**。要减少暴露: + +- **最小网络地图**:只下发"你确实需要连接的"对端,不下发全网名单。 +- **不透明 ID**:中继侧不用真实用户名/主机名。 +- **隐私模式**:直连会**向对方暴露自己的真实 IP**(P2P 的固有代价)⇒ 需要隐私的流量**强制走中继**,不暴露 IP。 + +### 4.4 一句话判据 + +> **"中继只能看到密文与元数据,控制面只能看到密文与身份"** —— 任何一条不满足即视为不合格。 + +--- + +## 五、与现有平台的关系(这三件哪些是现成的) + +| 需求 | 现成度 | 说明 | +|---|---|---| +| 群聊 | ❌ **需要新建** | 平台现在是"每用户一个实例 + 会话",**没有"房间"抽象** ⇒ 这是新增能力,不是开关 | +| Agent 入群 | ⚠️ 部分 | agent 能力有,但"作为群成员"需新增成员类型 + 发言预算机制 | +| 备份 | ✅ **基础已有** | `backup.sh` + cron + `/opt/dsh/backups/` + 恢复演练;需补"对象存储 + 只备不可再生" | +| 迁移提速 | ⚠️ 部分 | 分片已在用;缺多流并行、惰性迁移 | +| 传输保密 | ⚠️ **缺口在身份** | 隧道加密已有;**共享令牌 ⇒ 一机一钥**是硬前置;E2EE 需新增 | diff --git a/dsh-server-docs/04-调整方案/111-覆盖网络-补遗与参考方案.md b/dsh-server-docs/04-调整方案/111-覆盖网络-补遗与参考方案.md new file mode 100644 index 0000000..cf6aa1f --- /dev/null +++ b/dsh-server-docs/04-调整方案/111-覆盖网络-补遗与参考方案.md @@ -0,0 +1,250 @@ +# 111 · 覆盖网络 · 补遗与参考方案 +- 日期:2026-09-16 | 状态:📋 **规划态**(补遗复盘稿;未实施) +- 来源:工作区根 `覆盖网络_补遗与参考方案_20260916.md`(正文见 附录 A) +- 层级:专项补遗| 承接档案 104 · 110;被 108(游戏判定修正)引用 +- 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +> **TL;DR** +> 四部分:① **互联游戏可行性**(✅ 支持,但**由游戏形态决定**;优先做「**只传输入**」的锁步/回合制); +> ② **补遗 24 条**(身份与账户 / 寻址与名字 / 接入与可见性 / 自检与选路 / 流量与公平 / 移动端弱网 / 升级版本自愈 / 可观测); +> ③ **参考方案对照**(10 个能力域的现成物,**别自研**);④ **反模式 12 条**(踩了就出事,逐条对照)。 +> ⭐ 最划算的一处架构复用:**群聊房间与游戏对局是同一个模型** ⇒ 一次建房间层,群聊 + 游戏 + 协作 + 看板共用。 + +## 一、目标 + +补齐前面各档案未覆盖的项(24 条)+ 给出可借鉴的现成物清单 + 反模式清单,并回答「互联游戏是否可行」。 +可判定「做完了没有」= 四部分齐备,且**补遗 24 条每条都能落到一个能力域**。 + +## 二、只读前置 + +| # | 事实 | 核对方式(期望输出) | +|---|---|---| +| 1 | 各档案已有明确分工(见 §三 表格「已有明确分工」) | 档案 104 §1–§5(五层 / 12 特性 / 流量)· §四(风暴)· §五(流量组织) | +| 2 | ⚠️ 各档案**已有明确分工**,本档只补缺 | 逐条比对 104 / 105 / 106 / 107 / 108 / 109 / 110 | +| 3 | 平台已有域名 `alotbuy.com` ⇒ 可做子域解析(MagicDNS 式) | 读 `01-规划与架构.md` 域名接入 | +| 4 | 各档案**均有未验证项清单**(本档不重复) | 档案 104 §九 · 106 §九 · 107 §六 · 109 第三部分 | +| 5 | ⛔ 「平台已有 / 已存在」**未被核实前不得作安全假设** | 本档 §二 自检要求 | + +## 三、范围 + +- **改什么**:⏳ 未开跑。本档为**补遗 + 参考方案 + 反模式**,不含实施。 +- **不动什么**:⛔ 不重复各档案已有内容(见 §四 表格);⛔ 本轮不动服务器、不改代码。 +- **统一记录格式**(本档所有补遗项按此):**分类 / 结论 / 依据 / 待验证点 / 若做需要什么**。 + +## 四、决策点 + +**已定** + +1. **互联游戏 ✅ 支持,但由游戏形态决定**:回合制/卡牌/桌游/异步 ✅非常合适;小规模实时合作(≤8–16 人)✅合适;大厅在服务器 + 对局 P2P ✅经典;**大规模强实时竞技(FPS/MOBA 64+)❌不合适**(需专用服务端 + 中继多一跳 + P2P 无法反作弊)。 +2. **给覆盖网络的第一建议:优先做「只传输入」的锁步/回合制**(带宽可忽略、延迟容忍度高);实时动作类必须限定在同区域。 +3. **⛔ P2P 无法防作弊** ⇒ 凡有竞技性就必须**服务端权威**(好消息:有公网 IP 的节点天然可当对局主机/专用服务端 —— 与骨干层天然衔接)。 +4. **⭐ 复用「房间」抽象**:群聊房间与游戏对局是**同一个模型**(成员/可见性/事件分发/离线补拉)⇒ 一次投资四处共用。 +5. **落地优先级(补遗之后按依赖排)**:① 房间层 ② 身份与密钥 ③ **会合/中继拆成独立组件**(老结论,仍是第一件实事)④ IPv6 优先 + 上线自检 + 路径决策日志 ⑤ 配额与优先级队列 ⑥ 备份改造 ⑦ 游戏(锁步/回合制先行)。 +6. **反模式 12 条为硬拦项**:建全互联 · 无扇出限制的 gossip · 客户端持有权威状态 · 控制面下发全网名单 · 单中心中继当唯一通道 · 网内副本当主备份 · 用慢链路做备份/迁移 · 失败即重试 · agent 直接触发 agent · 推送式分发 · 共享密钥当节点身份 · 只按 IPv4 NAT 设计。 + +**未定**:本环境 IPv6 可用度(决定能否吃到「直达」红利,**未实测**)。 + +## 五、步骤 + +**本档为补遗,实施步骤已被下列档案承担**: +- 房间层 → **档案 108 §五 第 2 步**(组队/行会/频道) +- 身份与密钥 → **档案 112 §9**(协议治理同批)与 **110 §D**(一机一钥) +- 会合/中继拆组件 → **档案 105 §五 第 1 步**(本线第一件实事,见 `接续入口 §2.5`) +- IPv6 / 上线自检 / 决策日志 → **档案 109 §1.4**(数值依据)与 **112 §4**(jitter 选路) +- 配额与优先级队列 → **档案 112 §5**(备份抖动窗口 + 低优先级队列) +- 备份改造 → **档案 110 §B** +- 游戏 → **档案 108 §五**(锁步/回合制先行) + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 补遗 24 条 | 每条有归属能力域,且**不与既有档案重复** | +| B | 参考方案对照 | 10 个能力域各给出可借鉴的现成物与「借什么」 | +| C | 反模式 12 条 | 逐条可对照,且**每条都指向一个具体后果** | +| D | 落地优先级 | 7 条按**依赖**排(不是按收益) | +| E | 未验证项透明 | §六 四条已列全 | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- **执行期**:所引用的各档案步骤各自独立可回滚;⛔ **「客户端持有权威状态」不可回滚**(红线,见 §四 第 3 条)。 + +## 八、回报格式 + +执行会话回填:① 补遗 24 条中实际被采纳的条数与落点 ② 参考方案的选用结果(谁被选中、为什么) ③ 反模式自查结果(逐条对照,命中项与处置) ④ commit ⑤ 未完成项与卡点。 + +## 九、未验证项(勿当结论) + +本环境 IPv6 可用度(决定能否吃到「直达」红利,**未实测**)|移动端休眠唤醒后的实际重连耗时(**未实测**)|WebRTC DataChannel 经我们中继的延迟与丢包表现(**未实测**)|FEC / 多路径的实际收益(**待评估**)。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `覆盖网络_补遗与参考方案_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | 性质:**补遗复盘**(承接 `覆盖网络_全球架构复盘_20260916.md` 与 `覆盖网络_答疑_群聊备份迁移保密_20260916.md`) +> 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +--- + +## 一、互联游戏:✅ 支持,但**由游戏形态决定** + +覆盖网络对游戏是"够用"的底座,**但它是所有应用场景里最"重"的一个** —— 实时性、状态一致性、反作弊三条同时压上来。所以先分类: + +| 游戏类型 | 覆盖网络可行性 | 关键约束 | +|---|---|---| +| 回合制 / 卡牌 / 桌游 / 异步 | ✅ **非常合适** | 带宽极小(只传输入),延迟不敏感 | +| 小规模实时合作(≤8–16 人) | ✅ 合适 | 需要主机或专用服务端之一 | +| 大厅在服务器 + 对局 P2P | ✅ 经典架构 | 匹配/排行在中心,对局在 P2P | +| 大规模强实时竞技(FPS/MOBA 64+) | ❌ **不合适** | 需专用服务端 + 权威模拟;中继多一跳;P2P 无法反作弊 | +| 需要严格反作弊的竞技类 | ❌ **P2P 的致命伤** | **客户端持有权威状态 = 可作弊**,必须服务端权威 | + +### 1.1 三种同步模型(带宽与延迟特性完全不同) + +| 模型 | 传什么 | 带宽 | 适合 | +|---|---|---|---| +| **状态同步** | 定期广播状态快照 + 客户端插值 | 高(随人数上升) | 动作类、小规模 | +| **锁步 / 帧同步** | **只传输入(命令)** | **极低** | RTS、回合、卡牌 —— **对覆盖网络最友好** | +| **回滚码(GGPO 式)** | 输入 + 确定性模拟 + 预测回滚 | 低但要求严格 | 格斗类;**对延迟最敏感,跨洲不可行** | + +⇒ **给覆盖网络的第一建议:优先做"只传输入"的锁步/回合制**,带宽可忽略、延迟容忍度高;实时动作类必须限定在同区域。 + +### 1.2 延迟预算(决定哪些能玩) + +| 路径 | 典型 RTT | 可承载 | +|---|---|---| +| 同区域直连 | 5–30 ms | 几乎任何类型 | +| **经中继(多一跳)** | +RTT×2 | 回合/锁步仍可;动作类吃力 | +| 跨洲 | ~200 ms | **只适合回合制/异步** | + +### 1.3 游戏特有的风暴点(比聊天更危险) + +1. **状态广播放大**:每帧每人发给全体 = O(N²) ⇒ 必须**主机聚合后再分发**,或按**兴趣区域(AOI)裁剪**。 + > 📄 **重点修正(2026-09-16 10:0x)**:用户明确游戏重点是 **MMORPG(2D/2.5D)· MUD · 传奇类** —— 这三类是**覆盖网络最匹配的应用**(天生服务端权威 + tick 驱动 + **AOI 九宫格广播** + 分区/分线扩展,每玩家仅数 KB/s~数十 KB/s,几百 ms 延迟无感)。本节上面那张"❌ 不合适"的表**只适用于 3D 大世界强实时竞技**。游戏专项见 **`覆盖网络_游戏专项_MMORPG与MUD_20260916.md`**。 + ⭐ 该专稿的核心简化:**这类游戏玩家之间不需要互联**(服务端权威,玩家只与游戏服通信)⇒ 覆盖网络只需解决"**让玩家到达游戏服**",**中继容量按"服数"算、不按"玩家数"算**。 +2. **输入风暴**:锁步必须限帧率 + 合并输入,不能"每动一下发一条"。 +3. **主机切换惊群**:房主掉线时全员抢当主机 ⇒ **必须确定性继任顺序 + 退避**(不能"谁先喊谁当")。 +4. **匹配/大厅风暴**:开房高峰的列表刷新 ⇒ 列表走**带 TTL 的拉取**,不做推送。 + +### 1.4 反作弊(决定架构,不是可选) + +**P2P 无法防作弊** ⇒ 只要游戏有竞技性,就必须 **服务端权威**。好消息:覆盖网络里"**有公网 IP 的节点**"天然可当对局主机/专用服务端 —— 与骨干层设计天然衔接。 + +### 1.5 技术选型与复用点 + +- 传输:**WebRTC DataChannel 的"不可靠 + 无序"模式**(类 UDP,适合状态流);或直接用覆盖网络的 UDP 隧道。WebRTC 自带 ICE(打洞)+ TURN(中继)兜底,与我们的中继设计同构。 +- ⭐ **可复用"房间"抽象**:**群聊房间与游戏对局是同一个模型** —— 成员 / 可见性 / 事件分发 / 离线补拉。一旦建了房间层,**群聊、游戏、协作编辑、看板共用一次投资**。这是本方案最划算的一处架构复用。 + +--- + +## 二、补遗清单(按主题;凡前面没写到的都在这) + +### 2.1 身份与账户(**最容易被漏,且漏了会出运维灾难**) + +1. **多设备同账号**:一个用户多台设备如何归属同一身份;设备加入/移除流程。 +2. **密钥丢失的重建路径** ⚠️:私钥丢 = 设备永久失去身份。必须有**恢复机制**(恢复码 / 管理员重签 / 设备转让),且要能撤销被盗设备。 +3. **密钥存放**:用系统密钥库(Windows DPAPI / macOS Keychain / Linux TPM),不要明文落盘。 +4. **账户与设备的绑定粒度**:设备级身份 + 用户级授权(两层),避免"一台设备泄露 = 整个账号沦陷"。 + +### 2.2 寻址与名字(没有它,用户只能记 IP) + +5. **稳定名字解析**(MagicDNS 式):`<设备>.<用户>.<域名>`;平台已有 `alotbuy.com`,可直接做子域解析。 +6. **IPv6 优先** ⚠️ **重要且常被忽略**:不少网络有 IPv6 直达能力 ⇒ **可跳过打洞直接连**。别只按 IPv4 NAT 设计,否则白丢一大块性能红利。 + +### 2.3 接入与可见性 + +7. **出口节点 / 子网路由**:把某台机器背后的**整个局域网**借进覆盖网络(访问家里的 NAS、打印机)—— 对"一个人的多设备"场景是关键能力。 +8. **服务暴露**:把实例或某端口按**网内可见 / 公网可见**两档暴露(对应 Serve / Funnel 的区分)。 +9. **ACL 的具体形态**:粒度(用户 / 设备 / 服务 / 端口 / 时间)、表达方式(策略语言)、下发与缓存、**默认拒绝**。 + +### 2.4 自检与选路 + +10. **上线自检**(netcheck 式):探测 UDP 是否被封、NAT 类型、到各区域中继的时延 ⇒ 再决定选路。 +11. **路径决策可解释**:每次连接"为什么走了中继"要能查出原因(打洞失败?UDP 被封?策略强制?)—— 排障只能靠这个。 +12. **节点健康自评**:打洞率 / 丢包 / 时延 → 主动换路径或换骨干。 + +### 2.5 流量与公平 + +13. **按用户/设备配额**(带宽与连接数),防单点占满。 +14. **交互流量优先于后台流量**:备份/同步这类用**低优先级队列**(fq_codel / LEDBAT 类),保证聊天与游戏不被备份堵死。 +15. **多路径**:直连 + 中继同时传,聚合吞吐(大文件迁移用)。 +16. **前向纠错(FEC)**:丢包高的移动网,FEC 比"重传"便宜得多。 + +### 2.6 移动端与弱网(独立一章,坑最多) + +17. **电量**:心跳频率要能与电量/前台状态联动(后台降频)。 +18. **系统休眠/冻结**:唤醒后必须**秒级重连**,不能等下一个心跳周期。 +19. **网络切换**:Wi-Fi ↔ 蜂窝切换会换 IP ⇒ 需**连接迁移**(QUIC 的 connection migration 就是为这个设计的)。 + +### 2.7 升级、版本与自愈 + +20. **协议版本协商**:客户端与平台必须能协商协议版本,**严格递增防降级**。 +21. **灰度与回滚**:按节点分批升级,出问题能退回上一版。 +22. **更新包签名校验**(防投毒)。 + +### 2.8 可观测 + +23. **集中指标 + 每节点画像**(路径类型 / 打洞率 / 时延 / 重连次数)。 +24. **可 grep 的决策日志**("为什么走中继")—— 与 12 配套。 + +--- + +## 三、参考方案对照(可直接借鉴的现成物) + +| 能力域 | 参考方案 | 借什么 | +|---|---|---| +| 组网 / 打洞 / 中继 | **Tailscale / headscale + derper**、NetBird、Nebula、ZeroTier、EasyTier、innernet | 控制面/数据面分离;先中继后直连;限额中继;区域 DERP | +| 打洞 / 中继库 | **libp2p**(DCUtR + relay v2)、**Pion**(Go WebRTC)、**coturn** | 直接可用的协议实现与默认限流参数 | +| 游戏网络 | **GGPO / 回滚码**、**Nakama**(开源游戏后端)、Colyseus、Photon、**WebRTC DataChannel** | 房间/匹配/状态同步的现成模型;不可靠传输 | +| 联机传输库 | enet / KCP / QUIC | 类 UDP 的低延迟可靠传输 | +| 协作编辑 / CRDT | **Yjs**、Automerge | 无中心也一致的协作模型(适合 P2P 房间) | +| 群聊 / 联邦房间 | **Matrix**(联邦式房间,理念与覆盖网络最接近)、Nostr、Scuttlebutt | 房间、事件图、离线补拉、联邦 | +| 备份 | **restic / Borg**(增量 + 去重 + 加密)、**rclone**(多后端 + 加密)、MinIO | **与我们结论一致**:去重 + 客户端加密 + 不可变 | +| 迁移 | rsync(块级增量)、rclone、对象存储中转 | 断点续传与增量 | +| 观测 | Prometheus + Grafana(libp2p 有现成面板)、集中日志 | 直接抄面板 | +| 全球就近 | GeoDNS(PowerDNS / Route53)、anycast、DERP 的区域模型 | 就近接入 | + +--- + +## 四、反模式清单(踩了就出事,逐条对照) + +| # | 反模式 | 后果 | +|---|---|---| +| 1 | **建全互联**(N² 保活) | 保活与连接数爆炸 | +| 2 | **无扇出限制的 gossip / 广播** | 泛洪风暴 | +| 3 | **客户端持有权威状态** | 可作弊、可伪造归属 | +| 4 | **控制面下发全网名单** | 元数据全暴露 + 每条连接都要维护 | +| 5 | **单中心中继当唯一通道** | 单点 + 带宽瓶颈 | +| 6 | **把网内副本当主备份** | 无 SLA、可误删、对端离线即失效 | +| 7 | **用慢链路做备份/迁移通道** | 22 KB/s 量级 ⇒ 不可用 | +| 8 | **失败即重试(无退避/抖动)** | 重试风暴 | +| 9 | **agent 直接触发 agent** | 无限循环消息风暴 | +| 10 | **推送式分发(版本/目录/大资源)** | 冷启动拉取风暴 | +| 11 | **共享密钥当节点身份** | 无法吊销、一泄全通 | +| 12 | **只按 IPv4 NAT 设计** | 白丢 IPv6 直达红利 | + +--- + +## 五、落地优先级(补遗之后,按"依赖"排) + +1. **房间层**(一次投资,群聊 + 游戏 + 协作 + 看板共用)。 +2. **身份与密钥**(一机一钥 + 恢复机制 + 吊销)—— 大量能力的共同前置。 +3. **会合 / 中继拆成独立组件**(老结论,仍是第一件实事)。 +4. **IPv6 优先 + 上线自检 + 路径决策日志**(低成本高收益)。 +5. **配额与优先级队列**(交互优先,备份让路)。 +6. 备份改造(去重 + 客户端加密 + 对象存储主层)。 +7. 游戏(锁步/回合制先行,服务端权威留给竞技类)。 + +--- + +## 六、未验证项 + +| # | 项 | 状态 | +|---|---|---| +| 1 | 本环境 IPv6 可用度(决定能否吃到"直达"红利) | ⚠️ 未实测 | +| 2 | 移动端休眠唤醒后的实际重连耗时 | ⚠️ 未实测 | +| 3 | WebRTC DataChannel 经我们中继的延迟与丢包表现 | ⚠️ 未实测 | +| 4 | FEC / 多路径的实际收益 | 📋 待评估 | diff --git a/dsh-server-docs/04-调整方案/112-覆盖网络-九大瓶颈落地方案.md b/dsh-server-docs/04-调整方案/112-覆盖网络-九大瓶颈落地方案.md new file mode 100644 index 0000000..f4ab738 --- /dev/null +++ b/dsh-server-docs/04-调整方案/112-覆盖网络-九大瓶颈落地方案.md @@ -0,0 +1,281 @@ +# 112 · 覆盖网络 · 九大瓶颈落地方案 +- 日期:2026-09-16 | 状态:📋 **规划态 / 未实施**(落地解决方案稿) +- 来源:工作区根 `覆盖网络_瓶颈落地方案_20260916.md`(正文见 附录 A) +- 层级:专项落地(**瓶颈 → 可执行做法**)| 承接档案 **107 §4**(瓶颈排序);被 104 §8 落地顺序引用 +- 参考来源:Slack 官方 API 文档 · Microsoft SCCM / BranchCache / Delivery Optimization 官方文档 · presence 系统工程实践 +- 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +> **TL;DR** +> 把 107 §4 排出的**九大瓶颈**逐个给成**可执行做法 + 验收判据**(含 Slack / SCCM 官方照抄点)。 +> 🎯 **如果只做三件事:presence 改造 + 游戏服放 L1 + 块级内容寻址分发** —— 覆盖最大的三个瓶颈,且**都不需要改传输协议**。 +> 🔑 两个"零成本/低成本高收益"点:**游戏服部署规范(零成本,直接消掉 600 Mbps)**;**presence 改造(唯一第一瓶颈,纯应用层,不动协议)**。 + +## 一、目标 + +把九大瓶颈(presence / 游戏服放家宽 / 首屏包冷启动 / 中继抖动 / 备份窗口挤占 / 重连风暴 / agent 自激 / NAT 表溢出 / 版本碎片)逐条转成**可执行做法 + 验收判据 + 成本评级**。 +可判定「做完了没有」= 九条齐备,且**每条都有可复现的验收判据**(不是"感觉好了")。 + +## 二、只读前置 + +| # | 事实 | 核对方式(期望输出) | +|---|---|---| +| 1 | 首屏包 **10.8 GB/次**(1000 台口径)是 #3 的量级来源 | 实测 `11,363,655 B` × 1000(档案 97 / 107 §0.3) | +| 2 | 游戏服放家宽 ⇒ 中继需要 **600 Mbps 常驻** | 档案 107 §S3(300 × 10 KB/s = 24 Mbps/服 × 25 服) | +| 3 | presence 是 1000 台下的**第一瓶颈**(8.2k–16.7k 次/秒) | 档案 107 §S2 / §3 / §4 | +| 4 | 平台已有 **ETag / 304 短路**能力(内容分发的现成基础) | 档案 97 | +| 5 | 平台已有**崩溃熔断 + 冷却**先例(#6 重连治理可复用同一套机制) | 档案 78 | + +## 三、范围 + +- **改什么**:⏳ 未开跑。方案面 = presence 应用层改造 · 游戏服部署规范 · 内容分发三件套 · 中继抖动选路 · 备份窗口治理 · 重连治理 · agent 硬约束 · 每子网打洞并发上限 · 协议版本治理。 +- **不动什么**:⛔ 官方 dsh 主程序(R2)|⛔ **不改传输协议**("只做三件事"的硬前提)|⛔ 本轮不动服务器、不改代码。 + +## 四、决策点 + +**已定** + +1. **🎯 只做三件事 = presence 改造 + 游戏服放 L1 + 块级内容寻址分发**(覆盖最大三个瓶颈,且都不需要改传输协议)。 +2. **游戏服部署规范 = 游戏服一律部署在有公网 IP 的节点上**(零成本,收益最大)⇒ 服主在 NAT 后时**主动拨出到骨干、玩家连骨干入口**(不是直连服主)。 +3. **必须做「块级 + 内容寻址」,⛔ 不要做「包级」** —— 包级(Peer Cache 式)的坑:必须完整下载完才能当 peer 源,版本一变所有 peer 源失效 ⇒ **这正是「版本一发就全量重拉」的风暴成因**。 +4. **✅ 用户已定:presence 改造走 Slack 官方做法**(`presence_sub` + `batch_presence_aware`:订阅式扇出 + 只推给"正在看的人" + 本地批合并 + 绑连接生命周期)。 +5. **⛔ 禁止 agent 直接触发 agent**(只有人的消息能触发)—— 唯一能真正切断指数增长的规则。 +6. **明确使用最终一致**(presence 允许 5–15 s 陈旧;⛔ **不要为 presence 上强一致**)。 +7. **落地顺序按「收益 ÷ 成本」排**(见 §五)。 + +**未定**:agent 限额参数(M / N / 房间上限)取值 —— **需压测标定**。 + +## 五、步骤(§落地顺序,按「收益 ÷ 成本」;每步自带一次验证) + +1. **presence 改造**(七条落地做法)→ 验证:1000 人大房广播**从 ~16,700/s 降到 <2,000/s**;进房间首屏 presence **一次 bulk 请求**完成(无 N+1)。 +2. **游戏服部署规范(放 L1)** → 验证:新开服默认落 L1;中继出口带宽与"服数"的关系**可预测**。 +3. **内容分发:块级内容寻址 + 同网段 peer**(一次投资治 #3、#5、#9)→ 验证:版本发布时回源字节数 ≈ **1 份 × 组数**(不是 1000 份)。 +4. **重连治理**(指数退避 + 全抖动 + 重试预算 + 令牌桶)→ 验证:拔掉一台中继后 1000 台重连曲线**平滑爬升**,不是尖峰。 +5. **备份抖动窗口 + 低优先级队列** → 验证:备份进行期间聊天与游戏的 **p95 延迟不变**。 +6. **jitter 度量与选路**(按 jitter 排序,**不按 RTT 排序**;中继侧 fq_codel/SQM)→ 验证:每连接 jitter 直方图;超阈值自动切路径并告警。 +7. **agent 配额 + 硬约束** → 验证:注入「回声型 agent」压测,房间消息量**有上限、不增长**。 +8. **每子网打洞并发上限 + 收敛探测** → 验证:同一办公室 **20 台同时上线**,NAT 不丢线、其他网络不受影响。 +9. **协议版本治理**(协商 + 灰度 1%→10%→100% + 相邻版本互通 + 内容寻址版本包)→ 验证:各版本节点数与错误率**按版本切分**可观测。 + +## 六、验收 + +| # | 口径 | 期望 | +|---|---|---| +| A | 九条各有判据 | 每条给出「可复现的验收判据」(本档各节末「验收判据」) | +| B | presence | <2,000/s(原 ~16,700/s);首屏 presence 一次 bulk | +| C | 游戏 | 新开服默认落 L1;中继出口带宽与服数**可预测**(不随玩家数漂移) | +| D | 内容分发 | 回源字节 ≈ 1 份 × 组数;局域网内多台设备只回源一次 | +| E | 中继 | 利用率留 **30%+ 余量**;每连接 jitter 直方图可观测 | +| F | 备份 | 备份期间交互流量 p95 延迟不变 | +| G | agent | 回声型 agent 压测下消息量有上限 | +| H | 未验证项透明 | §未验证项 五条已列全 | + +## 七、回滚 + +- **本档自身**:零改动 ⇒ 无回滚需要。 +- **执行期**:九步各自独立可回滚(均为应用层参数/规范/开关,**不涉及传输协议变更**)⇒ 回滚即还原参数。 +- ⚠️ 第 3 步(内容分发)与第 9 步(版本包)**共用一套分发机制** ⇒ 回滚须成对评估。 + +## 八、回报格式 + +执行会话回填:① 每步验证命令 + 实际输出(**必须含本档各节的验收判据**) ② presence 收敛实际降幅 ③ 同网段 peer 命中率 ④ fq_codel 实际效果 ⑤ agent 限额参数标定值 ⑥ commit ⑦ 未完成项与卡点。 + +## 九、未验证项(勿当结论) + +presence 收敛的实际降幅(业界口径可达 **5×–8×**,**需实测**)|中继链路的 **jitter 分布**(决定能否支撑游戏,**最该先测**)|同网段 peer 命中率(决定 10.8 GB 能压到多少,**需实测**)|**fq_codel 在本环境中继上的实际效果**(需实测)|agent 限额参数(M / N / 房间上限)取值(**需压测标定**)。 + +--- + +## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) + +> 以下为工作区根 `覆盖网络_瓶颈落地方案_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), +> 其余**一字未改**;本档的可判定部分以上方 8 段为准。 + +> 日期:2026-09-16 | 性质:**落地解决方案**(承接 `覆盖网络_千台全场景推演_20260916.md` 的瓶颈排序) +> 参考来源:Slack 官方 API 文档、Microsoft SCCM / BranchCache / Delivery Optimization 官方文档、presence 系统工程实践(详见各节"参考实现") +> 🟢 范围:只考虑技术实现;跨境数据合规由使用者自行考虑。 + +--- + +## 总览:九个瓶颈 × 落地手段 + +| # | 瓶颈 | 量级 | 核心手段 | 成本 | +|---|---|---|---|---| +| 1 | **presence** | 8.2k–16.7k 次/秒 | **订阅式扇出 + 本地批合并 + 绑连接生命周期** | 低(纯应用层) | +| 2 | **游戏服放家宽** | 600 Mbps 常驻 | **部署规范:游戏服一律放有公网 IP 的节点** | **零** | +| 3 | **首屏包冷启动** | 10.8 GB/次 | **块级内容寻址 + 同网段 peer 优先** | 中 | +| 4 | **中继抖动** | 需 <20 ms | **按抖动选路 + 中继限载 + fq_codel** | 中 | +| 5 | 备份窗口挤占 | 136 Mbps | **抖动窗口 + 低优先级队列** | 低 | +| 6 | 重连风暴 | 160 / 1000 并发 | **全抖动退避 + 重试预算 + 令牌桶** | 低 | +| 7 | agent 自激 | 指数级 | **禁止 agent 触发 agent + 独立配额** | 低 | +| 8 | NAT 表溢出 | 整屋掉线 | **每子网打洞并发上限 + 收敛探测** | 低 | +| 9 | 版本碎片 | — | **协议协商 + 灰度 + 内容寻址版本包** | 中 | + +--- + +## 1. presence(最高优先,收益/成本比最好) + +### 落地做法(七条,均有成熟先例) + +1. **presence 绑到连接生命周期,不要轮询** —— WebSocket 连上 = 在线、断开 = 离线;**存储带 TTL 只作安全网**(防网关崩溃漏事件)。彻底干掉"每 30 s 全员轮询"。 +2. **本地批合并 + pipeline 刷写** —— 每个网关把本地心跳攒起来,**每 1 s 一次 pipeline 提交**。 + 业界的量级对照:10 万连接 × 0.2 心跳/s = **2 万条命令/秒** ⇒ 合并后变成 **1 次 pipeline/秒**(数量级差异)。 +3. **订阅式扇出:只推给"正在看的人"** —— 用户打开某个聊天/名单才订阅该用户的 presence,**订阅只活在连接期间**。 + 这是 **Slack 官方做法**(`presence_sub` + `batch_presence_aware`),也是它们把 presence 流量降下来的关键。 +4. **批量事件 + 节流** —— 一条消息里带 **user 数组**(不是逐个 user);**最多每几秒推一批**。 +5. **grace period 5–15 s + 离线 debounce 30 s** —— 防止"网络抖一下 = 状态闪烁",把短暂断连合并掉。 +6. **多设备按 device 聚合** —— 任一设备在线即在线;**重连后必须重新拉一次全量**(否则状态陈旧)。 +7. **明确使用最终一致** —— 允许 5–15 s 陈旧。⛔ **不要为 presence 上强一致**(会毁掉吞吐,且业务上不需要)。 + +### 大房(≥1000 人)的特殊策略 + +- 只推 **在线 / 离线**(不推 idle、不推 typing);**按百分比抽样降频**(如每 10 s 一轮); +- 打开房间用 **一次 bulk 查询**拿全量,之后只增量。 + +### 参考实现 +Slack 官方 changelog(batch presence + presence subscriptions)、Redis TTL + pub/sub 的 presence 标准设计、WebSocket 生命周期作为 presence 信号。 + +### 验收判据 +- 1000 人大房的 presence 广播次数 **从 ~16,700/s 降到 <2,000/s**; +- 进房间首屏 presence **一次 bulk 请求**完成(无 N+1)。 + +--- + +## 2. 游戏服放哪(**零成本,收益最大**) + +### 落地做法 + +1. **部署规范:游戏服一律部署在有公网 IP 的节点上**(= 骨干层)⇒ 玩家直连,**中继承载 0**。 +2. 服主确实在 NAT 后时:**服主动拨出到骨干**,**玩家连骨干入口**(不是直连服主)—— 把中继点从"服主机器"搬到"骨干",并让骨干做流量聚合。 +3. **错峰 + 配额**:攻城战高峰用**按服限额**,并提前公告时段。 +4. 容量按 **45% 设计、55% 留余量**;骨干池 **≥ N+1**。 + +### 验收判据 +- 新开服默认落 L1; +- **中继出口带宽与"服数"的关系可预测**(而不是随玩家数漂移)。 + +--- + +## 3. 首屏包冷启动(10.8 GB)—— 照抄内容分发三件套 + +### 落地做法(**直接照搬 SCCM 的内容源优先级**) + +1. **内容源优先级**(改成我们的版本): + **本地磁盘 → 同局域网 peer → 同区域边缘缓存 → 区域分发点 → 公网源** + (原版优先级顺序见 Microsoft 官方文档,结构一致) +2. **必须做"块级 + 内容寻址",不要做"包级"** —— 这是 **BranchCache vs Peer Cache** 的关键分水岭: + - **块级(BranchCache 式)**:按**哈希标识块**、**与文件无关** ⇒ **只拿到一部分也能开始共享**;内容更新时**只传变化的块**; + - ⚠️ **包级(Peer Cache 式)的坑**:必须**完整下载完**才能作为 peer 源;**版本一变所有 peer 源全部失效**,客户端会集体回源 ⇒ **这正是"版本一发就全量重拉"的风暴成因**。 +3. **客户端校验哈希**,不匹配就丢弃(Delivery Optimization 的做法)。 +4. **分组**:按"用户 / 团队 / 局域网"分组共享(对应 DO 的 group mode),避免跨组乱穿透。 +5. **同网段优先广播发现**(BranchCache 在子网内广播哈希找 peer)。 +6. 已加载走 **304**(平台已有此能力)。 + +### 验收判据 +**版本发布时回源字节数 ≈ 1 份 × 组数**(而不是 1000 份);局域网内多台设备只回源一次。 + +--- + +## 4. 中继抖动(游戏可玩性的真正门槛) + +### 落地做法 + +1. **把 jitter 做成一等指标** —— 持续采样 RTT 与 **jitter(RTT 方差)**,**选路按 jitter 排序,不按 RTT 排序**。 +2. **抑制 bufferbloat** —— 中继侧启用 **fq_codel / SQM** 类队列管理;排队延迟是抖动最大的来源。 +3. **路径多样性** —— 每连接维护 2–3 条候选(直连 / 就近中继 / 备用中继),**抖动劣化即切**。 +4. **中继不要打满** —— 利用率留 **30%+ 余量**;打满必然抖动爆炸。 +5. **就近接入** —— 骨干用 BGP 多线 / 就近节点(业界口径:BGP 多线可把跨网延迟压到 20 ms 内)。 + +### 验收判据 +每连接的 **jitter 直方图**;超阈值自动切路径并告警。 + +--- + +## 5. 备份窗口挤占 + +1. **抖动窗口**:200 台备份起点**随机散布到 2–3 小时**(cron + 随机 sleep),把 136 Mbps 尖峰摊平。 +2. **低优先级队列**:备份/同步走 **background 类**(fq_codel 的 background 档,或 LEDBAT 式延迟敏感型拥塞控制)⇒ 交互流量优先。 +3. **双层限速**:每台上限 + 全网上限。 +4. **只备不可再生 + 增量去重 + 上传前加密**(沿用备份三层方案)。 +5. 上传走**各自到对象存储**的路径,**不走中继**。 + +### 验收判据 +备份进行期间,聊天与游戏的 **p95 延迟不变**。 + +--- + +## 6. 重连风暴(160 / 1000 并发) + +1. **指数退避 + 全抖动(full jitter)** —— 关键结论:**没有抖动,退避会同步化**,等于没退。 +2. **重试预算(retry budget)** —— 限制"重试流量 / 正常流量"比例(如 10%),超预算就停止重试。 +3. **控制面令牌桶 + 排队 + 明确的 429/Retry-After**。 +4. **数据面不依赖控制面** —— 已建立的连接在控制面重启时不受影响。 +5. **熔断 + 冷却**(平台已有崩溃熔断先例,可复用同一套机制)。 + +### 验收判据 +拔掉一台中继后,1000 台的重连曲线是**平滑爬升**,不是**尖峰**。 + +--- + +## 7. agent 自激(本方案独有的放大源) + +1. **禁止 agent 直接触发 agent** —— **只有人的消息能触发 agent 发言**。这是唯一能真正切断指数增长的规则。 +2. 每 agent **每 N 分钟最多 M 条** + 发言后**静默期**。 +3. **房间级 agent 数上限**(建议 ≤ 房间人数 / 10)+ 房间级总速率上限。 +4. **agent 独立配额池**(不与人共享额度,避免 agent 挤掉真人)。 +5. 观测:**agent 发言占比**告警。 + +### 验收判据 +注入一个"回声型 agent"做压测,**房间消息量有上限、不增长**。 + +--- + +## 8. NAT 表溢出 + +1. **每 NAT / 每子网的打洞并发上限**(按该 NAT 的会话数能力推算)。 +2. **收敛探测** —— 禁止所有设备同时打同一目标;加**随机延迟 + 指数退避**。 +3. **同网段优先本地发现**(mDNS 式)⇒ 压根不走 NAT。 +4. 打洞失败**即降级中继**,不重试(与 #6 共用机制)。 + +### 验收判据 +同一办公室 **20 台同时上线**,NAT 不丢线、其他网络不受影响。 + +--- + +## 9. 版本碎片 + +1. **协议版本协商 + 严格递增**(防降级攻击)。 +2. **灰度**:1% → 10% → 100% 分批。 +3. **相邻版本必须互通**(客户端 N 与 N-1 必须能对话)。 +4. **版本包走内容寻址**(与 #3 共用一套分发机制)。 +5. 观测:各版本节点数与错误率**按版本切分**。 + +--- + +## 落地顺序(按"收益 ÷ 成本"排) + +| 序 | 动作 | 为什么排这里 | +|---|---|---| +| 1 | **presence 改造** | 唯一的第一瓶颈,且是**纯应用层**改动,不动协议 | +| 2 | **游戏服部署规范**(放 L1) | **零成本**,直接消掉 600 Mbps | +| 3 | **内容分发:块级内容寻址 + 同网段 peer** | 一次投资同时治 #3、#5、#9 | +| 4 | **重连治理**(退避 + 全抖动 + 重试预算 + 令牌桶) | 低成本,防事故 | +| 5 | **备份抖动窗口 + 低优先级队列** | 低成本 | +| 6 | **jitter 度量与选路** | 决定游戏可玩性 | +| 7 | **agent 配额 + 硬约束** | 本方案独有风险 | +| 8 | **每子网打洞并发上限** | 低成本 | +| 9 | **协议版本治理** | 随规模推进 | + +### 如果只做三件事 +**presence 改造 + 游戏服放 L1 + 块级内容寻址分发** —— 这三件覆盖了最大的三个瓶颈,且**都不需要改传输协议**。 + +--- + +## 未验证项 + +| # | 项 | 状态 | +|---|---|---| +| 1 | presence 收敛的实际降幅(业界口径可达 5×–8×) | ⚠️ 需实测 | +| 2 | 中继链路的 jitter 分布(决定能否支撑游戏) | ⚠️ **最该先测** | +| 3 | 同网段 peer 命中率(决定 10.8 GB 能压到多少) | ⚠️ 需实测 | +| 4 | fq_codel 在本环境中继上的实际效果 | ⚠️ 需实测 | +| 5 | agent 限额参数(M / N / 房间上限)取值 | 📋 需压测标定 | diff --git a/dsh-server-docs/INDEX.md b/dsh-server-docs/INDEX.md index 357ea09..b8a7e35 100644 --- a/dsh-server-docs/INDEX.md +++ b/dsh-server-docs/INDEX.md @@ -148,6 +148,16 @@ | 06 | 🔄 | **前端 UI 强制基线**:Token/布局/组件/交互/9 条已知坑 | | 07 | ✅ | **实例 UI 分区登记表**:settings.section 的 id/order/label → 提供者 → 源码 → 可改性 + 定位套路(含"中文文案要同时搜 UTF-8 与 \uXXXX") | | 04-89 | 🔄 进行中(L2 机制级已验 | **对话内文件预览**:采纳官方推荐库现成插件 `@softspark/dsh-file-preview`(65 KB,包住官方 `openWorkspacePath` 接管"点文件"手势;兼容预检 ok、已启用、L5 | +| 04-103 | 📋 | **客户端安装 + 覆盖网络互联 · 可行性评估**(规划态 · 未实施):判定 ✅ 可行,且现有架构已给出约 80% 形状(`soft` 档实例=裸子进程 ⇒ 无需 root;Worker 拨出式反向隧道 ⇒ **节点本来就不需要公网 IP**);缺口 4 条(客户端运行时落点 · 节点身份 · **信任模型反转** · 分发与版本矩阵);形态三档已按用户口径收窄为**单机自用**(B 档);6 步落地、每步可单独回滚。⚠️ 真正硬阻塞点修正 = **平台调用层**(Windows 下裸名 `spawn` ENOENT / `.cmd` EINVAL),非 dsh 运行时 | +| 04-104 | 📋 | **覆盖网络 · 全球架构复盘**(规划态 · 未实施):五层架构(控制面 / 会合 / 骨干·中继 / 数据面 / 观测)+ 12 条必须内建特性 + **10 类风暴类型学** + 流量组织五原则 + 流量预算表 + 7 步落地顺序。🔑 三句结论:控制面与数据面**彻底分离** · 失败不要变成重试(退避+抖动+判死) · 放大点必须前置治理。🟢 范围声明:**只做技术实现,跨境数据合规由使用者自负**(⛔ 不再作前置条件或上抛项) | +| 04-105 | 📋 | **覆盖网络 · 骨干层方案**(规划态 · 未实施):多中心骨干(≤10–20 成员、全互联;每节点只连 1–2 个骨干)+ 选择性加入。三条硬约束:**接入 / 成员 / 可见三分离** · **骨干资格只能控制面签发**(否则出现第二权威源、骨干沦为公网跳板) · **骨干不得被默认征用**(命中 R5)。⚠️ §7 唯一待拍板 = 骨干服务范围(A 只服务自己名下设备 / B 服务全网;**倾向 A→B 渐进**) | +| 04-106 | 📋 | **覆盖网络 · 百台规模推演 v2**(规划态 · 纯文字推演):⚠️ 含**前提级纠错**(v1 作废)—— 用户纠正「**单机用也要互联**」;错因 = **把「租户维度收窄」误当成「网络维度收窄」**。100 台异构画像:L1 10 / L2 30 / **L3 需中继 40–55** ⇒ **中继按 45% 设计、55% 留余量**(⛔ 不用同构假设的 15%);**必须补 443/TCP 兜底**(否则企业/校园网整类进不来);**L1 自动升格为中继候选**;仍不建全互联(4,950 vs 100) | +| 04-107 | 📋 | **覆盖网络 · 千台全场景推演**(规划态 · 纯文字推演):1000 台异构 × 11 场景 + **流量预算总表** + 瓶颈排序。🔥 **第一瓶颈 = presence**(1000 人大房 ≈ **16,700 次/秒**,是其消息扇出的 16 倍;普通房合计 8,200/s);💰 **最大成本杠杆 = 游戏服放 L1**(放家宽 ⇒ 中继 **600 Mbps 常驻**、峰值 1.2–2.0 Gbps;放公网 IP ⇒ **0**);游戏的真正门槛是 **jitter < 20 ms** 而非带宽;**agent 为本方案独有放大源** | +| 04-108 | 📋 | **覆盖网络 · 游戏专项(MMORPG 2D/2.5D · MUD · 传奇类)**(规划态 · 未实施):⚠️ 判定**由「不合适」修正为「最匹配」**(该类游戏天生服务端权威 + tick 驱动 + **AOI 九宫格** + 分区/分线;每玩家仅数 KB/s~数十 KB/s、几百 ms 无感)—— 原"不合适"只针对 3D 大世界强实时竞技。⭐ 核心简化:**玩家之间不需要互联 ⇒ 中继容量按「服数」算、不按「玩家数」算**。含 12 条设计细节 + 参考方案(Evennia/Skynet/Pomelo/Nakama…)+ 8 条反模式 | +| 04-109 | 📋 | **覆盖网络 · 调研:游戏网络特征与单房间群聊上限**(规划态 · 全网调研稿,数值均标来源):游戏侧每玩家 **2–20 KB/s**、同步 5–20 Hz、**jitter > 20 ms 即 desync**;群聊侧 **Telegram 20 万 / WhatsApp 2,048 / Discord 单频道 100K+**;🔑 **上限不是「人数」而是「扇出预算」**,且 **presence(N²) 比消息更早爆**(1000 人房 ≈16,700/s)。**本方案实际上限 = min(扇出预算, presence 预算, agent 预算)** | +| 04-110 | 📋 | **覆盖网络 · 答疑(群聊+agent / 备份 / 迁移提速 / 传输保密)**(规划态 · 未实施):① 群聊=**应用层**的事(覆盖网络只给「可达」);**agent 四条硬约束**(⛔ 禁止 agent 直接触发 agent);② ✅ **备份主层用对象存储**,覆盖网络只当**搬运通道与第三副本**(P2P 副本无 SLA、可误删,不适合当存档);③ 迁移 7 条按收益排,**最大一招 = 只搬不可再生(46.3 MB vs 2.9 GiB ≈ 64×)**;④ 保密 = 三层加密 + 元数据保护,**最大缺口 = 身份(共享令牌 → 一机一钥)** | +| 04-111 | 📋 | **覆盖网络 · 补遗与参考方案**(规划态 · 未实施):互联游戏 ✅ 但**由游戏形态决定**(锁步/回合/异步最友好;FPS/MOBA 64+ ❌ 不合适,P2P 无法反作弊);补遗 **24 条**(身份与账户 / 寻址与名字 / 接入与可见性 / 自检与选路 / 流量与公平 / 移动端弱网 / 升级版本自愈 / 可观测)+ 10 个能力域的参考方案 + **反模式 12 条**。⭐ 最划算的架构复用:**群聊房间与游戏对局是同一个模型**(一次投资,群聊 + 游戏 + 协作 + 看板共用) | +| 04-112 | 📋 | **覆盖网络 · 九大瓶颈落地方案**(规划态 · 未实施):把 107 的九大瓶颈逐个给成**可执行做法 + 验收判据**(含 Slack / SCCM·BranchCache·Delivery Optimization 官方照抄点)。🎯 **只做三件 = presence 改造 + 游戏服放 L1 + 块级内容寻址分发**(覆盖最大三个瓶颈,且**都不需要改传输协议**)。🔑 分水岭:**必须做「块级」内容寻址,⛔ 别做「包级」**(包级 = 版本一发所有 peer 源失效 ⇒ 正是全量重拉风暴的成因) | | — | 🗄 | `archive/dsh-improvement-plan-20260909-full.md`:拆分前 19 章 | | — | ✅ | `skills/dsh-change-workflow/SKILL.md`:六阶段 + **红线 R1-R11**(工作副本在本机 `.workbuddy/skills/`)| | — | ✅ | `skills/dsh-decision-method/SKILL.md`:**改造决策方法论**(用户有效决策 U1-U12 / AI 有效决策 A1-A13 / 反例 X1-X8 + 确认最优解十问 + 交互 UI 专项清单)(工作副本在本机 `.workbuddy/skills/`)| diff --git a/dsh-server-docs/docs-manifest.json b/dsh-server-docs/docs-manifest.json index 37bfdee..c12f0e4 100644 --- a/dsh-server-docs/docs-manifest.json +++ b/dsh-server-docs/docs-manifest.json @@ -1,27 +1,28 @@ { "generatedFrom": "scripts/docs-manifest.py", "counts": { - "files": 138, - "chars": 1129912 + "files": 148, + "chars": 1222542 }, "tiers": { "hot": 7, "cur": 27, - "warm": 56, - "cold": 12, + "warm": 57, + "cold": 21, "doc": 36 }, "domains": { - "platform": 54, - "method": 28, + "platform": 60, + "method": 29, "ui": 14, "plugin": 27, - "ops": 10, + "ops": 11, + "?": 2, "external": 5 }, "layers": { "L0": 1, - "L5": 115, + "L5": 125, "L4": 4, "L2": 3, "?": 1, @@ -65,8 +66,8 @@ "title": "03 路线图与待办", "status": "?", "date": "", - "chars": 18493, - "lines": 127, + "chars": 18981, + "lines": 128, "refs": 0, "refsCurrent": 0, "tier": "doc", @@ -217,7 +218,7 @@ "date": "04-10", "chars": 6261, "lines": 129, - "refs": 24, + "refs": 48, "refsCurrent": 1, "tier": "cur", "layer": "L5", @@ -269,6 +270,111 @@ "domain": "ui", "tldr": "**结论**:语言切换搬进 **`@dsh-local/portal-entry` 的「用户设置」分区**(id `user-settings`,order 103)," }, + { + "path": "04-调整方案/103-客户端安装与覆盖网络互联-可行性评估.md", + "num": "103", + "title": "103 · 客户端安装与覆盖网络互联 · 可行性评估", + "status": "📋 规划态 / 未实施(本轮", + "date": "2026-09-16", + "chars": 11661, + "lines": 242, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "platform", + "tldr": "> ✅ **可行,且现有架构已给出约 80% 的形状** —— T08 集群化已经把「一台机器 = 一个可被平台拨入的执行体」定义完了," + }, + { + "path": "04-调整方案/104-覆盖网络-全球架构复盘.md", + "num": "104", + "title": "104 · 覆盖网络 · 全球架构复盘", + "status": "📋 规划态 / 未实施(架构", + "date": "2026-09-16", + "chars": 9621, + "lines": 267, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "platform", + "tldr": "> ✅ **有完整可循的工程路径** —— Tailscale / ZeroTier / Nebula / libp2p / BitTorrent 已反复验证过,**关键是照抄它们踩过的坑,而不是自己发明**。" + }, + { + "path": "04-调整方案/105-覆盖网络-骨干层方案.md", + "num": "105", + "title": "105 · 覆盖网络 · 骨干层方案", + "status": "📋 规划态 / 未实施(设计", + "date": "2026-09-16", + "chars": 7710, + "lines": 254, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "?", + "tldr": "> ✅ **可以,而且是成熟系统里的标准模式** —— 业内叫「**超级节点 / 骨干层(supernode / backbone)**」(ZeroTier Moon · Nebula Lighthouse · Tailscale DERP" + }, + { + "path": "04-调整方案/106-覆盖网络-百台规模推演-v2.md", + "num": "106", + "title": "106 · 覆盖网络 · 百台规模推演-v2", + "status": "📋 规划态", + "date": "2026-09-16", + "chars": 8519, + "lines": 255, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "platform", + "tldr": "" + }, + { + "path": "04-调整方案/107-覆盖网络-千台全场景推演.md", + "num": "107", + "title": "107 · 覆盖网络 · 千台全场景推演", + "status": "📋 规划态(文字推演", + "date": "2026-09-16", + "chars": 9463, + "lines": 290, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "?", + "tldr": "> 1000 台异构设备 × 11 个场景的流量推演。**控制面在 1000 台规模仍不是瓶颈**(50 req/s);" + }, + { + "path": "04-调整方案/108-覆盖网络-游戏专项-MMORPG与MUD.md", + "num": "108", + "title": "108 · 覆盖网络 · 游戏专项-MMORPG与MUD", + "status": "📋 规划态 / 未实施", + "date": "2026-09-16", + "chars": 7498, + "lines": 231, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "platform", + "tldr": "> 这三类游戏的架构(**服务端权威 + tick 驱动 + AOI 九宫格广播 + 分区/分线**)**本身就是覆盖网络友好型的**," + }, + { + "path": "04-调整方案/109-覆盖网络-调研-游戏网络特征与群聊上限.md", + "num": "109", + "title": "109 · 覆盖网络 · 调研-游戏网络特征与群聊上限", + "status": "📋 规划态(全网调研稿", + "date": "2026-09-16", + "chars": 7347, + "lines": 203, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "platform", + "tldr": "> 两部分:① **这类游戏的网络特征**(传奇 / MMORPG / MUD 的每玩家带宽、同步间隔、承载、延迟/丢包门槛);" + }, { "path": "04-调整方案/11-技能管理面-shared+mine-API与页面.md", "num": "11", @@ -277,13 +383,58 @@ "date": "04-11", "chars": 7789, "lines": 176, - "refs": 15, + "refs": 28, "refsCurrent": 0, "tier": "warm", "layer": "L5", "domain": "method", "tldr": "**结论**:补完技能管理面:admin 管**全员共享技能** + 每个用户管**自己的个人技能**(`/api/skills/{shared,mine}` + 页面)。" }, + { + "path": "04-调整方案/110-覆盖网络-答疑-群聊备份迁移保密.md", + "num": "110", + "title": "110 · 覆盖网络 · 答疑-群聊备份迁移保密", + "status": "📋 规划态(技术答疑稿", + "date": "2026-09-16", + "chars": 6824, + "lines": 221, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "ops", + "tldr": "> 四问四答:① **群聊 + agent 入群** = ✅ 可实现(群聊是**应用层**的事,覆盖网络只解决「可达」);② **备份** = **主备份优先对象存储**," + }, + { + "path": "04-调整方案/111-覆盖网络-补遗与参考方案.md", + "num": "111", + "title": "111 · 覆盖网络 · 补遗与参考方案", + "status": "📋 规划态(补遗复盘稿", + "date": "2026-09-16", + "chars": 8308, + "lines": 251, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "platform", + "tldr": "> 四部分:① **互联游戏可行性**(✅ 支持,但**由游戏形态决定**;优先做「**只传输入**」的锁步/回合制);" + }, + { + "path": "04-调整方案/112-覆盖网络-九大瓶颈落地方案.md", + "num": "112", + "title": "112 · 覆盖网络 · 九大瓶颈落地方案", + "status": "📋 规划态 / 未实施", + "date": "2026-09-16", + "chars": 9158, + "lines": 282, + "refs": 0, + "refsCurrent": 0, + "tier": "cold", + "layer": "L5", + "domain": "method", + "tldr": "> 把 107 §4 排出的**九大瓶颈**逐个给成**可执行做法 + 验收判据**(含 Slack / SCCM 官方照抄点)。" + }, { "path": "04-调整方案/12-VoxEMW全云API化接入dsh-调研与M1落地.md", "num": "12", @@ -1282,7 +1433,7 @@ "date": "2026-09-13", "chars": 5969, "lines": 111, - "refs": 9, + "refs": 10, "refsCurrent": 0, "tier": "warm", "layer": "L5", @@ -1387,9 +1538,9 @@ "date": "2026-09-13", "chars": 12153, "lines": 236, - "refs": 0, + "refs": 2, "refsCurrent": 0, - "tier": "cold", + "tier": "warm", "layer": "L5", "domain": "platform", "tldr": "① 原先平台是「**统一 KEY**」——`resolveApiKey()` **显式忽略入参 userId**,不管谁 spawn 都注入 admin 那一把;② 本轮改为**两层**:**用户自己的 key 优先,没有才回落管理员的「平" @@ -1567,7 +1718,7 @@ "date": "2026-09-14", "chars": 3035, "lines": 76, - "refs": 1, + "refs": 6, "refsCurrent": 0, "tier": "warm", "layer": "L5", @@ -1700,8 +1851,8 @@ "title": "dsh 平台文档导航(INDEX)", "status": "?", "date": "", - "chars": 16649, - "lines": 830, + "chars": 19438, + "lines": 840, "refs": 0, "refsCurrent": 0, "tier": "doc", @@ -1910,8 +2061,8 @@ "title": "dsh-decision-method — 平台改造的思考与决策方法", "status": "?", "date": "", - "chars": 12562, - "lines": 306, + "chars": 14128, + "lines": 335, "refs": 0, "refsCurrent": 0, "tier": "doc", @@ -2000,8 +2151,8 @@ "title": "dsh-feature-first — 功能优先协作协议", "status": "?", "date": "", - "chars": 13242, - "lines": 353, + "chars": 14920, + "lines": 361, "refs": 0, "refsCurrent": 0, "tier": "doc",