Files
Edu/docs/architecture/issues/worklines/api-gateway_workline.md

19 KiB
Raw Blame History

api-gateway 工作排期

负责人ai01 关联:workline.mdcoord.mdcontracts/api-gateway_contract.mdobjections/api-gateway_issue.md 模式:全并行(各 AI 一口气完成 P2-P6 全部代码,最后统一集成测试) 依据:coord-final-decisions.md §3.8 W1-W8、president-final-rulings.md §2.15/§2.16/§2.19、02-architecture-design.md §9


§1 总览

api-gateway 是 Edu 系统统一入口L3 网关层负责路由转发、JWT RS256 验签、限流、熔断、CORS、可观测性。无业务状态纯 HTTP 反向代理。

全阶段目标

  • P2:路由表 + JWT RS256HTTP JWKS + shared-go 接入 + 错误码 GW_ 前缀 + ActionState 信封 + slog + /readyz 真实检查 + 业务 metrics + tracer 资源属性 + DevMode 防护(遵循 W1-W8 / G1-G17 裁决)
  • P3路由扩展student-bff :3009+ core-edu 路由
  • P4路由扩展parent-bff :3010+ content / data-ana 路由
  • P5路由扩展msg / ai 路由)+ 接入 push-gateway 协作WebSocket 升级透传评估)
  • P6:限流迁 Redis + per-服务实例熔断评估 + 测试覆盖率 ≥ 80% + 安全加固

当前状态2026-07-10P1 已交付classes 域 CRUD 端到端跑通P2 升级未启动。已有仲裁核查发现 6 项未遵循裁决(见 objections/api-gateway_issue.md §0.4)。


§2 全阶段甘特图P2-P6

gantt
    title ai01 api-gateway 全阶段排期P2-P6
    dateFormat YYYY-MM-DD
    axisFormat %m-%d

    section P2 基础升级批次1
    P2.0 修复P0遗留 :crit, p2a, 2026-07-10, 1d
    P2.1 shared-go接入 :crit, p2b, after p2a, 2d
    P2.2 JWT RS256+JWKS :crit, p2c, after p2b, 3d
    P2.3 错误码GW_+ActionState :crit, p2d, after p2c, 1d
    P2.4 slog+metrics+tracer :crit, p2e, after p2d, 2d
    P2.5 /readyz真实检查 :crit, p2f, after p2e, 1d
    P2.6 DevMode防护 :p2g, after p2f, 1d
    P2.7 路由表扩展iam/teacher :p2h, after p2g, 1d

    section P3 路由扩展批次2
    P3.1 student-bff路由 :p3a, after p2h, 1d
    P3.2 core-edu路由 :p3b, after p3a, 1d
    P3.3 API版本化/v1迁移 :p3c, after p3b, 2d

    section P4 路由扩展批次3
    P4.1 parent-bff路由 :p4a, after p3c, 1d
    P4.2 content路由 :p4b, after p4a, 1d
    P4.3 data-ana路由 :p4c, after p4b, 1d

    section P5 路由扩展批次4
    P5.1 msg路由 :p5a, after p4c, 1d
    P5.2 ai路由 :p5b, after p5a, 1d
    P5.3 push-gateway协作评估 :p5c, after p5b, 2d

    section P6 硬化批次5
    P6.1 限流迁Redis :p6a, after p5c, 3d
    P6.2 per-服务熔断评估 :p6b, after p6a, 2d
    P6.3 测试覆盖率80% :p6c, after p6b, 3d
    P6.4 安全加固 :p6d, after p6c, 2d

关键路径(红色 critP2.0 → P2.1 → P2.2 → P2.3 → P2.4 → P2.5 → P2.6 → P2.7 总时间线P2 约 11 天 + P3-P5 约 9 天 + P6 约 10 天 = 约 30 天


§3 详细任务

P2.0:修复 P0 遗留问题

  • 负责人ai01
  • 依赖:无
  • 交付物
    • services/api-gateway/go.mod L3 改为 go 1.22(修复 ISSUE-005
    • go.work L1 改为 go 1.22
    • 删除 01-understanding.md §7.1 issue #3 死代码引用ISSUE-008
    • 修正 01-understanding.md §6 审计表 metrics 行ISSUE-007
    • 修正 README.md L38 删除不存在的 /health 兼容端点描述
    • 修正 proxy.go L24 删除冗余 TrimPrefix("/api")
  • 验收标准go build ./... + go vet ./... 通过;文档与代码一致
  • 对应 ISSUEISSUE-005 / ISSUE-007 / ISSUE-008

P2.1shared-go 包接入

  • 负责人ai01
  • 依赖packages/shared-go 已建立(批次 0 已完成coord 仲裁 ISSUE-002 / ISSUE-004
  • 交付物
    • go.work 增加 ./packages/shared-go
    • services/api-gateway/go.mod 增加 github.com/edu-cloud/shared-go 依赖
    • 按 ISSUE-004 仲裁结果接入 shared-go/loggerzap 或 slog取决于 coord 裁决)
    • tracer.go 评估接入 shared-go/tracer若接口兼容
    • config.go 评估接入 shared-go/env
  • 验收标准go build ./... 通过import shared-go 成功logger 输出结构化 JSON
  • 对应 ISSUEISSUE-002 / ISSUE-004

P2.2JWT RS256 升级 + JWKS 缓存

  • 负责人ai01
  • 依赖iam (ai06) 暴露 GET /.well-known/jwks.json HTTP 端点coord 仲裁 ISSUE-001确认 HTTP JWKS
  • 交付物
    • auth.go 改用 shared-go/jwks.Fetcherjwks.NewFetcher(cfg.JWKSURL)
    • HS256 逻辑废弃,cfg.JWTSecret 仅 DevMode 下用作 mock 密钥
    • JWKS 缓存策略TTL 5minshared-go/jwks 默认kid 未命中时强制刷新,刷新失败保留旧公钥
    • 启动时同步拉取一次 JWKS失败则 panic 拒绝启动
    • claims 增加 data_scope 字段提取,注入 x-data-scope
    • internal/config/config.go 增加 JWKSURL 字段(环境变量 IAM_JWKS_URL
  • 验收标准JWT RS256 验签通过JWKS 缓存命中率达 99%+kid 未命中自动刷新
  • 对应裁决W1错误码加 GW_ 前缀、§2.16HTTP JWKS非 gRPC

P2.3:错误码 GW_ 前缀 + ActionState 信封

  • 负责人ai01
  • 依赖:无
  • 交付物
    • auth.go 错误码改为 GW_UNAUTHORIZED / GW_INVALID_TOKEN / GW_INVALID_CLAIMS
    • ratelimit.go 响应体改为 {success:false,error:{code:"GW_RATE_LIMITED",message:"...",retry_after:60}}
    • circuit-breaker.go 响应体改为 {success:false,error:{code:"GW_CIRCUIT_OPEN",message:"...",retry_after:30}}
    • recovery.go 响应体改为 {success:false,error:{code:"GW_INTERNAL_ERROR",message:"...",request_id:"..."}}
    • RequestBodyLimit 超限响应改为 {success:false,error:{code:"GW_REQUEST_TOO_LARGE",message:"..."}}
  • 验收标准:所有错误响应符合 ActionState 信封;错误码统一 GW_ 前缀
  • 对应裁决W1 / W2 / G14
  • 对应 ISSUEISSUE-009

P2.4slog + 业务 metrics + tracer 资源属性

  • 负责人ai01
  • 依赖P2.1 shared-go 接入完成
  • 交付物
    • 按 ISSUE-004 仲裁结果统一 loggerzap 或 slog
    • 所有 log.Printf / log.Println / log.Fatal 改为结构化日志(带 request_id / trace_id / user_id / method / path / status / latency_ms 字段)
    • 新增 internal/observability/metrics.go,注册 7 个业务指标:
      • api_gateway_http_requests_totalCountermethod/endpoint/status
      • api_gateway_http_request_duration_secondsHistogrammethod/endpoint
      • api_gateway_circuit_breaker_stateGaugeservice/state
      • api_gateway_rate_limited_totalCounterip
      • api_gateway_proxy_upstream_duration_secondsHistogramupstream
      • api_gateway_jwks_refresh_totalCounterresult
      • api_gateway_auth_failures_totalCounterreason
    • tracer.go 资源属性补全:service.name + service.version(编译时注入)+ deployment.environmentENV 变量)+ host.name
    • Metrics 中间件:在 Auth 之后、CircuitBreaker 之前注册(统计通过鉴权的请求)
  • 验收标准/metrics 端点返回 7 个业务指标;日志为 JSON 结构化tracer 资源属性完整
  • 对应裁决W3 / W5 / W6 / G4 / G5 / G6

P2.5/readyz 真实健康检查

  • 负责人ai01
  • 依赖:所有下游服务实现 /healthzP2 阶段 iam / teacher-bff 已就绪)
  • 交付物
    • health.go Readyz 重构为并行 ping 下游 /healthz
    • 下游清单从 cfg.ServicesURL 动态读取iam / classes / teacher-bff / core-edu / content / msg / ai / data-ana
    • 超时 2s任一不可达返回 503 + {"status":"error","unhealthy":["iam","core-edu"]}
    • 全部可达返回 200 + {"status":"ok"}
    • 可选依赖软失败规则:未启用 gRPC 的下游P3-P5 阶段未就绪的服务)失败仅告警,返回 200 + degraded: true(依据 president-final-rulings.md §3.3
  • 验收标准/readyz 真实检查下游;某服务下线时返回 503
  • 对应裁决W4 / G2

P2.6DevMode 生产防护

  • 负责人ai01
  • 依赖:无
  • 交付物
    • config.go Load() 增加 ENV 环境变量读取
    • DevMode=true && ENV=productionpanic 拒绝启动
    • 启动日志打印 ENV / DevMode 状态
  • 验收标准DEV_MODE=true ENV=production 启动失败;DEV_MODE=true ENV=development 启动成功
  • 对应裁决W7

P2.7路由表扩展iam / teacher

  • 负责人ai01
  • 依赖coord 仲裁 ISSUE-003API 版本化路由规则iam (ai06) / teacher-bff (ai03) P2 就绪
  • 交付物
    • 按 ISSUE-003 仲裁结果更新路由(方案 A/B/C 之一)
    • 若方案 Aiam 路由改为 /api/v1/iam/v1/*pathproxy 透传 /iam/v1/*path
    • teacher-bff 路由保持 /api/v1/teacher/*path
    • 02-architecture-design.md §4.1 路由表同步更新
  • 验收标准:路由表与代码一致;前端调用 /api/v1/iam/v1/auth/login 透传到 iam 服务
  • 对应裁决§2.15

P3.1student-bff 路由

  • 负责人ai01
  • 依赖student-bff (ai04) P3 就绪
  • 交付物
    • main.go 增加 student-bff 路由:/api/v1/student + /api/v1/student/*pathcfg.StudentBffURL:3009
    • config.go 增加 StudentBffURL 字段(环境变量 STUDENT_BFF_URL
  • 验收标准/api/v1/student/* 代理到 student-bff:3009

P3.2core-edu 路由

  • 负责人ai01
  • 依赖core-edu (ai08) P3 就绪classes 服务已合并入 core-eduC1 裁决)
  • 交付物
    • main.go classes 路由目标改为 core-educfg.ClassesServiceURLcfg.CoreEduServiceURL
    • 或保留 classes 路由别名proxy 到 core-edu
    • exams / homework / grades 路由已在 P1 实现,无需修改
  • 验收标准/api/v1/classes/* 代理到 core-edu:3004

P3.3API 版本化 /v1 迁移

  • 负责人ai01
  • 依赖P2.7 路由规则仲裁结果core-edu (ai08) P3 就绪
  • 交付物
    • 按 ISSUE-003 仲裁结果,全服务路由统一加 /v1 前缀
    • core-edu 路由:/api/v1/exams/v1/*path 等(若方案 A
    • 更新 02-architecture-design.md §4.1 路由表
  • 验收标准:所有业务路由含 /v1 版本前缀

P4.1parent-bff 路由

  • 负责人ai01
  • 依赖parent-bff (ai05) P4 就绪
  • 交付物
    • main.go 增加 parent-bff 路由:/api/v1/parent + /api/v1/parent/*pathcfg.ParentBffURL:3010
    • config.go 增加 ParentBffURL 字段
  • 验收标准/api/v1/parent/* 代理到 parent-bff:3010

P4.2content 路由

  • 负责人ai01
  • 依赖content (ai09) P4 就绪
  • 交付物
    • main.go 已有 content 路由P1 实现textbooks / chapters / knowledge-points / questions
    • 验证路由目标 cfg.ContentServiceURL:3005正确
    • 按 P3.3 版本化规则加 /v1 前缀
  • 验收标准content 路由可用 + 版本化

P4.3data-ana 路由

  • 负责人ai01
  • 依赖data-ana (ai11) P4 就绪
  • 交付物
    • main.go 已有 data-ana 路由P1 实现analytics
    • 增加 dashboard 路由别名:/api/v1/dashboard + /*path → data-ana
    • 按版本化规则加 /v1 前缀
  • 验收标准data-ana 路由可用 + dashboard 别名可用

P5.1msg 路由

  • 负责人ai01
  • 依赖msg (ai10) P5 就绪
  • 交付物
    • main.go 已有 msg 路由P1 实现notifications
    • 增加 messages 路由别名:/api/v1/messages + /*path → msg
    • 按版本化规则加 /v1 前缀
  • 验收标准msg 路由可用 + messages 别名可用

P5.2ai 路由

  • 负责人ai01
  • 依赖ai (ai12) P5 就绪
  • 交付物
    • main.go 已有 ai 路由P1 实现)
    • 按版本化规则加 /v1 前缀
  • 验收标准ai 路由可用

P5.3push-gateway 协作评估

  • 负责人ai01
  • 依赖push-gateway (ai02) P5 就绪
  • 交付物
    • 评估 WebSocket 升级请求是否需要 Gateway 透传到 push-gateway
    • 若需要:增加 /ws + /sse 路由透传到 push-gateway:8081
    • 若不需要:文档说明 WebSocket 直连 push-gateway不经过 Gateway
    • 更新 02-architecture-design.md §7 交互点清单
  • 验收标准WebSocket 推送链路可用(透传或直连)

P6.1:限流迁 Redis

  • 负责人ai01
  • 依赖Redis 基础设施就绪
  • 交付物
    • ratelimit.go 改用 Redis 令牌桶(github.com/go-redis/redis_rate/v10
    • 支持多副本一致限流
    • 增加用户级限流(基于 x-user-id 头)
    • 登录接口额外加用户级限流(防爆破)
    • 保留 DevMode 下内存令牌桶回退
  • 验收标准:多副本部署时限流一致;用户级限流生效

P6.2per-服务实例熔断评估

  • 负责人ai01
  • 依赖P6.1 完成
  • 交付物
    • 评估是否将共享 downstream 熔断器拆分为 per-服务实例iam / core-edu / teacher-bff 等)
    • 若拆分:每个下游服务独立熔断状态,互不影响
    • 若不拆分:保持 W8 裁决现状,文档说明理由
    • 按 W8 裁决,此项 P6 单独评估,不强制拆分
  • 验收标准:评估报告 + 决策记录

P6.3:测试覆盖率 80%

  • 负责人ai01
  • 依赖P2-P5 全部完成
  • 交付物
  • 验收标准go test ./... -cover 覆盖率 ≥ 80%

P6.4:安全加固

  • 负责人ai01
  • 依赖P6.1-P6.3 完成
  • 交付物
    • 评估 IP 黑名单 / WAF 规则是否在 Gateway 层实现(建议在 Istio 层做,本服务不介入)
    • 限流策略表 per-路由细化02 §4.2
    • 熔断阈值 per-服务配置02 §4.3
    • CORS 白名单生产环境强制配置(禁止 *
    • 审计日志:记录所有 401 / 403 / 429 / 503 响应
  • 验收标准:安全扫描通过;审计日志可追溯

§4 依赖与就绪信号

4.1 我依赖的上游就绪标志

上游 就绪标志 阶段 状态
coord shared-go 包骨架tracer/logger/jwks/env 批次 0 已完成
coord ISSUE-001 仲裁JWKS vs gRPC P2 启动前 待仲裁
coord ISSUE-002 仲裁shared-go 接入) P2 启动前 待仲裁
coord ISSUE-003 仲裁API 版本化路由) P2.7 前 待仲裁
coord ISSUE-004 仲裁zap vs slog P2.1 前 待仲裁
iam (ai06) GET /.well-known/jwks.json HTTP 端点 + RS256 签发 P2
iam (ai06) gRPC 50052 启用(不影响 GatewayGateway 走 HTTP P2
teacher-bff (ai03) POST /graphql :3003 启用 P2
student-bff (ai04) POST /graphql :3009 启用 P3
core-edu (ai08) gRPC 50053 启用 + classes 合并 P3
parent-bff (ai05) POST /graphql :3010 启用 P4
content (ai09) gRPC 50054 启用 P4
data-ana (ai11) gRPC 50055 启用 P4
msg (ai10) gRPC 50056 启用 P5
ai (ai12) gRPC 50058 启用 P5
push-gateway (ai02) :8081 启用 + /internal/push P5

4.2 我的就绪标志(供下游消费)

阶段 就绪标志 状态
P2 api-gateway :8080 可访问 + JWT RS256 验签可用 + 7 个业务指标 + /readyz 真实检查
P2 /api/v1/iam/* + /api/v1/teacher/* 路由可用
P3 /api/v1/student/* + /api/v1/exams/* 等路由可用
P4 /api/v1/parent/* + /api/v1/textbooks/* + /api/v1/analytics/* 路由可用
P5 /api/v1/notifications/* + /api/v1/ai/* 路由可用
P6 限流迁 Redis + 测试覆盖率 ≥ 80%

§5 风险与应对

风险 概率 影响 应对
coord 仲裁延期ISSUE-001/002/003/004 P2 阻塞 ai01 先按 HTTP JWKS + shared-go + 方案 A 推进,仲裁后调整
iam JWKS 端点延期 P2.2 阻塞 DevMode 下用本地 mock RS256 公钥(与 mock 私钥配对)
shared-go 接口不兼容 P2.1 阻塞 ai01 自行适配,或反馈 coord 修改 shared-go
下游服务未实现 /healthz /readyz 误报 软失败规则:未就绪服务失败仅告警,返回 200 + degraded
JWKS 缓存过期时 iam 不可达 全量 401 fail-open 1 次后 fail-close监控 jwks_refresh_total 指标
DevMode 旁路误开到生产 鉴权绕过 P2.6 生产防护W7 裁决)

§6 与其他模块的协作

模块 协作内容 时机
iam (ai06) JWKS HTTP 端点 + JWT RS256 签发 P2
teacher-bff (ai03) 反向代理 :3003 GraphQL P2
student-bff (ai04) 反向代理 :3009 GraphQL P3
parent-bff (ai05) 反向代理 :3010 GraphQL P4
core-edu (ai08) 反向代理 :3004 + classes 合并 P3
content (ai09) 反向代理 :3005 P4
data-ana (ai11) 反向代理 :3006 P4
msg (ai10) 反向代理 :3007 P5
ai (ai12) 反向代理 :3008 P5
push-gateway (ai02) WebSocket 升级透传评估 P5
coord shared-go 包维护 + ISSUE 仲裁 持续