Files
dsh_ai1net_server/dsh-server-docs/04-调整方案/112-覆盖网络-九大瓶颈落地方案.md
T
admin 4e3a1a4a13 docs(overlay): 覆盖网络/客户端化 10 份规划转正式档案 103-112 + 登记
- 新增 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-<NN> 再写)
2026-09-16 10:25:09 +08:00

282 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 / 房间上限)取值 | 📋 需压测标定 |