From c9e52d38955610514cb7d60c12a5177692ec5f46 Mon Sep 17 00:00:00 2001 From: bujinyuan Date: Mon, 2 Mar 2026 16:40:28 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20Phase=202a=20=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=88WebSocket=20+=20=E8=81=94=E7=B3=BB?= =?UTF-8?q?=E4=BA=BA=E7=AE=A1=E7=90=86=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 架构方案:Redis Pub/Sub 全量消息总线 - WebSocket 连接管理:gorilla/websocket + Hub + 心跳 30s - 联系人模块:好友申请/分组/黑名单/搜索/推荐 - 在线状态:混合推拉方案 - 文档管理策略:按模块拆分,单文件 300-500 行 Made-with: Cursor --- docs/plans/2026-03-02-phase2a-design.md | 230 ++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 docs/plans/2026-03-02-phase2a-design.md diff --git a/docs/plans/2026-03-02-phase2a-design.md b/docs/plans/2026-03-02-phase2a-design.md new file mode 100644 index 0000000..0ea0f09 --- /dev/null +++ b/docs/plans/2026-03-02-phase2a-design.md @@ -0,0 +1,230 @@ +# Phase 2a 设计文档:WebSocket 实时通讯与联系人管理 + +> **状态:** 设计确认,开发中 +> **分支:** `feature/phase2a-websocket-contacts` +> **实施计划:** `docs/plans/2026-03-02-phase2a-implementation.md`(独立文件) +> **前置依赖:** Phase 1 全部完成(用户认证 + 管理端用户管理) + +--- + +## 一、设计目标 + +搭建 WebSocket 实时通讯基础设施,实现完整联系人/好友管理功能,为 Phase 2b 即时聊天奠定基础。 + +**核心交付物:** +- WebSocket 长连接(心跳、断线重连、Redis Pub/Sub 消息总线) +- 联系人完整功能(好友申请/分组/黑名单/搜索/推荐) +- 在线状态管理(混合推拉方案) +- 管理端:在线监控 + 好友关系管理 + +--- + +## 二、架构方案 + +### 2.1 消息总线:Redis Pub/Sub 全量路由 + +所有跨用户的实时消息经 Redis Pub/Sub 路由,每个用户拥有独立频道。 + +**消息投递链路:** + +``` +业务层(Service) + ↓ PUBLISH echo:ws:channel:{targetUserID} +Redis Pub/Sub + ↓ SUBSCRIBE +目标实例 Hub + ↓ send chan +目标 Client WebSocket +``` + +**方案选定理由:** +- 天然支持多实例扩展(第三期微服务拆分无需重构) +- 消息路由标准化,所有模块统一使用 Pub/Sub +- 当前单实例阶段性能影响微乎其微(延迟增加 ~0.1-0.5ms) + +### 2.2 WebSocket 连接管理 + +| 组件 | 职责 | +|------|------| +| `pkg/ws/hub.go` | Hub 连接管理(注册/注销/按 userID 查找) | +| `pkg/ws/client.go` | 客户端连接封装(readPump + writePump + 心跳) | +| `pkg/ws/message.go` | 统一消息协议(匹配设计文档 5.2 节) | +| `pkg/ws/pubsub.go` | Redis Pub/Sub 封装(Publish/Subscribe/Unsubscribe) | +| `app/ws/handler.go` | WebSocket 升级处理(JWT 认证) | + +**连接生命周期:** +1. `GET /ws?token=xxx` → JWT 认证 → gorilla/websocket 升级 +2. 创建 Client → 注册 Hub → Redis SADD + SET + SUBSCRIBE +3. 心跳保活 30s(ping/pong)+ Redis TTL 续期 +4. 断线 → 注销 Hub → Redis SREM + DEL + UNSUBSCRIBE + +**技术选型:** `gorilla/websocket`(社区最成熟,虽已归档但稳定可靠) + +### 2.3 消息协议 + +复用系统设计文档 5.2 节: + +```json +// 客户端 → 服务端 +{ "event": "contact.request.send", "seq": 1001, "data": {...}, "time": "2026-03-02 10:30:00" } + +// 服务端 → 客户端(推送) +{ "event": "notify.friend.request", "seq": 0, "data": {...}, "time": "..." } + +// 服务端 → 客户端(ACK) +{ "event": "contact.request.send.ack", "seq": 1001, "code": 0, "message": "ok", "data": {...} } +``` + +事件命名规范:`{模块}.{对象}.{动作}` + +--- + +## 三、联系人模块设计 + +### 3.1 数据模型 + +复用系统设计文档已有表: + +- `contact_friendships` — 好友关系(双向存储,status: 0=待确认, 1=已接受, 2=已拒绝, 3=已拉黑) +- `contact_groups` — 好友分组 + +### 3.2 好友申请流程 + +``` +A 搜索用户 B + ↓ POST /contacts/request +创建 A→B 记录(status=0) + ↓ Redis PUBLISH → B +B 收到 WebSocket 推送 notify.friend.request + ↓ POST /contacts/accept +更新 A→B(status=1)+ 创建 B→A(status=1) + ↓ Redis PUBLISH → A +A 收到 WebSocket 推送 contact.request.accepted + → 双向好友关系建立 +``` + +### 3.3 黑名单机制 + +复用 `contact_friendships.status=3`: +- 拉黑操作:双向删除好友记录 → 新建单向 status=3 记录 +- 被拉黑方无法发送好友申请和消息 +- 取消拉黑:删除 status=3 记录(不自动恢复好友关系) + +### 3.4 REST API + +``` +# 好友关系 +GET /api/v1/contacts 好友列表(含在线状态) +POST /api/v1/contacts/request 发送好友申请 +POST /api/v1/contacts/accept 接受申请 +POST /api/v1/contacts/reject 拒绝申请 +DELETE /api/v1/contacts/:id 删除好友 +PUT /api/v1/contacts/:id/remark 设置备注 +GET /api/v1/contacts/requests 待处理申请列表 + +# 好友分组 +GET /api/v1/contacts/groups 分组列表 +POST /api/v1/contacts/groups 创建分组 +PUT /api/v1/contacts/groups/:id 修改分组 +DELETE /api/v1/contacts/groups/:id 删除分组 +PUT /api/v1/contacts/:id/group 移动好友到分组 + +# 黑名单 +POST /api/v1/contacts/block 拉黑 +DELETE /api/v1/contacts/block/:user_id 取消拉黑 +GET /api/v1/contacts/block 黑名单列表 + +# 搜索与推荐 +GET /api/v1/users/search 搜索用户 +GET /api/v1/contacts/recommend 好友推荐 +``` + +--- + +## 四、在线状态设计 + +### 4.1 混合方案 + +| 场景 | 方式 | 说明 | +|------|------|------| +| 打开联系人页 | REST 拉取 | `GET /api/v1/contacts/online` 批量查询好友在线状态 | +| 好友上/下线 | WS 推送 | 通过 Pub/Sub 推送 `user.status.online`/`offline` | +| 心跳续期 | Redis TTL | `EXPIRE echo:user:status:{userID} 60` | + +### 4.2 Redis 键设计(匹配系统设计文档 4.2 节) + +``` +echo:user:online SET 所有在线用户 ID +echo:user:status:{user_id} STRING 状态 JSON(TTL=60s 心跳续期) +echo:ws:user:{user_id} STRING 连接实例信息 +echo:ws:channel:{user_id} Pub/Sub 频道(消息投递) +``` + +--- + +## 五、管理端扩展 + +### 5.1 新增功能 + +- 仪表盘:实时在线用户数统计卡片 +- 在线用户列表页 +- 好友关系管理页(查看/删除) + +### 5.2 管理端 API + +``` +GET /api/v1/admin/online/users 在线用户列表 +GET /api/v1/admin/online/count 在线用户数 +GET /api/v1/admin/contacts 所有好友关系(分页) +DELETE /api/v1/admin/contacts/:id 管理员解除好友关系 +``` + +--- + +## 六、前台用户端变更 + +### 6.1 WebSocket 客户端 + +- 单例模式,`ws://host/ws?token=xxx` +- 心跳 30s,断线指数退避重连(1s → 2s → 4s → 8s → 30s max) +- 事件分发:`on(event, callback)` / `off(event, callback)` + +### 6.2 新增页面 + +- 联系人列表(替换占位页) +- 好友申请列表 +- 好友详情(备注/分组/删除/拉黑) +- 搜索添加好友 +- 好友分组管理 +- 黑名单 + +--- + +## 七、文档管理策略 + +Phase 2a 开始执行新的文档拆分规则: + +- **每个 Phase 独立设计文档**(本文件) +- **每个 Phase 独立实施计划** +- **API 文档按模块 + 端拆分**(每文件对应一个功能模块) +- **WebSocket 事件协议独立为文档** +- **单文件控制在 300-500 行以内** + +``` +docs/ +├── api/ +│ ├── admin/ +│ │ ├── user.md 已有 +│ │ ├── online.md 新增:在线监控 API +│ │ └── contact.md 新增:好友关系管理 API +│ └── frontend/ +│ ├── auth.md 已有 +│ ├── contact.md 新增:联系人 API +│ └── websocket.md 新增:WebSocket 事件协议 +├── plans/ +│ ├── 2026-02-27-echochat-system-design.md 总设计(蓝图参考) +│ ├── 2026-02-27-phase1-foundation-and-auth.md Phase1(已完成) +│ └── 2026-03-02-phase2a-design.md 本文件 +└── progress/ + └── CURRENT_STATUS.md +```