feat(server): WebSocket 广播支持 Redis Pub/Sub 跨节点扇出(REDIS_ADDR 可选开关)

- 新增 ws.EventBus 接口与 RedisBus 实现;Hub 五类广播改为发布信封、各节点订阅后本地投递
- 单实例不设 REDIS_ADDR 保持进程内直投;Redis 不可用时自动兜底本地投递
- config 新增 REDIS_ADDR/REDIS_PASSWORD/REDIS_DB;dev compose 增加 --profile redis (6380)
- prod compose 与 .env.prod.example 增加多副本配置说明;README 更新已知边界
- 已用双实例 + 真实 Redis 实测跨节点推送;新增总线单测(含发布失败兜底),-race 通过
This commit is contained in:
yml2213
2026-09-05 14:39:56 +08:00
parent 8b9f3d710f
commit 10d2e2ed3d
11 changed files with 430 additions and 6 deletions
+6 -4
View File
@@ -61,7 +61,7 @@
| 后端 | Go、Gin、GORM、JWT、Gorilla WebSocket |
| 数据库 | PostgreSQL(生产/开发主库);测试可用 SQLite |
| 存储 | MinIO(S3 兼容),图片转 WebP |
| 实时 | 进程内 WebSocket Hub(单实例;多副本需后续 Redis 广播) |
| 实时 | 进程内 WebSocket Hub;多 API 副本时通过 `REDIS_ADDR` 启用 Redis Pub/Sub 跨节点广播 |
### 消息链路(简要)
@@ -211,6 +211,8 @@ make db-up
| `STORAGE_ACCESS_KEY` / `STORAGE_SECRET_KEY` | `minioadmin` | |
| `STORAGE_BUCKET` | `kefu` | |
| `STORAGE_PUBLIC_BASE_URL` | `http://localhost:9100/kefu` | 浏览器访问前缀 |
| `REDIS_ADDR` | 空 | 为空=单实例进程内广播;设置后 WS 广播走 Redis Pub/Sub 跨节点扇出 |
| `REDIS_PASSWORD` / `REDIS_DB` | 空 / `0` | 与 `REDIS_ADDR` 配合使用 |
---
@@ -270,8 +272,8 @@ cd web && npx tsc --noEmit
| 项 | 说明 |
|----|------|
| 多 API 实例 | Hub 为进程内存;扩副本需 Redis Pub/Sub 等跨节点广播 |
| 独立消息队列 | 当前不需要;实时靠 WS Hub |
| 多 API 实例 | 设置 `REDIS_ADDR` 后 Hub 广播经 Redis Pub/Sub 跨节点扇出(各节点本地投递、连接仍节点本地,需入口层 sticky/共享连接);单实例无需 Redis |
| 独立消息队列 | 当前不需要;实时靠 WS Hub(+ 可选 Redis 广播) |
| 技能组 / 渠道专属坐席 | 未做;可在候选过滤层扩展 |
| 厂商推送(APNs/FCM) | 未做 |
| 微信/APP/电话渠道 | 模型预留,完整对接未做 |
@@ -279,7 +281,7 @@ cd web && npx tsc --noEmit
### 建议演进顺序
1. 生产配置加固(JWT、HTTPS、存储与 DB 备份)
2. 需要水平扩展时:Redis 会话广播 + sticky 或共享连接层
2. 需要水平扩展时:`REDIS_ADDR` 启用跨节点广播 + sticky 或共享连接层(已内置)
3. 技能组 / 渠道路由
4. 监控可对接 Prometheus(现有 metrics 可作过渡)