## 15. P6 生产硬化（补记）

> 本章为 `004_architecture_impact_map.md` 的 P6 阶段补记，记录生产硬化引入的横切关注点与基础设施栈。
> 维护规则与正文一致：源码变更后同步 `npm run arch:scan` 更新 arch.db。

### 15.1 横切关注点矩阵

| 关注点 | NestJS 服务 | Python 服务 | Go 网关 | 实现位置 |
|--------|-------------|-------------|---------|----------|
| 健康检查 | HealthController | health.py | /healthz | shared/health, src/health |
| 优雅停机 | LifecycleService | FastAPI lifespan | enableShutdownHooks | shared/lifecycle |
| 熔断 | 经 Gateway | 经 Gateway | gobreaker v2 | api-gateway/middleware |
| 限流 | 经 Gateway | 经 Gateway | token bucket | api-gateway/middleware |
| 链路追踪 | tracer.ts | OpenTelemetry | OpenTelemetry | shared/observability |
| 指标 | metrics.ts | prometheus_fastapi | prometheus | shared/observability |
| 日志 | logger.ts | structlog | zap | shared/observability |
| 错误处理 | global-error.filter | exception handler | middleware | shared/errors |

### 15.2 API Gateway 中间件链

请求流经顺序（出向到下游服务）：

```
请求入口
  → WAF（规则匹配）
  → CORS
  → 限流（token bucket，按 route+tenant）
  → 熔断（gobreaker v2，按下游服务）
  → 重试（指数退避，仅幂等）
  → 链路追踪注入
  → 转发到下游
  → 响应 → 指标记录 → 返回
```

### 15.3 可观测性栈

```
应用层（NestJS / Python / Go）
  → OpenTelemetry SDK（trace + metrics）
  → OTLP exporter
  → 采集层
      ├─ Prometheus（metrics）
      ├─ Tempo / Jaeger（trace）
      └─ Loki / ELK（log）
  → 展示层
      ├─ Grafana（仪表盘）
      └─ Alertmanager（告警路由）
```

关键指标命名约定：
- `http_request_duration_seconds`（histogram，含 service/route/status 维度）
- `circuit_breaker_state`（gauge，0=Closed / 1=Open / 2=HalfOpen）
- `rate_limiter_rejected_total`（counter）
- `db_connections_in_use`（gauge）
- `kafka_consumer_lag`（gauge）

### 15.4 安全栈

| 层 | 机制 | 配置位置 |
|----|------|----------|
| 边缘 | WAF + DDoS 防护 | Cloudflare / 入口 LB |
| 网关 | JWT 校验 + 限流 + CORS | api-gateway |
| 服务 | requirePermission 权限点 | modules/*/actions |
| 数据 | 字段加密 + 审计日志 | data-access |
| 密钥 | KMS + K8s Secret + 轮换 | deploy/k8s/secrets |
| 传输 | mTLS（服务间，可选）+ TLS（边缘） | mesh / ingress |

### 15.5 健康检查约定

- `GET /healthz`：liveness，仅返回进程存活，不检查依赖，避免滚动重启雪崩
- `GET /readyz`：readiness，检查 DB 等关键依赖，失败返回 503
- K8s 探针：livenessProbe → /healthz，readinessProbe → /readyz
- Python 服务 readyz 简化为 ok + TODO，待依赖客户端就绪后补全
- 无需鉴权，必须在路由白名单中放行

### 15.6 优雅停机约定

- NestJS：`app.enableShutdownHooks()` 注册 SIGTERM/SIGINT 钩子
- LifecycleService 实现 OnApplicationShutdown，按序关闭：Kafka producer → Redis → DataSource
- K8s：`terminationGracePeriodSeconds=60`，preStop hook 可加 sleep 5s 摘流量
- Python：FastAPI lifespan shutdown 事件，关闭连接池
- 销毁顺序理由：先停外部消息生产（避免新事件），再关缓存，最后关 DB

### 15.7 灾难恢复策略

- 备份：CronJob 每 15min，PostgreSQL + Redis + Kafka offset
- 恢复：`scripts/restore/`，月度演练验证 RTO
- 多 AZ：Pod 反亲和 + DB 同步复制 + Redis 哨兵 + Kafka ISR=2
- DNS 切换：区域级故障，TTL=60s，季度演练

### 15.8 与正文章节的对应

| 本章小节 | 对应正文章节 |
|----------|--------------|
| 横切关注点 | 第 3 章 共享内核 |
| 中间件链 | 第 5 章 API Gateway |
| 可观测性 | 第 10 章 可观测性 |
| 安全栈 | 第 11 章 安全 |
| 健康检查 | 第 6 章 服务边界 |
| 灾难恢复 | 第 12 章 部署与运维 |

### 15.9 同步要求

新增导出符号需在落地到 Edu 仓库后运行 `npm run arch:scan` 更新 arch.db：
- `HealthController`、`HealthModule`（5 个 NestJS 服务）
- `LifecycleService`（5 个 NestJS 服务）
- `health.py` router（ai、data-ana）
