# 全链路启用与测试手册（Full Stack Runbook）

> 版本：1.0
> 日期：2026-07-09
> 适用范围：Edu 微服务架构（P6 阶段：11 基础设施 + 10 应用服务 + 1 前端）
> 关联文档：[local-dev-runbook](./local-dev-runbook.md)、[004 架构影响地图](../architecture/004_architecture_impact_map.md)、[known-issues](../troubleshooting/known-issues.md)

---

## 1. 前置条件

| 工具           | 版本要求 | 验证命令                 |
| -------------- | -------- | ------------------------ |
| Node.js        | ≥ 20     | `node -v`                |
| pnpm           | ≥ 9      | `pnpm -v`                |
| Go             | 1.22+    | `go version`             |
| uv             | 0.4+     | `uv --version`           |
| Docker         | 24+      | `docker version`         |
| Docker Compose | v2+      | `docker compose version` |

> Windows 用户：Go 工具链若不在 PATH，临时加入：`$env:Path = "C:\Program Files\Go\bin;" + $env:Path`

---

## 2. 服务端口矩阵

### 2.1 应用服务（10 个）

| 端口 | 服务           | 语言/框架 | 启动方式                                       |
| ---- | -------------- | --------- | ---------------------------------------------- |
| 3000 | teacher-portal | Next.js   | `pnpm --filter teacher-portal dev`             |
| 3001 | classes        | NestJS    | `pnpm --filter @edu/classes-service dev`       |
| 3002 | iam            | NestJS    | `pnpm --filter @edu/iam-service dev`           |
| 3003 | teacher-bff    | NestJS    | `pnpm --filter @edu/teacher-bff dev`           |
| 3004 | core-edu       | NestJS    | `pnpm --filter @edu/core-edu-service dev`      |
| 3005 | content        | NestJS    | `pnpm --filter @edu/content-service dev`       |
| 3006 | data-ana       | FastAPI   | `uv run uvicorn data_ana.main:app --port 3006` |
| 3007 | msg            | NestJS    | `pnpm --filter @edu/msg-service dev`           |
| 3008 | ai             | FastAPI   | `uv run uvicorn ai.main:app --port 3008`       |
| 8080 | api-gateway    | Go (Gin)  | `go run .`                                     |
| 8081 | push-gateway   | Go (Gin)  | `go run .`                                     |

### 2.2 基础设施（11 个）

| 端口      | 服务               | 用途                  |
| --------- | ------------------ | --------------------- |
| 3306      | MySQL 8            | 写模型主库            |
| 6379      | Redis 7            | 缓存/会话             |
| 8083      | Debezium Connect   | CDC source connector  |
| 8123/9000 | ClickHouse 24.3    | 读模型宽表            |
| 9092      | Kafka 7.6          | 事件总线              |
| 7474/7687 | Neo4j 5.20         | 知识图谱              |
| 9200      | Elasticsearch 8.13 | 题库检索              |
| 9090      | Prometheus         | 指标采集              |
| 3030      | Grafana            | 可视化（admin/admin） |
| 16686     | Jaeger             | 分布式追踪 UI         |
| 4318      | OTLP Collector     | OTel span 接收        |

---

## 3. 一键启动

### 3.1 启动基础设施

```powershell
cd e:\Desktop\Edu\infra
docker compose -f docker-compose.yml --profile p6 --profile observability up -d
```

等待所有容器 healthy（约 60 秒）：

```powershell
docker ps --filter "name=edu-" --format "table {{.Names}}\t{{.Status}}"
```

### 3.2 一键启动所有应用服务

使用项目根目录的启动脚本：

```powershell
cd e:\Desktop\Edu
.\scripts\start-all.ps1
```

该脚本会：

1. 检查基础设施健康状态
2. 为每个应用服务启动独立后台窗口（带标题）
3. 自动注入 Python 服务的环境变量（CLICKHOUSE/KAFKA/OTEL）
4. 等待所有服务健康检查通过

### 3.3 健康检查

```powershell
cd e:\Desktop\Edu
.\scripts\health-check.ps1
```

预期输出：所有服务 ✅

---

## 4. 端到端链路测试

### 4.1 IAM 注册 + 登录

```powershell
$h = @{Authorization="Bearer dev-token"}

# 注册
$body = @{username="testteacher";password="Test@1234";email="test@edu.com";role="teacher"} | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:8080/iam/auth/register" -Method Post -Body $body -ContentType "application/json" -Headers $h

# 登录
$loginBody = @{username="testteacher";password="Test@1234"} | ConvertTo-Json
$resp = Invoke-RestMethod -Uri "http://localhost:8080/iam/auth/login" -Method Post -Body $loginBody -ContentType "application/json"
$token = $resp.data.accessToken
Write-Host "Token: $token"
```

### 4.2 Classes CRUD

```powershell
# 创建班级
$classBody = @{name="高三一班";gradeId="grade-1";headTeacherId=""} | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:8080/classes" -Method Post -Body $classBody -ContentType "application/json" -Headers $h

# 查询班级列表
Invoke-RestMethod -Uri "http://localhost:8080/classes" -Method Get -Headers $h
```

### 4.3 CDC 完整链路（MySQL → Debezium → Kafka → data-ana → ClickHouse）

```powershell
# 1. 向 MySQL 插入成绩（触发 binlog）
docker exec edu-mysql mysql -uedu -pchangeme next_edu_cloud -e "
INSERT INTO core_edu_exams (id, class_id, subject_id, title, exam_date, total_score, created_at, updated_at)
VALUES ('exam-cdc-test-001','cls-test-001','sub-math','CDC测试考试',NOW(),100,NOW(),NOW())
ON DUPLICATE KEY UPDATE updated_at=NOW();

INSERT INTO core_edu_grades (id, exam_id, student_id, score, rank_in_class, created_at, updated_at)
VALUES ('grade-cdc-001','exam-cdc-test-001','student-cdc-001',92.5,1,NOW(),NOW())
ON DUPLICATE KEY UPDATE score=92.5, updated_at=NOW();
"

# 2. 等待 Debezium 捕获 + data-ana 消费
Start-Sleep -Seconds 5

# 3. 验证 ClickHouse 已同步
docker exec edu-clickhouse clickhouse-client --user default --password clickhouse -q "
SELECT student_id, class_id, exam_id, score, last_updated
FROM edu_analytics.student_dashboard_view
WHERE student_id = 'student-cdc-001'
ORDER BY last_updated DESC
"
# 预期：返回一行，score=92.5，class_id='cls-test-001'
```

### 4.4 data-ana 查询 API

```powershell
# 学生学情看板
Invoke-RestMethod -Uri "http://localhost:3006/analytics/student/student-cdc-001/weakness" -Headers $h

# 班级成绩分析
Invoke-RestMethod -Uri "http://localhost:3006/analytics/class/cls-test-001/performance" -Headers $h

# CDC 消费者状态
Invoke-RestMethod -Uri "http://localhost:3006/readyz"
# 预期: cdc_consumer = "running"
```

### 4.5 可观测性验证

| 检查项             | URL                                 | 预期                     |
| ------------------ | ----------------------------------- | ------------------------ |
| Prometheus targets | http://localhost:9090/targets       | 所有 target UP           |
| Grafana 面板       | http://localhost:3030 (admin/admin) | 可登录                   |
| Jaeger UI          | http://localhost:16686              | 可搜索到各 service trace |
| data-ana /metrics  | http://localhost:3006/metrics       | Prometheus 格式输出      |
| iam /metrics       | http://localhost:3002/metrics       | Prometheus 格式输出      |

**Jaeger trace 验证步骤**：

1. 打开 http://localhost:16686
2. Service 下拉框应能看到 `iam`、`classes`、`data-ana`、`api-gateway` 等
3. 选择任一服务 → Find Traces → 应看到 HTTP 请求的自动埋点 span

---

## 5. 一键停止

### 5.1 停止应用服务

```powershell
cd e:\Desktop\Edu
.\scripts\stop-all.ps1

.\scripts\stop-all.ps1 -KillByPort
```

该脚本会关闭所有 `edu-app-*` 标题的终端窗口。

### 5.2 停止基础设施

```powershell
cd e:\Desktop\Edu\infra
docker compose -f docker-compose.yml --profile p6 --profile observability down
```

---

## 6. 故障排查

### 6.1 端口占用

```powershell
# 查看占用端口的进程
netstat -ano | findstr :3001
# 终止进程
taskkill /PID <PID> /F
```

### 6.2 基础设施未启动

```powershell
# 检查容器状态
docker ps --filter "name=edu-"

# 重启单个容器
docker restart edu-mysql

# 查看日志
docker logs edu-debezium --tail 50
```

### 6.3 CDC 链路断开

```powershell
# 1. 检查 Debezium connector 状态
Invoke-RestMethod -Uri "http://localhost:8083/connectors/edu-mysql-source/status"

# 2. 重启 connector
Invoke-RestMethod -Uri "http://localhost:8083/connectors/edu-mysql-source/restart" -Method Post

# 3. 检查 Kafka topic 是否有数据
docker exec edu-kafka kafka-console-consumer --bootstrap-server localhost:9092 --topic edu-cdc.next_edu_cloud.core_edu_grades --from-beginning --max-messages 1

# 4. 检查 data-ana 消费者日志
# 查看 data-ana 终端窗口的 cdc_consumer_started / cdc_event_received 日志
```

### 6.4 OTel trace 未上报

```powershell
# 1. 检查 Jaeger 是否收到 trace
Invoke-RestMethod -Uri "http://localhost:16686/api/services"

# 2. 检查 OTLP endpoint 是否可达
Invoke-RestMethod -Uri "http://localhost:4318/v1/traces" -Method Post -ContentType "application/json" -Body "{}"

# 3. 检查服务环境变量
# 确保 OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 已设置
```

---

## 7. 速查：常用命令

| 场景               | 命令                                                                                                                                                 |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| 启动基础设施       | `docker compose -f infra/docker-compose.yml --profile p6 --profile observability up -d`                                                              |
| 一键启动应用       | `.\scripts\start-all.ps1`                                                                                                                            |
| 一键停止应用       | `.\scripts\stop-all.ps1`                                                                                                                             |
| 健康检查           | `.\scripts\health-check.ps1`                                                                                                                         |
| CDC 链路验证       | `.\scripts\test-cdc.ps1`                                                                                                                             |
| 查看容器状态       | `docker ps --filter "name=edu-"`                                                                                                                     |
| 查看 Debezium 状态 | `Invoke-RestMethod http://localhost:8083/connectors/edu-mysql-source/status`                                                                         |
| ClickHouse 查询    | `docker exec edu-clickhouse clickhouse-client --user default --password clickhouse -q "SELECT * FROM edu_analytics.student_dashboard_view LIMIT 10"` |
| Kafka topic 列表   | `docker exec edu-kafka kafka-topics --bootstrap-server localhost:9092 --list`                                                                        |
| Prometheus 查询    | `Invoke-RestMethod "http://localhost:9090/api/v1/query?query=up"`                                                                                    |
