- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次) - .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…), 目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪 - .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/) - .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*) - .gitignore 补:备份件(*.bak-*) - 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
8.2 KiB
交付物 · 用户组网群聊可行性评估(环形网络 · 2026-09-25)
工作区:
E:/ProgramData/AIProject/aliyun-dsh-server|基线:D:/github/dsh_shenxian问:能否让用户组成环形网络做群组聊天、只有数据保存到服务器?群聊的技术特性(对话顺序、历史记录等)是否满足? 方法:① 只读取证现有覆盖网络能力 ② 联网核对业界群聊技术特性 ③ 逐条对照
§0 判定(先说结论)
- 「环形拓扑」不推荐 —— 三个硬伤(延迟随人数线性增长、单点断环、两两打洞成本
O(N²)),业界群聊无此形态。 - ✅ 但「用户之间点对点组网」本身可行,且底座已经在平台里 —— 打洞、分网隔离、直连优先回落、组密钥都已落地(
src/net/relay/direct/+content/)。 - 🔴 顺序与历史这两条,恰恰要求服务器必须是权威 —— 所以正确形态不是"P2P 取代服务器",而是 服务器定序落库(权威)+ 用户间直连(加速投递)。你说的"只有数据保存到服务器"与这个形态完全一致。
- 🔴 但有一个前置硬阻塞:云安全组未放行 ⇒ 真机打洞成功率实测 = 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、未改任何别的工作区。 ⛔ 未登记下一棒(路线选择 + 云安全组操作均需你定)。