Files
dsh_shenxian/dsh-server-docs/04-调整方案/123-方案规划方法-覆盖网络线提炼.md
T
admin 04776af4b1 docs: 工作区根项目文档批量入仓(04-调整方案 113–128 / 交接单 T09–T21 / ops / archive)
起因:用户 2026-09-17 明确「所有文档都要同步,都放在开发仓库 docs 对应文件夹下」。
判据:工作区根 *.md 中在仓库(git ls-files --quotepath=false)搜不到的那些。

入仓 33 份(一律复制,工作区根原件保留不动,避免引用断链):
- 04-调整方案/113–128(16 份 · 原子占号后落盘):覆盖网络 传输方案取舍 / 应用场景与待完善清单 /
  插件化vs改内核 / 问题逐条推演 / 参数表与观测口径;会合中继拆分取证与改造方案;
  集群化改造方案 Manager-Worker;跨节点迁移与节点自举;项目代码分层范式与迭代风险评估;
  搬运与共享重建方案 guest w47→w106;方案规划方法提炼;文档无效信息审计报告;
  会话接续机制复盘与修复;会话接续规范;dsh 客户端化部署方案;dsh 桌面客户端开发方案
- 交接单/archive/交接单-已完成/T09–T21(13 份 · 覆盖网络线已完成单归档)
- ops/(2 份运行态指针:接续入口 / 接续包 · 覆盖网络线)
- archive/(2 份临时与内部简报)

已排除(无需重复入仓):覆盖网络线 10 份方案正文已入档案 103–112(文件名不同)。

登记:INDEX.md §二 新增 04-113–128 共 16 行 + §四 追加 T09–T21 说明 + 机器摘要行刷新
(⛔ 未跑 docs-index-stats.py --write:该脚本会按 \r\n 归一化全文件行尾,故改为字节级单行替换);
README.md 追加 1 条入仓指针;docs-manifest.json 复跑 scripts/docs-manifest.py 刷新。

验收:工作区根 47 份 .md —— 同名已入仓 8 / 本次内容一致 29 / 已知改名映射 10 / 未入仓 0;
git status 待提交清单只含本次新增与登记 3 件(未涉 src/ 与 relay 代码面)。
2026-09-17 18:24:19 +08:00

20 KiB
Raw Blame History

方案规划方法 —— 从覆盖网络线提炼(2026-09-16)

它是什么:一套「从零推演出一个可落地架构」的分段作业法。五段 = 信息收集 → 方案调研 → 场景梳理 → 逻辑验证 → 应用推演,每段有固定骨架、固定产出、固定出口判据,全部走完才允许进入执行。 它不是凭空设计的 —— 是从覆盖网络线 17 份文档 + 6 份勘误 + 1 次落地执行 的真实过程里反推出来的(§9 有 8 次纠错作证)。 适用边界:信息不全、没有现成答案、要一次拍准方向的重规划任务。小改动不需要这么重(那种直接按 dsh-change-workflow 六阶段走即可)。 不适用范围:已有明确技术答案的实现任务;单文件改动;纯 UI 调整。


0. 一句话总览

把"一个大到没法定的事"拆成五段流水线;每段只回答一个问题,出口必须能给"这步做完了吗"的判据。

① 信息收集   该知道的数,都有出处了吗?           → 参数表(实测 / 业内 / 推算 三档标注)
② 方案调研   别人踩过的坑,照抄了吗?             → 参考方案对照 + 分层架构
③ 场景梳理   要扛的事,列全了吗?口径对了吗?      → 场景清单(含故障)+ 完成度表
④ 逻辑验证   每条推得通吗?有跳跃/矛盾吗?         → 缺口清单 P0/P1/P2 + 勘误 + 反模式
⑤ 应用推演   叠加起来先炸哪个?能算吗?            → 流量预算总表 + 瓶颈先炸顺序
────────────────────────────────────────────────────────
出口闸门    估值换成实测 + 参数表固化 + 权限/成本评估  → 交接单(方可开工)

五段的顺序不可交换:跳过 ③④ 直接做 ⑤,会得到"数字很漂亮但前提是错的";跳过 ①② 直接做 ⑤,会得到"自己发明的一套轮子"。


1. 第一段 · 信息收集

只回答一个问题:我要用的每个数、每条结论,出处是什么、可信到什么程度。

要做的四件事

# 动作 判据
1 范围边界前置 文档开头写死「只做什么 / 不考虑什么」,并注明这是谁的口径(用户原话 / 自定)
2 找对照组(能力标尺) 每个能力域找到真实在跑的产品作标尺,不允许"我觉得"
3 数据分三档标注 实测(本环境有命令/证据)|业内口径(有出处,非本环境)|推算(自己算的)——⛔ 三档不许混写
4 先标"最该先测的三项" 在收集阶段就点出"哪几个数一换、全部结论的可信度就变"

覆盖网络线的实例

  • 范围声明(用户原话):「方案只考虑技术实现,跨境数据合规是谁用谁自己考虑」⇒ 此后所有文档统一带 🟢 范围声明,且选型不为合规让路。
  • 对照组:Tailscale / headscale / ZeroTier / Nebula / libp2p / BitTorrent / Slack / Telegram / WhatsApp / Discord / SCCM / restic。
  • 三档标注实例:首屏 10.8 MB、跨云 22 KB/s、心跳 20 s = 实测;打洞率 90%/40%/10% = 估算;presence 16,700 次/秒 = 推算。

常见失手

⛔ 把业内口径当自家实测(会导致后续所有容量结论虚高)|⛔ 只收"支持我结论"的资料|⛔ 范围边界写成事后补充。


2. 第二段 · 方案调研

只回答一个问题:这套东西别人已经做过吗、踩过什么坑——目标是照抄,不是发明。

核心原则(一句话)

关键是照抄它们踩过的坑,而不是自己发明。(覆盖网络线原文口径)

要做的三件事

  1. 参考方案对照表:能力域 → 参考方案 → 借什么。"借什么"必须写具体(不是"参考 Tailscale",而是"借它的控制面/数据面分离 + DERP 区域模型")。
  2. 默认参数直接固化:成熟项目的默认值不要自己拍(libp2p 的拨号并发 ≤4 / 总 100 / 超时 30 s、连接水位 100/400/1 min、中继自荐 15 min/30 min TTL、BitTorrent 上传并发 4 等)⇒ 直接进 §1 的参数表。
  3. 分层:先给架构分层(覆盖网络线 = 控制面 / 会合层 / 骨干中继层 / 数据面 / 观测层五层),再谈组件。分层定了,后面"这块放哪"才有判据。

先拆概念(这一步经常被跳过,然后全盘皆错)

覆盖网络线的实例:「插件」这个项目里有两个完全不同的含义 —— (a) dsh 官方插件(跑在实例内部)够不到宿主网络栈;(b) 平台自身的模块化。没先拆这两个概念,就会在错的对象上讨论"插件 vs 改代码"。

⇒ 判据:出现一个术语可能指两件事时,先列表拆开再往下走。

三层归属(普适判据,可直接复用)

层 内容 形态 判据
数据面组件 要碰宿主网络栈、要独立扩缩容与加固 独立进程 / 独立 systemd 单元 与主进程同生共死就出局
平台侧集成 寻址、身份、资格签发、容量准入 改平台代码 必须与权威状态同源(外置 = 第二个权威源 = 脑裂)
实例内展示与工具 「我的 XX」面板、实例内工具 插件 纯实例内 UI/工具才配插件

3. 第三段 · 场景梳理

只回答一个问题:这东西被用在什么场景、要扛多大——且先确认口径对不对。

要做的五件事

# 动作 说明
1 口径先校正 目标场景必须由用户确认过;文档里显式写 📌 口径校正(日期,谁纠正)
2 设备/环境画像 按类列表(不是平均值):覆盖网络线用 6 类(云服务器 / 家宽 / CGNAT / 移动网 / 企业网 / VPN)× 台数 × 成功率
3 场景枚举含故障 正常场景 + 故障场景 + 极端场景三类都要有(S1–S11 含"中继故障 / 控制面重启 / 区域突变 / NAT 表溢出")
4 分工矩阵 环境类型 × 应用 → 关键约束(一眼看出"哪类节点必然走中继")
5 完成度表 纸面推演 / 可运行模拟 / 实测 三档分开标 ——⛔ 不许把"纸面算过"说成"验证过"

关键动作:把口径纠正当成产出

覆盖网络线真实发生过一次重排:用户明确目标场景 = ① 多人 + agent 对话 ② MUD / MMORPG 网游 ③ 以上述应用为负载的 1000 台异构网络互联 ⇒ 原报告把"跨机访问实例/文件交换"排第 1 档属次级用途,已重排。

⇒ 教训:场景优先级排错,后面全部推演都在给次要场景做容量。这一步上抛是值得的(属"业务目标与优先级",是边界外真门禁)。

常见失手

⛔ 只列正常场景(故障场景才是容量规划的主体)|⛔ 用"平均设备"代替异构画像(掩盖了 CGNAT/移动网这类必走中继的少数派)|⛔ 不标注"哪些是纸面"(下游会把推演当事实)。


4. 第四段 · 逻辑验证(本方法的核心)

只回答一个问题:从场景到结论,每一步都站得住吗。

4.1 固定四段骨架(每条问题都按这个写,不例外)

① 问题      —— 一句话说清缺什么/错在哪
② 查到什么资料 —— 业界范式 + 出处(能照抄就给照抄点)
③ 推演      —— 拿资料 + 我方实际约束,推出来
④ 结论      —— 能不能解 / 怎么解 / 代价是什么(三问必答)

这个骨架的价值:它把"我觉得"逼成"资料说什么 + 我们实际是什么 + 推出什么"。任何一条卡在②或③,说明还不到下结论的时候。

4.2 四类必须主动去找的"洞"(覆盖网络线全部命中)

类型 长什么样 覆盖网络线的实例
缺口 方案里有个位置空着,但下游已经依赖它 "单房间上限 = min(扇出预算, presence 预算, agent 预算)",而 agent 预算从未标定 ⇒ 三个预算里一个是空的
逻辑跳跃 结论 A 需要前提 B,而 B 从没被论证过 S3 算出"服放家宽 ⇒ 600 Mbps 过中继",但玩家是外部客户端、不是网络成员,凭什么走我们的中继⇒ 由此发现缺一整个"发布层",且瓶颈性质变了
自相矛盾 方案内部两条约束互斥 S5 设"1000 人房聚集 200 个 agent",而自家硬约束是"房间 agent ≤ 人数/10 = 100"
事故级预判 不提前处理必然出事,且事后极难排查 设备池里 200 台 CGNAT + 150 台移动网本机就在 100.64.0.0/10 内;若覆盖网也用这段 ⇒ 路由黑洞、"部分节点时通时不通",极难排查 ⇒ 主寻址必须走 IPv6 ULA + IPv4 冲突检测进首版

⇒ 这四类不许靠"通读一遍觉得没问题",要逐条对照:每个结论问"它的前提被论证过吗",每条约束问"它和另一条冲突吗"。

4.3 实测证伪 —— 纸面推演不算数

任何"机制类的设计"在落地前,必须有一次最小实测:

实例:方案 S3 原设计用"回环别名"(ssh -R 127.0.0.2:…)隔离中继落点。实测:47 的 sshd -T ⇒ gatewayports no ⇒ 127.0.0.2 被静默改写成 127.0.0.1,ssh 侧零报错(ExitOnForwardFailure 未触发、日志为空)⇒ 机制作废,改用"实例端口区间隔离"。 ⚠️ 要点:失败是静默的 —— 如果只做纸面推演,这套机制会带着"看起来对"的样子进入生产。

实测的副产品往往是真 bug:顺着这条线查出 findFreePort() 各 worker 各自随机 + tunnel.forward() 返回值两处被忽略 ⇒ 撞号时 -R 失败但静默 ⇒ Manager 照旧拨 127.0.0.1:<port> ⇒ 静默打到另一个用户的实例。这条 两台机器即可触发。

4.4 前人结论,先做最小取证

实证:同一天踩两次 —— ① 方案写"proxy.ts:109 是中继连接目标",实为发给上游 dsh 的 Host 头(改它 = 全量 /api 403);② 说"有 3 处基础层反向依赖",实为入口层的合法依赖、真实违规 0 处。 ⇒ 拿上一份文档的结论当既成事实,是这类规划最主要的错误来源。 引用前必须复核(连行号都会漂:138-139 实测为 136-137)。

4.5 勘误要集中成节,且写清"照字面做会出什么事"

要求 说明
位置 集中一节(覆盖网络线 = 方案 §8/§9 + 交接单 §0.2),⛔ 不散落在正文
分级 🔴 实测证伪(改变做法)|⚠️ 需修正(不改做法)|📌 结论不变仅行号漂移
必写 "照原方案字面做会白做/会出事" 一句 —— 否则执行会话会照抄
复验 下一轮对上一轮勘误再确认一次(覆盖网络线 §9.7 复验了 §8 的三条)

4.6 反模式清单(同步产出)

验证过程中识别出的"踩了就出事"的做法,汇总成表(覆盖网络线 12 条:建全互联 / 无扇出限制的 gossip / 客户端持有权威状态 / 控制面下发全网名单 / 单中心中继 / 把网内副本当主备份 / 慢链路做备份 / 失败即重试 / agent 直接触发 agent / 推送式分发 / 共享密钥当身份 / 只按 IPv4 设计)。⇒ 这张表是给执行会话的红线,不是给自己看的笔记。


5. 第五段 · 应用推演

只回答一个问题:这些场景叠加起来,先炸哪个、多大、怎么治。

5.1 三条层层递进的动作

① 逐场景独立算 —— 每场景给"数值 + 判读",判读比数值重要(例:presence ≈16,700 次/秒,判读 = "presence 比消息早爆一个量级")。

② 流量预算总表(全案最重要的一张表) —— 列:流量 × 频率 × 单次 × N 台放大 → 上限手段。要求可复算(每个数从哪来能追)。

③ 叠加推演(此前最容易漏的一步) —— 串行列举 ≠ 最坏情况。方法三步:

步骤 做法
时间轴重叠检查 把各场景的时间窗排开(游戏高峰 20:00–22:00 / 群聊 20:00–23:00 / agent 随真人 / 备份 02:00)⇒ 重叠的才是要叠加的;顺带确认"备份与游戏错峰"是设计而非巧合
共享资源争用矩阵 列出被多方抢的同一个资源(出口带宽 / presence 通道 / 控制面 req/s / 客户端上行)⇒ 叠加后量级
主导项法 差一个数量级可忽略 ⇒ 只保留主导项,其余进"次要"

叠加的产出是"瓶颈排序会变":覆盖网络线叠加后,第一瓶颈仍是出口带宽,但第二从「presence」变成「presence × agent 叠加」(≈33,400 事件/秒,是任何单场景的两倍)。

5.2 瓶颈排序 = 按"先炸顺序"排,不是按"大小"排

产出一张 序 / 瓶颈 / 量级 / 主要处置 表。这张表就是落地顺序的输入(再按"收益 ÷ 成本"重排一次 ⇒ 覆盖网络线的结论是"只做三件事")。

5.3 数字可信度必须分级(这条决定了整套推演的诚实度)

覆盖网络线的原话口径:"关键结论对比例敏感、对绝对值不敏感" ⇒ 结构判断可信,具体容量数字还不可信。

⇒ 任何一份推演都要写清:哪些结论是"结构可信"(换个数也成立)、哪些是"数字可信"(已实测)。⛔ 不许把两者混在一句话里。

5.4 收尾三件套(每份推演都必须有)

  1. 未验证项表(标题就写"勿当结论")—— 所有不能证实的,统一放这里;
  2. 本次未做(范围声明) —— 明确边界,避免下游误读;
  3. 上抛项收敛 —— 写"未新增上抛项"或列出新增项;能排出优劣的自己拍掉。

6. 七条横切纪律(贯穿五段)

# 纪律 判据 / 反例
1 先只读,后动手 每份规划文档头部写明「⛔ 未改代码、未动服务器、未写文档库」;改任何文件前先抢执行锁
2 行号级引用 结论引用到 文件:行;引用前复核(行号会漂)
3 三档数据标注 实测 / 业内 / 推算,三档不许混写
4 口径校正显式化 用户纠正过的地方,文档里留 📌 口径校正 标记,⛔ 不静默改写
5 上抛收敛 一轮只问"真取舍"(各有优有劣);只有优点或只有缺点的自己拍;每个候选必须写优点 + 缺点,竖排成段
6 一条线一个入口 新会话只读"接续入口",不读全量日志(覆盖网络线:入口 3 KB,日志 60 KB)
7 文档间标"承接" 每份文档头写"承接 X"⇒ 形成 DAG,避免重复造轮子、也避免下游读到已作废的结论

7. 出口闸门:什么时候可以从"推演"走到"落地"

五段全绿不等于可以开工。覆盖网络线把卡点收敛成三件必须先办的事:

# 闸门 判据 覆盖网络线的实况
1 把关键估值换成实测 最少 3–5 台真机;只测那 3 个"一换全变"的数 选定 打洞成功率 / 中继 jitter / 真实可用带宽 —— ⚠️ 直到 09-16 仍未做,故容量数字仍标"不可信"
2 参数表固化 所有输入参数在一张表里 ⇒ 可复算、可仿真 已给(B3 表),⏳ 待落文档
3 权限影响评估 + 成本承诺 扩权(R5)与花钱(边界外)必须上抛 三处扩权:虚拟网卡驱动 / 骨干开端口 / 发布层对外暴露;成本 = 发布层 + 会合 + 中继

另一条独立闸门:执行前置 —— 落地前必须先把"挡住整个方向的那一个耦合点"拆掉。覆盖网络线的判断是:中继绑在 Manager 上 ⇒ 多区域 / 多中心 / 骨干层全部做不了,所以 S0–S4 排在任何功能开工之前。

⛔ 反模式:一上来换协议(WireGuard / TURN)。正确顺序是"先把耦合抽成配置与接口,让现有实现退化成'第一个可替换实现'"⇒ 每一步独立可验、独立可回滚。


8. 落地形态:规划 → 交接单 → 执行 → 勘误

规划会话只产出交接单,执行会话不读规划上下文。交接单必含(覆盖网络线的单子模板):

# 段 要求
1 §0 复核结论 + 勘误 实测基线表 + 逐条勘误(🔴 会白做/会出事 的排最前)
2 §1 只读前置 抢锁 / 读哪几节 / 照基线逐项复核 / 远程入口
3 §2 范围 做什么、⛔ 不做什么(把勘误结论写成禁令)
4 §3 步骤 每步:改哪些文件 / 接口怎么切 / 怎么验 / 怎么回滚 —— 四件缺一不可
5 §4–5 全局验收 + 清理 用户口径的业务验收 + 测试残留必须清(有副作用的验证脚本要写明)
6 §6 回报格式 判定 → 改了什么 + 部署到哪 → 实测输出 → 未做/风险 → 锁状态。⛔ 不许写"应该没问题"
7 §7 已知的坑 省执行方踩一遍(凭据、配置位置、端口、环境限制)

执行完必须回写:执行记录(P1/P2/P3 实测证据)+ 新勘误 + 未做项为什么没做(命中哪条红线)。


9. 方法自证:这条线上真实发生的 8 次纠错

# 纠错 由哪一段抓住
1 场景优先级排错 —— 把"跨机访问实例/文件交换"排第 1 档(实为次级) ③ 场景梳理(口径校正)
2 缺一整个"发布层" —— 玩家是外部客户端,凭什么走中继 ④ 逻辑验证(逻辑跳跃)
3 自相矛盾 —— 200 个 agent 违反自家"≤人数/10" ④ 逻辑验证(矛盾检出)
4 回环别名机制作废 —— sshd gatewayports no 静默改写绑定地址 ④ 逻辑验证(实测证伪)
5 地址段冲突 —— 设备池本机就在 100.64.0.0/10 内 ④ 逻辑验证(事故级预判)
6 真 bug:静默拨到别人实例 —— 端口撞号 + 返回值被忽略 ④ 逻辑验证(实测副产品)
7 前两条结论勘误 —— proxy.ts:109 是 Host 头;"3 处反向依赖"实为 0 处 ④ 逻辑验证(最小取证)
8 部署面漏了 47 —— 方案与交接单 v1 都只写了 106 执行阶段回写(规划也要复核部署面)

⇒ 8 次里有 5 次发生在第四段。这就是为什么第四段值得单独成段、且必须用固定骨架逐条走。


10. 可抄模板

10.1 文档头(三行定性质)

> 日期:YYYY-MM-DD | 性质:**只读推演稿 / 调研稿 / 设计稿 / 复盘稿**(⛔ 未改代码、未动服务器、未写文档库)
> 承接:<上一份文档>
> 🟢 范围:只考虑技术实现;<明确不做什么>
> 用户要求:<用户原话或口径来源>

10.2 条目骨架(第四段核心)

### X-n · <问题名>

**① 问题**:<一句话>
**② 资料(<范式名>)**:<可照抄的点 + 出处>
**③ 推演**:<我方实际约束 + 推出的结构>
**④ 结论**:✅/⚠️/❌ <能不能解> | 怎么解 | **代价**(缺一个不算结论)

10.3 文档尾(三件套)

## 未验证项(勿当结论)
| # | 项 | 状态 |

## 本次未做
- ⛔ 未改代码 / 未动服务器 / 未写文档库(原因:执行锁被 X 占用)

## 上抛
- 未新增上抛项 | 或:<项> —— A:优点/缺点 | B:优点/缺点 | 倾向

10.4 判定分级(全流程统一用词)

✅ 已完成并验收 | ⏳ 待授权/待做 | ⚠️ 缺口/需修正 | 🔴 实测证伪/事故级 | ⛔ 禁令/反模式


11. 已知局限

# 局限 说明
1 样本单一 方法从"覆盖网络"一条线反推 ⇒ 对"信息不全、要从零拍架构"的任务适配最好;对实现型任务偏重
2 第四段的产出高度依赖实测能力 没有真机/真环境时,只能停在"结构可信";本线的容量数字至今仍是估值
3 成本 全程 17 份文档 + 多次实测;「只做三件事」的收敛是必要的,否则规划本身会失控
4 未验证 本方法尚未在第二条线上复用过 ⇒ 尚属"一次成功案例反推",不是已验证的通用流程