api-gateway 下游工作清单(Next Steps)
负责人:ai01
更新日期:2026-07-13
关联:api-gateway_contract.md、api-gateway_workline.md
1. 概述
api-gateway 是 Edu 系统统一入口(L3 网关层),负责路由转发、JWT RS256 验签、限流、熔断、CORS、可观测性。本文档记录基于上游 4 个前端 portal 模块(teacher-portal / student-portal / parent-portal / admin-portal)的下游依赖分析,梳理 api-gateway 已完成工作与剩余阻塞项。
本地 Docker 测试结果(2026-07-13):
- ✅ 镜像构建成功(
edu/api-gateway:test,golang:1.25-alpine + 多阶段构建)
- ✅ 容器启动正常(端口 8080,DevMode)
- ✅
/healthz 返回 200
- ✅
/readyz 返回 503(下游未启动时正确报告不可达)
- ✅
/metrics 返回 200 + Prometheus 格式(7 个业务指标可见)
- ✅
/api/admin/graphql 无 auth → 401(AuthMiddleware 拦截)
- ✅
/api/admin/graphql dev-token → 502(路由存在,admin 角色通过,下游 teacher-bff 不可达)
- ✅
/api/v1/teacher/graphql dev-token → 502(路由存在,BFF 路径重写正确,下游不可达)
- ✅ go vet + go build + go test 全部通过(13 个新测试)
2. 已完成工作(基于上游 portal 依赖分析)
2.1 admin-portal P0 阻塞项(已解决)
来源:admin-portal nextstep.md §2.1
| # |
工作项 |
状态 |
实现详情 |
| 1 |
新增 /api/admin/graphql 路由 |
✅ |
main.go 新增 /api/admin 路由组,POST /api/admin/graphql 代理到 teacher-bff:3003/graphql |
| 2 |
admin 角色强制校验中间件 |
✅ |
新增 AdminRoleMiddleware(internal/middleware/admin_role.go),校验 x-user-roles 含 admin 角色 |
| 3 |
路径对齐契约 §2.3 |
✅ |
/api/admin/graphql 为唯一入口,路径重写 /api/admin/graphql → /graphql(teacher-bff @Controller) |
关键文件:
2.2 BFF 路由路径重写修复(已解决)
来源:student-portal nextstep.md §2、teacher-portal nextstep.md §4.3
问题:teacher-bff / student-bff / parent-bff 的 GraphQL 端点在 /graphql(@Controller("graphql")),但原代理仅剥离 /api 前缀,导致下游收到 /v1/teacher/graphql 而非 /graphql,返回 404。
修复:新增 registerBffProxy 函数,对 BFF 路由(teacher/student/parent)剥离 /api/v1/{bff} 前缀,仅转发剩余路径到下游。
| 路由 |
修复前(错误) |
修复后(正确) |
| /api/v1/teacher/graphql |
→ teacher-bff:3003/v1/teacher/graphql (404) |
→ teacher-bff:3003/graphql ✓ |
| /api/v1/student/graphql |
→ student-bff:3009/v1/student/graphql (404) |
→ student-bff:3009/graphql ✓ |
| /api/v1/parent/graphql |
→ parent-bff:3010/v1/parent/graphql (404) |
→ parent-bff:3010/graphql ✓ |
契约依据:student-portal_contract.md §2.3「/api/v1/student/* → student-bff:3009/*」
2.3 Docker 构建修复(已解决)
问题:原 Dockerfile 使用 golang:1.22-alpine 且构建上下文为 service 目录,无法解析 shared-go 依赖(go.work 模式)。
修复:
- 升级基础镜像为 golang:1.25-alpine(匹配 go.work 的 go 1.25.0)
- 构建上下文改为仓库根目录(访问 packages/shared-go)
- 生成精简版 go.work(仅含 api-gateway + shared-go,排除 push-gateway)
- 设置 GOPROXY=https://goproxy.cn,direct(国内网络环境)
3. 上游依赖(api-gateway 需要的输入)
3.1 iam 服务(ai06 负责)— P0
| # |
依赖项 |
用途 |
状态 |
| 1 |
GET /.well-known/jwks.json |
RS256 公钥集(JWKS),TTL 5min 缓存 |
⏳ |
| 2 |
RS256 JWT 签发 |
api-gateway 用 JWKS 公钥校验 access_token |
⏳ |
| 3 |
GET /healthz 端点 |
/readyz 下游健康检查 |
⏳ |
| 4 |
JWT claims 含 role/data_scope |
api-gateway 注入 x-user-roles / x-data-scope 头 |
⏳ |
影响:非 DevMode 下无法验签 JWT,所有鉴权路由不可用。
3.2 teacher-bff(ai03 负责)— P0
| # |
依赖项 |
用途 |
状态 |
| 1 |
POST /graphql :3003 启用 |
teacher-portal + admin-portal GraphQL 代理目标 |
⏳ |
| 2 |
GET /healthz 端点 |
/readyz 下游健康检查 |
⏳ |
| 3 |
admin 命名空间 Resolver |
admin-portal 的 16 Query + 11 Mutation |
⏳ |
影响:teacher-portal 与 admin-portal 的所有 GraphQL 请求无法获取真实数据。
3.3 student-bff(ai04 负责)— P1
| # |
依赖项 |
用途 |
状态 |
| 1 |
POST /graphql :3009 启用 |
student-portal GraphQL 代理目标 |
⏳ |
| 2 |
GET /healthz 端点 |
/readyz 下游健康检查 |
⏳ |
| 3 |
57 个 GraphQL 操作 Resolver |
student-portal 全部页面数据 |
⏳ |
3.4 parent-bff(ai05 负责)— P1
| # |
依赖项 |
用途 |
状态 |
| 1 |
POST /graphql :3010 启用 |
parent-portal GraphQL 代理目标 |
⏳ |
| 2 |
GET /healthz 端点 |
/readyz 下游健康检查 |
⏳ |
3.5 core-edu / content / msg / ai / data-ana 服务 — P2
| 服务 |
端口 |
依赖项 |
状态 |
| core-edu |
3004 |
GET /healthz + 业务 REST |
⏳ |
| content |
3005 |
GET /healthz + 业务 REST |
⏳ |
| msg |
3007 |
GET /healthz + 业务 REST |
⏳ |
| ai |
3008 |
GET /healthz + 业务 REST |
⏳ |
| data-ana |
3006 |
GET /healthz + 业务 REST |
⏳ |
影响:/readyz 报告这些服务不可达(软失败规则:返回 503 但不阻断启动)。
4. 下游依赖(api-gateway 提供给下游的能力)
4.1 teacher-portal(ai13 负责)
| 能力 |
配置 |
状态 |
/api/v1/teacher/* 反向代理 |
→ teacher-bff:3003/*(路径重写剥离 /api/v1/teacher) |
✅ |
| JWT 鉴权 + x-user-roles 注入 |
AuthMiddleware 注入 x-user-id/x-user-roles/x-data-scope |
✅ |
| CORS 白名单 |
CORS_ORIGINS 环境变量配置 |
✅ |
| 限流(IP 级令牌桶) |
100 rps,突发 20 |
✅ |
| 熔断(下游 5xx 触发) |
CircuitBreaker("downstream") |
✅ |
| /metrics 业务指标 |
7 个 Prometheus 指标 |
✅ |
4.2 student-portal(ai14 负责)
| 能力 |
配置 |
状态 |
/api/v1/student/* 反向代理 |
→ student-bff:3009/*(路径重写剥离 /api/v1/student) |
✅ |
| JWT 鉴权 + x-user-roles 注入 |
同上 |
✅ |
/api/v1/student/upload 特殊路由 |
需对象存储 + signed URL(待 SRE 配置) |
⏳ |
4.3 parent-portal(ai15 负责)
| 能力 |
配置 |
状态 |
/api/v1/parent/* 反向代理 |
→ parent-bff:3010/*(路径重写剥离 /api/v1/parent) |
✅ |
| JWT 鉴权 + x-user-roles 注入 |
同上 |
✅ |
4.4 admin-portal(ai16 负责)
| 能力 |
配置 |
状态 |
/api/admin/graphql 反向代理 |
→ teacher-bff:3003/graphql(路径重写剥离 /api/admin) |
✅ |
| admin 角色强制校验 |
AdminRoleMiddleware 拒绝非 admin 角色(403 GW_FORBIDDEN) |
✅ |
| JWT 鉴权 + x-user-roles 注入 |
同上 |
✅ |
5. 路由清单(完整)
5.1 公开路由(无需鉴权)
| Method |
Path |
用途 |
| GET |
/healthz |
liveness 健康检查 |
| GET |
/readyz |
readiness 健康检查 |
| GET |
/metrics |
Prometheus 指标 |
5.2 API v1 路由(JWT 鉴权 + 熔断 + 指标)
| 前缀 |
下游 |
路径重写 |
备注 |
| /api/v1/classes |
core-edu:3004 |
剥离 /api |
classes 域(C1 合并入 core-edu) |
| /api/v1/iam |
iam:3002 |
剥离 /api |
含公开路径白名单 |
| /api/v1/teacher |
teacher-bff:3003 |
剥离 /api/v1/teacher |
BFF(GraphQL at /graphql) |
| /api/v1/student |
student-bff:3009 |
剥离 /api/v1/student |
BFF(GraphQL at /graphql) |
| /api/v1/parent |
parent-bff:3010 |
剥离 /api/v1/parent |
BFF(GraphQL at /graphql) |
| /api/v1/exams |
core-edu:3004 |
剥离 /api |
core-edu 域 |
| /api/v1/homework |
core-edu:3004 |
剥离 /api |
core-edu 域 |
| /api/v1/grades |
core-edu:3004 |
剥离 /api |
core-edu 域 |
| /api/v1/textbooks |
content:3005 |
剥离 /api |
content 域 |
| /api/v1/chapters |
content:3005 |
剥离 /api |
content 域 |
| /api/v1/knowledge-points |
content:3005 |
剥离 /api |
content 域 |
| /api/v1/questions |
content:3005 |
剥离 /api |
content 域 |
| /api/v1/notifications |
msg:3007 |
剥离 /api |
msg 域 |
| /api/v1/messages |
msg:3007 |
剥离 /api |
msg 域 |
| /api/v1/ai |
ai:3008 |
剥离 /api |
ai 域 |
| /api/v1/analytics |
data-ana:3006 |
剥离 /api |
data-ana 域 |
| /api/v1/dashboard |
data-ana:3006 |
剥离 /api |
data-ana 域 |
5.3 Admin 路由(JWT 鉴权 + admin 角色强制 + 熔断 + 指标)
| Method |
Path |
下游 |
路径重写 |
备注 |
| ANY |
/api/admin/graphql |
teacher-bff:3003 |
剥离 /api/admin |
admin-portal 唯一入口(§2.3) |
6. 剩余工作
6.1 P6 硬化任务(部分待 Redis 就绪)
| # |
工作项 |
状态 |
阻塞条件 |
| 1 |
P6.1 限流迁 Redis |
⏳ |
待 SRE 部署 Redis 生产环境 |
| 2 |
P6.2 熔断评估 |
✅ |
维持 W8 共享 downstream 策略 |
| 3 |
P6.3 测试覆盖率 ≥ 80% |
✅ |
已达 85%+(含 13 个新测试) |
| 4 |
P6.4 安全加固 |
⏳ |
待 P6.1 Redis 就绪后补齐 |
6.2 联调待办
| # |
工作项 |
触发条件 |
| 1 |
teacher-bff GraphQL 端到端联调 |
teacher-bff schema 上线 main |
| 2 |
admin-portal → api-gateway → teacher-bff |
admin 命名空间 Resolver 就绪 |
| 3 |
student-portal → api-gateway → student-bff |
student-bff 57 个 GraphQL 操作就绪 |
| 4 |
iam JWKS 真实验签联调 |
iam JWKS 端点 + RS256 JWT 签发就绪 |
| 5 |
/readyz 全绿 |
所有下游服务 /healthz 就绪 |
7. 已完成项汇总
| 工作项 |
状态 |
验证方式 |
| admin-portal P0:/api/admin/graphql 路由 |
✅ |
Docker 测试 502(路由存在,下游不可达) |
| admin-portal P0:AdminRoleMiddleware |
✅ |
8 个单元测试通过 |
| BFF 路由路径重写修复(teacher/student/parent) |
✅ |
Docker 测试 502(路径正确,下游不可达) |
| NewProxyRewrite 代理函数 |
✅ |
5 个单元测试通过 |
| Docker 镜像构建修复 |
✅ |
edu/api-gateway:test 构建成功 |
| Docker 容器运行验证 |
✅ |
/healthz 200 + /metrics 200 + /readyz 503 + 路由 401/502 |
| go vet + go build + go test |
✅ |
零错误,13 个新测试通过 |
| P6.2 熔断评估 |
✅ |
维持 W8 共享 downstream 策略 |
| P6.3 测试覆盖率 |
✅ |
middleware + proxy 包覆盖率 85%+ |
本文件由 ai01 维护,上游/下游工作项请各负责 AI 完成后通知 ai01 更新状态。