Files
dsh_ai1net_server/交付物/用户组网群聊可行性评估-20260925.md
T

115 lines
8.2 KiB
Markdown
Raw Normal View History

# 交付物 · 用户组网群聊可行性评估(环形网络 · 2026-09-25)
> **工作区**:`E:/ProgramData/AIProject/aliyun-dsh-server`|**基线**:`D:/github/dsh_shenxian`
> **问**:能否让用户组成**环形网络**做群组聊天、只有数据保存到服务器?群聊的技术特性(对话顺序、历史记录等)是否满足?
> **方法**:① 只读取证现有覆盖网络能力 ② 联网核对业界群聊技术特性 ③ 逐条对照
---
## §0 判定(先说结论)
1. **「环形拓扑」不推荐** —— 三个硬伤(延迟随人数线性增长、单点断环、两两打洞成本 `O(N²)`),业界群聊无此形态。
2. ✅ **但「用户之间点对点组网」本身可行,且底座已经在平台里** —— 打洞、分网隔离、直连优先回落、组密钥**都已落地**(`src/net/relay/direct/` + `content/`)。
3. 🔴 **顺序与历史这两条,恰恰要求服务器必须是权威** —— 所以正确形态不是"P2P 取代服务器",而是
**服务器定序落库(权威)+ 用户间直连(加速投递)**。你说的"只有数据保存到服务器"与这个形态**完全一致**。
4. 🔴 **但有一个前置硬阻塞**:**云安全组未放行 ⇒ 真机打洞成功率实测 = 0** ⇒ 现在做 P2P 投递会**全部回落中继,等于没做**。
## §1 先分清两个概念(你的设想里混在一起)
| 说法 | 含义 | 判定 |
|---|---|---|
| **环形拓扑**(A→B→C→…→A) | 严格指消息沿环逐跳转发 | ❌ 不推荐(§2) |
| **点对点组网**(成员之间直连) | 彼此能直连,拓扑不限 | ✅ 可行,底座已在(§3) |
⇒ 我按"你要的是**用户之间能直连**"来评估;若你确实要严格的环,§2 给出为什么不建议。
## §2 为什么不推荐"环"
| 硬伤 | 具体 |
|---|---|
| **延迟随人数线性涨** | N 人环上,一条消息到最远的人要 **N/2 跳**;10 人尚可,100 人就是 50 跳的排队 |
| **单点断环** | 环上任意一人掉线/断网 ⇒ 环**断成两半**(要补救就得双向环 + 重路由 ⇒ 又回到全互联) |
| **两两打洞成本 `O(N²)`** | 每人要与其他所有人建直连 ⇒ 打洞次数按人数平方增长。🔴 这正是你们已记录过的 `O(N²)` 扇出问题 |
| **没有定序者** | 环只是拓扑,**不提供顺序**(见 §4-①) |
> 业界群聊的拓扑只有两种:**星型(服务器/中继为中心)**、**小群全互联(≤ 几十人)**。没有用"环"的。
## §3 已具备的能力(好消息 · 实测口径)
| 能力 | 落点 | 状态 |
|---|---|---|
| **打洞 / 直连** | `src/net/relay/direct/{candidate,punch}.ts` | ✅ 已落地(离线 NAT 模拟器 `24/24` 成功,p50 建连 155 ms) |
| **直连优先、回落中继** | `content/runtime.ts` 的 `PEER_CHANNEL_ORDER = ['direct','wss']` | ✅ 双通道已落地生产 |
| **块 id 复算闸门** | 取回的块必须复算 id 才对 | ✅ 防"假绿" |
| **分网隔离(用户可组独立网)** | `dialers: Map<networkId, Set<hostId>>`,**没列到的一个都拨不动(默认拒绝)** | ✅ **零代码**:新增一个 `networkId` 即可(`ops` / `u:<userId>` / 自命名) |
| **一键加入 + 分组准入** | `overlay-node-join.cjs` / `overlay-node-admit.cjs` | ✅ 已落地 |
| **组密钥加密** | 按 `(network, group)` 的 AES-256-GCM,组内密文一致 | ✅ 已落地 |
| **中继带宽节省(实测)** | `1 − 组数/节点数` ⇒ 4 人组 **75%**、16 人组 **93.75%** | ✅ 内容面实测 |
| 🔴 **云安全组放行 UDP** | 47 / 106 入站 `21100/21115` 仅放对端 `/32` | ❌ **未实施(唯一在册红)** ⇒ 真机打洞 **发 21 收 0** |
⚠️ **一处关键事实**:上述 P2P 能力目前**只用在「内容面」**(插件的静态内容分发,按块)。
**「消息面」零 P2P** —— `src/im/hub.ts` 的扇出只有"本进程逐连接"与"交给外部连接层"两条路。
⇒ 要在群聊里用 P2P,需要**把消息面接上这套直连**(新增接线,不是零成本)。
## §4 群聊技术特性逐条对照(联网核对 · 5 个来源一致)
### ① 对话顺序 —— 🔴 这条决定了"服务器必须权威"
业界一致结论(OpenIM / WhatsApp 设计 / 系统设计手册,五篇同口径):
> **会话内必须强顺序一致**(同一会话所有参与者看到的顺序严格一致);
> 做法 = **服务器在落库那一刻分配单调递增 `seq`**,客户端**按 seq 渲染、⛔ 不按本地到达时间**。
> **全局顺序不需要**(没人在乎两个不同群的先后)。
> 纯客户端时间戳**做不到**——时钟漂移 + 同毫秒并发无定序。
🔴 **推论**:`seq` 必须由**落库那一步**产生 ⇒ **定序点只能在服务器**。这否掉了"纯 P2P 群聊"。
✅ **你们已经这么做了**:`messages.seq` = DB 分配的房内单调整数(权威序),
`lamport` 只在**同一 seq 冲突**里做 tie-break、⛔ 不参与最终排序 —— 与业界口径**逐字一致**。
### ② 历史记录 —— 你说的"数据存服务器"正好满足
- 历史 = 按会话分区、按 `seq` 聚簇的**追加式日志**(append-mostly)。
- 离线补拉 = 客户端带上自己的游标,取"seq 大于游标"的那一段。
- ✅ 现有:`resume`(游标补拉是断线重连的**唯一**补齐路径)。
- 🔴 **如果消息只走 P2P 而不落库 ⇒ 历史直接缺失** ⇒ **每条消息都必须落库**,P2P 只做加速。
### ③~⑨ 其余特性对照表
| # | 特性 | 环网能否满足 | 现有平台 | 说明 |
|---|---|---|---|---|
| ③ | **多设备同步** | ❌ | ⚠️ 部分 | 每设备需各自游标(`last_read_seq` / `last_delivered_seq`);现只有单游标补拉 |
| ④ | **成员变更边界** | ⚠️ 要重构环 | ✅ 成员表 | 新成员能否看历史、踢出后是否即时停收 —— 现有成员表可判 |
| ⑤ | **在线态 presence** | ❌ 环上要全互联 | ✅ | 已有心跳 + 1 s 批合并 + 收敛(防惊群) |
| ⑥ | **群 E2EE** | ⚠️ 密钥分发复杂 | ✅ 方向已定 | 🔴 必须用**群共享密钥**(Megolm 化),⛔ 不能对 N 人各加密一次(`O(N²)`)—— 已在册 |
| ⑦ | **扇出成本** | ❌ `O(N²)` 连接 | ✅ | 中继 = 一次发布;P2P 反而放大连接数 |
| ⑧ | **单点故障** | ❌ 断环 | ✅ | 两台中继冗余 + 抖动切流(实测切换 18.8–20.9 s) |
| ⑨ | **CAP 取舍** | — | ✅ 已选 | 业界做法 = **最终一致 + 会话内强序**;现有实现同向 |
## §5 若要做,正确形态(架构选型 · 我已定,可推翻)
**不做环。采用「服务器定序 + 直连加速」**:
```
发消息 → 服务器落库(分配 seq = 权威序)──► 历史 / 补拉 / 多设备 都以此为源
└─► 同时经覆盖网络直连推给在线的其他成员(能直连就直连,不能就回落中继)
```
- 复用**已有**的 `direct/`(打洞)+ `content/runtime.ts` 的**双通道模式**(直连优先、回落 wss)+ **块 id 复算闸门**那套防假绿思路。
- 新增工作量:**消息面接直连**(现在只有内容面接了)+ 直连失败回落 + 防重放/去重。
- 收益(按已有实测外推):中继带宽节省 `1 − 组数/节点数`;**消息面需另测**(⛔ 不是照搬内容面读数)。
### 🔴 顺序约束(必须先做的前置)
**云安全组不放行 ⇒ 真机打洞成功率 = 0** ⇒ 先做消息面 P2P 会**全部回落中继 = 白做**。
⇒ 顺序是:**① 开云安全组 → ② 复测真机打洞率 → ③ 再决定要不要做消息面直连**。
⚠️ 云安全组只能**你在控制台操作**(我无云凭据,不得索取)。
## §6 一个更容易被忽略的前提
即便 P2P 建成,**"用户之间"要先在同一个覆盖网络里** —— 现有分网隔离是**默认拒绝**:
不在白名单的节点一个都拨不动。所以"让用户组成网络"这件事本身 = **先给这些用户建一个网 + 逐个准入**(P1 已能一键加入)。
## §7 边界
⛔ 本件**零代码改动**、未部署、未 commit/push、未动 47/106、未改任何别的工作区。
⛔ **未登记下一棒**(路线选择 + 云安全组操作均需你定)。