Files
Edu/services/api-gateway/README.md
SpecialX 4307f6b73c feat(api-gateway): 实现 W1-W8 网关硬化与 P2-P5 路由扩展
依据 coord-final-decisions §3.8 W1-W8 裁决与
president-final-rulings §2.15/§2.16/§2.19 完整实现网关硬化:

- W1/W2: 错误码 GW_ 前缀 + ActionState 信封响应体
- W3: 全量替换为 log/slog 结构化日志
- W4: /readyz 并行 ping 9 下游 + 软失败规则
- W5: 7 个业务 Prometheus 指标 + /metrics 端点
- W6: tracer 资源属性补全(name/version/env/host)
- W7: DevMode=true && ENV=production panic 防护
- W8: 保持共享 downstream 熔断

P2 RS256 升级:接入 shared-go/jwks.Fetcher(TTL 5min)。
P2.7+P3-P5 路由扩展:student/parent/messages/dashboard。
文档同步:README/01/02/known-issues,arch.db 已更新。
质量校验:go vet + build + test 均通过。
2026-07-10 18:15:48 +08:00

129 lines
8.8 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
Go (Gin) 实现的 API 网关,所有外部请求的统一入口。
## 职责
- **路由转发**`/api/v1/<service>/*` → 下游服务iam / teacher-bff / student-bff / parent-bff / core-edu / content / msg / ai / data-ana
- **JWT 鉴权**RS256IAM 签发Gateway 通过 JWKS 公钥校验DevMode 下支持 `dev-token` 旁路
- **请求 ID 注入**:生成或透传 `X-Request-Id``req-<uuid-v4>` 格式),全链路追踪
- **限流**:基于令牌桶的 per-IP 限流100 rps突发 20超限返回 429 + `GW_RATE_LIMITED`
- **熔断**:基于 gobreaker v2 的下游服务熔断5xx 错误率 > 50% 触发 OPEN返回 503 + `GW_CIRCUIT_OPEN`
- **可观测性**slog 结构化日志 + 7 个业务 metrics + OpenTelemetry tracer资源属性完整
- **CORS / 安全头 / Recovery**:标准化中间件链
## 中间件链
请求处理顺序(自外向内):
```
Request → Recovery → OTel → RequestID → CORS → SecurityHeaders → RequestBodyLimit → RateLimit
→ [api/v1 组] CircuitBreaker → AuthMiddleware(RS256) → Metrics → Proxy → Response
```
| 中间件 | 文件 | 职责 |
| --------------- | ---------------------------------------- | ---------------------------------------------------------------------- |
| Recovery | `internal/middleware/recovery.go` | panic 兜底返回 500 + `GW_INTERNAL_ERROR` |
| OTel | `otelgin.Middleware` | OpenTelemetry 自动埋点 |
| RequestID | `internal/middleware/requestid.go` | 生成/透传 `X-Request-Id``req-<uuid-v4>` |
| CORS | `internal/middleware/cors.go` | 跨域允许(从 Config 读取白名单) |
| SecurityHeaders | `internal/middleware/security.go` | 安全响应头 + 请求体限制413 `GW_REQUEST_TOO_LARGE` |
| RateLimit | `internal/middleware/ratelimit.go` | per-IP 令牌桶限流,超限 429 `GW_RATE_LIMITED` |
| CircuitBreaker | `internal/middleware/circuit-breaker.go` | 下游 5xx 错误率 > 50% 触发熔断503 `GW_CIRCUIT_OPEN` |
| Auth | `internal/middleware/auth.go` | JWT RS256 校验JWKS注入 `x-user-id`/`x-user-roles`/`x-data-scope` |
| Metrics | `internal/observability/metrics.go` | HTTP 请求计数 + 延迟统计7 个业务指标) |
## 路由表
| 前缀 | 目标服务 | 端口 | 鉴权 |
| ---------------------------- | ----------- | ---- | ------------------------------------ |
| `/api/v1/iam/*` | iam | 3002 | JWTregister/login/refresh 白名单) |
| `/api/v1/teacher/*` | teacher-bff | 3003 | JWT |
| `/api/v1/student/*` | student-bff | 3009 | JWT |
| `/api/v1/parent/*` | parent-bff | 3010 | JWT |
| `/api/v1/classes/*` | core-edu | 3004 | JWT |
| `/api/v1/exams/*` | core-edu | 3004 | JWT |
| `/api/v1/homework/*` | core-edu | 3004 | JWT |
| `/api/v1/grades/*` | core-edu | 3004 | JWT |
| `/api/v1/textbooks/*` | content | 3005 | JWT |
| `/api/v1/chapters/*` | content | 3005 | JWT |
| `/api/v1/knowledge-points/*` | content | 3005 | JWT |
| `/api/v1/questions/*` | content | 3005 | JWT |
| `/api/v1/notifications/*` | msg | 3007 | JWT |
| `/api/v1/messages/*` | msg | 3007 | JWT |
| `/api/v1/ai/*` | ai | 3008 | JWT |
| `/api/v1/analytics/*` | data-ana | 3006 | JWT |
| `/api/v1/dashboard/*` | data-ana | 3006 | JWT |
## 健康检查
| 端点 | 用途 | 鉴权 |
| -------------- | ---------------------------------------------------------- | ---- |
| `GET /healthz` | 存活探针liveness | 无 |
| `GET /readyz` | 就绪探针readiness并行 ping 下游 /healthz软失败规则 | 无 |
| `GET /metrics` | Prometheus 指标端点7 个业务指标 + Go runtime | 无 |
## 开发
```bash
cd services/api-gateway
go run main.go
```
DevMode接受 `Bearer dev-token` 旁路鉴权):
```bash
DEV_MODE=true go run main.go
```
## 测试
```bash
cd services/api-gateway
go test ./internal/middleware/... -v -cover
```
## 构建
```bash
go build ./...
docker build -t edu/api-gateway .
```
## 配置
通过环境变量配置(见 `internal/config/config.go`
| 变量 | 默认值 | 说明 |
| ----------------------------- | ------------------------------------------- | -------------------------------------------------------- |
| `API_GATEWAY_PORT` | 8080 | 监听端口 |
| `ENV` | development | 部署环境production 时 W7 防护生效) |
| `DEV_MODE` | false | 开发模式旁路true 时接受 `Bearer dev-token`(仅非生产) |
| `IAM_JWKS_URL` | http://localhost:3002/.well-known/jwks.json | RS256 公钥端点(非 DevMode 必填) |
| `JWT_ISSUER` | next-edu-cloud | JWT 签发者校验 |
| `JWT_AUDIENCE` | next-edu-cloud | JWT 受众校验 |
| `CORS_ORIGINS` | (空,用开发默认白名单) | CORS 白名单(逗号分隔) |
| `CLASSES_SERVICE_URL` | http://localhost:3001 | classes 服务地址(遗留,路由实际走 core-edu |
| `IAM_SERVICE_URL` | http://localhost:3002 | iam 服务地址 |
| `TEACHER_BFF_URL` | http://localhost:3003 | teacher-bff 服务地址 |
| `STUDENT_BFF_URL` | http://localhost:3009 | student-bff 服务地址 |
| `PARENT_BFF_URL` | http://localhost:3010 | parent-bff 服务地址 |
| `CORE_EDU_SERVICE_URL` | http://localhost:3004 | core-edu 服务地址 |
| `CONTENT_SERVICE_URL` | http://localhost:3005 | content 服务地址 |
| `DATA_ANA_SERVICE_URL` | http://localhost:3006 | data-ana 服务地址 |
| `MSG_SERVICE_URL` | http://localhost:3007 | msg 服务地址 |
| `AI_SERVICE_URL` | http://localhost:3008 | ai 服务地址 |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | http://localhost:4318 | OpenTelemetry OTLP 端点 |
| `LOG_LEVEL` | info | 日志级别 |
> **生产环境警告**`DEV_MODE=true` 且 `ENV=production` 时服务 panic 拒绝启动W7 防护)。
## 关联文档
- [架构影响地图](../../docs/architecture/004_architecture_impact_map.md)
- [项目规则](../../.trae/rules/project_rules.md)
- [模块理解确认书](./docs/01-understanding.md)
- [架构设计文档](./docs/02-architecture-design.md)
- [P6 硬化 Runbook](../../docs/architecture/runbooks/p6-hardening.md)
- [Helm Chart](../../infra/k8s/helm/api-gateway/)