Files
Edu/services/api-gateway/docs/nextstep.md

244 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# api-gateway 下游工作清单Next Steps
> 负责人ai01
> 更新日期2026-07-13
> 关联:[api-gateway_contract.md](../../docs/architecture/issues/contracts/api-gateway_contract.md)、[api-gateway_workline.md](../../docs/architecture/issues/worklines/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 + 多阶段构建)
- ✅ 容器启动正常(端口 8080DevMode
-`/healthz` 返回 200
-`/readyz` 返回 503下游未启动时正确报告不可达
-`/metrics` 返回 200 + Prometheus 格式7 个业务指标可见)
-`/api/admin/graphql` 无 auth → 401AuthMiddleware 拦截)
-`/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](../../../apps/admin-portal/docs/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 → /graphqlteacher-bff @Controller |
**关键文件**
- [main.go](../main.go)L107-126admin 路由组注册)
- [internal/middleware/admin_role.go](../internal/middleware/admin_role.go)AdminRoleMiddleware 实现)
- [internal/proxy/proxy.go](../internal/proxy/proxy.go)NewProxyRewrite 路径重写代理)
### 2.2 BFF 路由路径重写修复(已解决)
**来源**[student-portal nextstep.md](../../../apps/student-portal/docs/nextstep.md) §2、[teacher-portal nextstep.md](../../../apps/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 公钥集JWKSTTL 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-bffai03 负责)— 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-bffai04 负责)— P1
| # | 依赖项 | 用途 | 状态 |
| --- | --------------------------- | ------------------------------- | ---- |
| 1 | `POST /graphql` :3009 启用 | student-portal GraphQL 代理目标 | ⏳ |
| 2 | `GET /healthz` 端点 | /readyz 下游健康检查 | ⏳ |
| 3 | 57 个 GraphQL 操作 Resolver | student-portal 全部页面数据 | ⏳ |
### 3.4 parent-bffai05 负责)— 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-portalai13 负责)
| 能力 | 配置 | 状态 |
| ---------------------------- | ------------------------------------------------------- | ---- |
| `/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-portalai14 负责)
| 能力 | 配置 | 状态 |
| --------------------------------- | ---------------------------------------------------- | ---- |
| `/api/v1/student/*` 反向代理 | → student-bff:3009/*(路径重写剥离 /api/v1/student | ✅ |
| JWT 鉴权 + x-user-roles 注入 | 同上 | ✅ |
| `/api/v1/student/upload` 特殊路由 | 需对象存储 + signed URL待 SRE 配置) | ⏳ |
### 4.3 parent-portalai15 负责)
| 能力 | 配置 | 状态 |
| ---------------------------- | -------------------------------------------------- | ---- |
| `/api/v1/parent/*` 反向代理 | → parent-bff:3010/*(路径重写剥离 /api/v1/parent | ✅ |
| JWT 鉴权 + x-user-roles 注入 | 同上 | ✅ |
### 4.4 admin-portalai16 负责)
| 能力 | 配置 | 状态 |
| ----------------------------- | --------------------------------------------------------- | ---- |
| `/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 | BFFGraphQL at /graphql |
| /api/v1/student | student-bff:3009 | 剥离 /api/v1/student | BFFGraphQL at /graphql |
| /api/v1/parent | parent-bff:3010 | 剥离 /api/v1/parent | BFFGraphQL 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 P0AdminRoleMiddleware | ✅ | 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 更新状态。**