Files
Edu/services/push-gateway/docs/nextstep.md
SpecialX b745443b6d feat(push-gateway): docker 本地验证通过 + nextstep 上下游依赖文档
- Dockerfile 修复:GOPROXY 国内镜像 + go.mod 路径修正 + 构建目录
- docker-compose.deploy.yml 补全 push-gateway 全部 12 个环境变量
- deploy.env.example 新增 push-gateway 段(INTERNAL_API_TOKEN/WS_ALLOWED_ORIGINS)
- 本地 Docker 验证通过(非 mock):
  - /healthz + /readyz(Redis + Kafka 健康)
  - WebSocket /ws + dev-token 鉴权
  - /internal/push HTTP API 投递 3 类考试事件
  - Kafka → push-gateway → WebSocket 全链路透传
    ExamExtended / ExamForceSubmitted / ExamQuestionReordered
- 新增 docs/nextstep.md:上游依赖(iam/Redis/Kafka)+
  下游依赖(4 portal + msg)+ 事件投递架构图 + 环境变量清单
2026-07-13 17:56:28 +08:00

12 KiB
Raw Permalink Blame History

push-gateway 下一步工作与上下游依赖

模块push-gatewayWebSocket 实时推送网关L3 基础设施) 负责人ai09 更新日期2026-07-13 关联文档:02-architecture-design.md · push-gateway_workline.md


1. 模块当前状态

push-gateway 的 P1P6 全部批次已完成并经本地 Docker 验证通过(非 mock 数据)。

能力 状态 验证方式
WebSocket /ws 端点JWT RS256 + DevMode dev-token 完成 Docker 容器本地测试
/internal/push HTTP APIX-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

测试环境:本地 Dockeredu-redis + edu-kafka + edu-push-gateway-test 容器,均接入 edu-full_default 网络)

镜像edu/push-gateway:test63.2MB
容器edu-push-gateway-testDEV_MODE=true

测试 1健康检查
  GET /healthz  → {"service":"push-gateway","status":"ok"} ✅
  GET /readyz   → {"status":"ok","degraded":false,"dependencies":{"kafka":{"ok":true},"redis":{"ok":true}}} ✅

测试 2HTTP /internal/push → WebSocket 投递
  WS 客户端连接 ws://localhost:8081/ws?token=dev-token → 连接成功 ✅
  POST /internal/push × 3ExamExtended / ExamForceSubmitted / ExamQuestionReordered
    → 三个事件均 delivered=trueWS 客户端全部收到 ✅

测试 3Kafka → WebSocket 投递
  Kafka producer → topic edu.notification.requested × 3 条消息
    → push-gateway 消费 → WS 客户端全部收到 ✅
  指标push_gateway_kafka_consumed_total = 3 ✅

测试 4在线状态查询
  GET /internal/online/dev-user无连接 → {"online":false} ✅

2. 上游依赖push-gateway 依赖谁)

push-gateway 作为 L3 基础设施网关,运行时依赖以下服务/组件:

2.1 iamai01— 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:29092KAFKA_NOTIFICATION_TOPIC=edu.notification.requestedKAFKA_CONSUMER_GROUP=push-gateway
消费策略 Consumer Group push-gatewayStartOffset=LastOffset首次启动跳过历史积压
幂等性 event_id Redis SETNX 去重24h TTL
DLQ 失败 3 次后投递到 edu.notification.requested.dlq
降级策略 Kafka 不可用时 /readyz 标记 degradedHTTP /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-portalai13— 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-portalai14— 考试实时事件

内容
依赖内容 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-portalai15— WebSocket 通知

内容
依赖内容 WebSocket /ws 端点
当前状态 push-gateway /ws 已标记就绪parent-portal nextstep.md §6 确认)
portal 需求来源 apps/parent-portal/docs/nextstep.md §6

3.4 admin-portalai16— 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 关注)

┌──────────────┐     gRPC/HTTP      ┌──────────┐   Outbox→Kafka   ┌─────────────┐
│ core-edu     │ ──────────────────→ │   msg    │ ──────────────→ │   Kafka     │
│ (考试业务)   │  ExamExtended 等    │ (ai10)   │  edu.notification│ (edu-kafka) │
└──────────────┘                     └──────────┘ .requested      └──────┬──────┘
                                                                        │ consume
                                                                        ▼
┌──────────────┐  WS /ws?token=JWT   ┌──────────────────┐   Redis    ┌─────────────┐
│ 4× portal    │ ←────────────────── │  push-gateway    │ ←────────→ │  edu-redis  │
│ (前端)       │  事件透传(event字段) │  (ai09, 本模块)  │  Pub/Sub   │  (在线状态) │
└──────────────┘                     └──────────────────┘            └─────────────┘

关键设计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-portalai13 push-gateway 就绪 待 portal 执行
student-portal 接入考试事件 WS student-portalai14 push-gateway 就绪 + msg 发出考试事件 待 msg + portal 联调
parent-portal 接入 WS parent-portalai15 push-gateway 就绪 待 portal 执行
admin-portal WS 实时通知联调 admin-portalai16 push-gateway 就绪 待 portal 执行
msg 服务接入 /internal/push msgai10 push-gateway 就绪 待 msg 执行
iam JWKS 端点就绪 iamai01 生产环境必需DevMode 可旁路
Redis 生产部署 SRE P6.1 限流迁移依赖