244 lines
15 KiB
Markdown
244 lines
15 KiB
Markdown
# 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 + 多阶段构建)
|
||
- ✅ 容器启动正常(端口 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](../../../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 → /graphql(teacher-bff @Controller) |
|
||
|
||
**关键文件**:
|
||
|
||
- [main.go](../main.go)(L107-126,admin 路由组注册)
|
||
- [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 公钥集(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 更新状态。**
|