- 架构方案:Redis Pub/Sub 全量消息总线 - WebSocket 连接管理:gorilla/websocket + Hub + 心跳 30s - 联系人模块:好友申请/分组/黑名单/搜索/推荐 - 在线状态:混合推拉方案 - 文档管理策略:按模块拆分,单文件 300-500 行 Made-with: Cursor
7.2 KiB
7.2 KiB
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 认证) |
连接生命周期:
GET /ws?token=xxx→ JWT 认证 → gorilla/websocket 升级- 创建 Client → 注册 Hub → Redis SADD + SET + SUBSCRIBE
- 心跳保活 30s(ping/pong)+ Redis TTL 续期
- 断线 → 注销 Hub → Redis SREM + DEL + UNSUBSCRIBE
技术选型: gorilla/websocket(社区最成熟,虽已归档但稳定可靠)
2.3 消息协议
复用系统设计文档 5.2 节:
// 客户端 → 服务端
{ "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