push-gateway 下一步工作与上下游依赖
模块:push-gateway(WebSocket 实时推送网关,L3 基础设施)
负责人:ai09
更新日期:2026-07-13
关联文档:02-architecture-design.md · push-gateway_workline.md
1. 模块当前状态
push-gateway 的 P1–P6 全部批次已完成并经本地 Docker 验证通过(非 mock 数据)。
| 能力 |
状态 |
验证方式 |
WebSocket /ws 端点(JWT RS256 + DevMode dev-token) |
✅ 完成 |
Docker 容器本地测试 |
/internal/push HTTP API(X-Internal-Token 鉴权) |
✅ 完成 |
curl + WS 客户端联调 |
/internal/broadcast 广播 API |
✅ 完成 |
代码实现 + 单元测试 |
/internal/online/:userID 在线查询 |
✅ 完成 |
curl 验证 |
Kafka 消费 edu.notification.requested |
✅ 完成 |
Kafka producer → WS 客户端联调 |
| Redis Pub/Sub 跨实例消息扇出 |
✅ 完成 |
容器连接 edu-redis 验证 |
| Redis 在线状态 SET + 启动重建(ISSUE-058) |
✅ 完成 |
/readyz 返回 redis ok |
| P6 Reconnect 协议(session_id + last_seq + ring buffer 100 条/用户) |
✅ 完成 |
代码实现 + 单元测试 |
| 幂等性(event_id Redis SETNX 24h 去重) |
✅ 完成 |
Kafka 重复消息测试 |
| /healthz + /readyz(软失败探活) |
✅ 完成 |
curl 验证 |
| /metrics Prometheus 指标 |
✅ 完成 |
curl 验证 |
| Docker 多阶段构建(golang:1.25-alpine → alpine:3.20) |
✅ 完成 |
docker build 成功 |
| 事件透传(event_type 字段无需硬编码) |
✅ 完成 |
3 类考试事件 Kafka→WS 验证 |
1.1 本地 Docker 验证结果(2026-07-13)
测试环境:本地 Docker(edu-redis + edu-kafka + edu-push-gateway-test 容器,均接入 edu-full_default 网络)
2. 上游依赖(push-gateway 依赖谁)
push-gateway 作为 L3 基础设施网关,运行时依赖以下服务/组件:
2.1 iam(ai01)— JWT RS256 公钥
| 项 |
内容 |
| 依赖内容 |
iam /.well-known/jwks.json 端点提供 RS256 公钥 |
| 端点 |
GET http://iam:3002/v1/iam/.well-known/jwks.json |
| 用途 |
WebSocket /ws 连接时校验客户端 JWT 签名(RS256) |
| 当前状态 |
DevMode 下使用 dev-token 旁路,生产环境需要 iam 就绪 |
| 缓存策略 |
shared-go/jwks Fetcher 每 5 分钟刷新 JWKS 缓存 |
| 环境变量 |
JWKS_URL=http://iam:3002/v1/iam/.well-known/jwks.json |
2.2 Redis(基础设施)— 在线状态 + 跨实例消息扇出
| 项 |
内容 |
| 依赖内容 |
Redis SET(在线用户→实例映射)+ Pub/Sub(跨实例消息扇出) |
| 端点 |
redis://edu-redis:6379 |
| 用途 |
1) 多实例在线状态同步 2) 跨实例 WebSocket 消息投递 3) event_id 幂等去重(SETNX 24h TTL) |
| 当前状态 |
✅ 本地 Docker edu-redis 已就绪并验证通过 |
| 环境变量 |
REDIS_URL=redis://edu-redis:6379 |
| 降级策略 |
Redis 不可用时 /readyz 标记 degraded 但不返回 503(软失败,ARB-015 §17.4) |
2.3 Kafka(基础设施)— 通知事件消费
| 项 |
内容 |
| 依赖内容 |
Kafka topic edu.notification.requested 消费 |
| 端点 |
kafka:29092(容器内 INSIDE listener) |
| 用途 |
消费 msg 服务发出的 NotificationRequested 事件,投递到在线用户的 WebSocket |
| 当前状态 |
✅ 本地 Docker edu-kafka 已就绪并验证通过 |
| 环境变量 |
KAFKA_BROKERS=kafka:29092、KAFKA_NOTIFICATION_TOPIC=edu.notification.requested、KAFKA_CONSUMER_GROUP=push-gateway |
| 消费策略 |
Consumer Group push-gateway,StartOffset=LastOffset(首次启动跳过历史积压) |
| 幂等性 |
event_id Redis SETNX 去重,24h TTL |
| DLQ |
失败 3 次后投递到 edu.notification.requested.dlq |
| 降级策略 |
Kafka 不可用时 /readyz 标记 degraded,HTTP /internal/push 仍可用 |
2.4 OTel Collector(基础设施)— 可观测性
| 项 |
内容 |
| 依赖内容 |
OpenTelemetry trace 上报 |
| 端点 |
http://otel-collector:4318(本地使用 edu-jaeger:4318) |
| 当前状态 |
可选依赖,初始化失败时 tracing 自动禁用(不影响业务) |
| 环境变量 |
OTEL_EXPORTER_OTLP_ENDPOINT |
3. 下游依赖(谁依赖 push-gateway)
以下 4 个前端 portal 模块和 1 个后端服务依赖 push-gateway:
3.1 teacher-portal(ai13)— WebSocket 通知通道
| 项 |
内容 |
| 依赖内容 |
WebSocket /ws 端点,用于 /notifications 页面实时推送 |
| 端点 |
ws://push-gateway:8081/ws?token=<JWT> |
| 事件类型 |
通知类事件(由 msg 服务通过 Kafka 发出,push-gateway 透传) |
| 当前状态 |
✅ push-gateway 已就绪,等待 teacher-portal 切换 MSW mock → 真实 WS |
| portal 需求来源 |
apps/teacher-portal/nextstep.md §2.3 |
3.2 student-portal(ai14)— 考试实时事件
| 项 |
内容 |
| 依赖内容 |
WebSocket /ws 端点,接收考试实时事件 |
| 端点 |
ws://push-gateway:8081/ws?token=<JWT> |
| 需要的事件类型 |
ExamExtended(教师延长考试)、ExamForceSubmitted(教师强制收卷)、ExamQuestionReordered(教师调整题目顺序) |
| 当前状态 |
✅ 已验证:3 类考试事件经 Kafka → push-gateway → WebSocket 全链路投递成功 |
| 事件来源 |
msg 服务(ai10)通过 Outbox → Kafka edu.notification.requested 发出 |
| 透传机制 |
push-gateway 从 Kafka 消息的 event_type 字段读取事件类型,作为 WebSocket 消息的 event 字段透传,无需在 push-gateway 中硬编码事件类型 |
| portal 需求来源 |
apps/student-portal/docs/nextstep.md §3 |
3.3 parent-portal(ai15)— WebSocket 通知
| 项 |
内容 |
| 依赖内容 |
WebSocket /ws 端点 |
| 当前状态 |
✅ push-gateway /ws 已标记就绪(parent-portal nextstep.md §6 确认) |
| portal 需求来源 |
apps/parent-portal/docs/nextstep.md §6 |
3.4 admin-portal(ai16)— WebSocket 实时通知联调
| 项 |
内容 |
| 依赖内容 |
WebSocket /ws 端点,管理端实时通知联调 |
| 当前状态 |
✅ push-gateway 已就绪,等待 admin-portal 联调 |
| portal 需求来源 |
apps/admin-portal/docs/nextstep.md §3.5 |
3.5 msg 服务(ai10)— /internal/push HTTP API
| 项 |
内容 |
| 依赖内容 |
POST /internal/push(定向推送)、POST /internal/broadcast(广播)、GET /internal/online/:userID(在线查询) |
| 端点 |
http://push-gateway:8081/internal/* |
| 鉴权 |
X-Internal-Token 头(生产环境),DevMode 跳过 |
| 当前状态 |
✅ 全部 API 已实现并验证 |
| 环境变量(msg 侧) |
PUSH_GATEWAY_URL=http://push-gateway:8081 |
4. 事件投递架构(portal 关注)
关键设计:push-gateway 不硬编码事件类型。Kafka 消息中的 event_type 字段被原样作为 WebSocket 消息的 event 字段透传给前端。前端根据 event 字段路由处理。这意味着:
- 新增事件类型无需修改 push-gateway
- msg 服务只需在 Kafka 消息中设置正确的
event_type
- 前端在 WebSocket 消息回调中按
event 字段分发
5. 环境变量清单(Docker 部署)
| 变量 |
必填 |
示例值 |
说明 |
PUSH_GATEWAY_PORT |
是 |
8081 |
HTTP 监听端口 |
JWT_SECRET |
生产必填 |
— |
DevMode 自动使用 dev 默认值 |
DEV_MODE |
否 |
false |
true 时跳过 JWT/InternalToken 校验 |
REDIS_URL |
是 |
redis://edu-redis:6379 |
Redis 连接地址 |
KAFKA_BROKERS |
是 |
kafka:29092 |
Kafka broker 地址(逗号分隔) |
KAFKA_NOTIFICATION_TOPIC |
是 |
edu.notification.requested |
消费的 Kafka topic |
KAFKA_CONSUMER_GROUP |
是 |
push-gateway |
Consumer Group ID |
INTERNAL_API_TOKEN |
生产必填 |
— |
/internal/* API 鉴权 token |
JWKS_URL |
是 |
http://iam:3002/v1/iam/.well-known/jwks.json |
iam JWKS 端点 |
WS_ALLOWED_ORIGINS |
是 |
http://localhost:3000,... |
WebSocket 允许的 Origin 白名单 |
MAX_CONNS_PER_USER |
否 |
5 |
每用户最大连接数 |
HEARTBEAT_INTERVAL_SECONDS |
否 |
30 |
心跳间隔 |
OTEL_EXPORTER_OTLP_ENDPOINT |
否 |
http://otel-collector:4318 |
OTLP 上报端点 |
6. 剩余工作
push-gateway 模块自身功能已全部完成,无剩余开发任务。以下为联调阶段事项:
| 任务 |
负责方 |
依赖 |
状态 |
| teacher-portal 切换 MSW mock → 真实 WS |
teacher-portal(ai13) |
push-gateway 就绪 ✅ |
待 portal 执行 |
| student-portal 接入考试事件 WS |
student-portal(ai14) |
push-gateway 就绪 ✅ + msg 发出考试事件 |
待 msg + portal 联调 |
| parent-portal 接入 WS |
parent-portal(ai15) |
push-gateway 就绪 ✅ |
待 portal 执行 |
| admin-portal WS 实时通知联调 |
admin-portal(ai16) |
push-gateway 就绪 ✅ |
待 portal 执行 |
| msg 服务接入 /internal/push |
msg(ai10) |
push-gateway 就绪 ✅ |
待 msg 执行 |
| iam JWKS 端点就绪 |
iam(ai01) |
— |
生产环境必需,DevMode 可旁路 |
| Redis 生产部署 |
SRE |
— |
P6.1 限流迁移依赖 |