283 lines
18 KiB
Markdown
283 lines
18 KiB
Markdown
# data-ana 模块上下游依赖与工作清单(Next Steps)
|
||
|
||
> 模块:data-ana(智能洞察域,数据分析服务)
|
||
> 负责人:ai11
|
||
> 更新日期:2026-07-13
|
||
> 关联文档:[01-understanding.md](./01-understanding.md)、[02-architecture-design.md](./02-architecture-design.md)、[data-ana_contract.md](../../../docs/architecture/issues/contracts/data-ana_contract.md)、[data-ana_workline.md](../../../docs/architecture/issues/worklines/data-ana_workline.md)
|
||
|
||
---
|
||
|
||
## 1. 模块当前状态
|
||
|
||
data-ana 已完成 P2-P5 全部代码实现,P6 硬化期未开始。当前服务包含:
|
||
|
||
- **HTTP 14 端点**(3 基础 + 11 业务),端口 3006
|
||
- **gRPC 12 RPC**(11 unary + 1 server-streaming),端口 50055
|
||
- **CDC 消费者**:Debezium binlog → ClickHouse 5 宽表,手动 commit + Redis 去重
|
||
- **ClickHouse 宽表**:student_dashboard_view / student_errors / mastery_snapshot / ai_usage_log / attendance_logs
|
||
- **Kafka 生产者**:MasteryEvent + WarningTriggered(Outbox 豁免)
|
||
- **iam gRPC 集成**:GetEffectiveDataScope + Redis 缓存 + role 降级兜底
|
||
- **降级模式**:ClickHouse/Kafka/Redis/iam 任一不可达时服务仍可启动
|
||
|
||
---
|
||
|
||
## 2. 上游依赖(data-ana 依赖谁)
|
||
|
||
### 2.1 iam 服务(ai06 负责)— P0
|
||
|
||
| # | 依赖项 | 用途 | 状态 |
|
||
| --- | ------------------------------------------- | ------------------------------------------------------------------ | ----------------------------- |
|
||
| 1 | gRPC `GetEffectiveDataScope(userId)` :50052 | DataScope 6 级过滤(SELF/CLASS/GRADE/SCHOOL/DISTRICT/ALL) | ✅ 已就绪(iam.proto 已补全) |
|
||
| 2 | REST `GET /healthz` :3002 | /readyz 下游健康检查 | ⏳ 待 iam 容器启动 |
|
||
| 3 | JWT RS256 公钥 | (data-ana 不直接验签,由 api-gateway 验签后注入 x-user-* header) | — |
|
||
|
||
**环境变量**:`DATA_ANA_IAM_GRPC_TARGET=iam:50052`
|
||
**降级策略**:iam 不可达时按 role 映射默认 DataScope + `degraded: true`
|
||
|
||
### 2.2 ClickHouse(基础设施)— P0
|
||
|
||
| # | 依赖项 | 用途 | 状态 |
|
||
| --- | ---------------- | ------------------------------ | -------------------------------------- |
|
||
| 1 | ClickHouse :8123 | 5 宽表读写(分析查询核心存储) | ✅ Docker 已启动 |
|
||
| 2 | DDL 建表 | 5 宽表 schema | ✅ 已创建 `scripts/clickhouse_ddl.sql` |
|
||
| 3 | 种子数据 | mock 数据集 | ✅ 已创建 `scripts/seed_clickhouse.py` |
|
||
|
||
**环境变量**:`DATA_ANA_CLICKHOUSE_HOST=clickhouse`、`DATA_ANA_CLICKHOUSE_PORT=8123`、`DATA_ANA_CLICKHOUSE_DATABASE=edu_analytics`
|
||
**降级策略**:ClickHouse 不可达时服务启动跳过,查询返回 degraded 空数据
|
||
|
||
### 2.3 Kafka(基础设施)— P1
|
||
|
||
| # | 依赖项 | 用途 | 状态 |
|
||
| --- | ----------------- | ----------------------------------------------------------- | ---------------- |
|
||
| 1 | Kafka :29092 消费 | CDC topic(edu-cdc.next_edu_cloud.* 等 7 topic) | ✅ Docker 已启动 |
|
||
| 2 | Kafka :29092 生产 | edu.insight.mastery.updated + edu.insight.warning.triggered | ✅ Docker 已启动 |
|
||
|
||
**环境变量**:`DATA_ANA_KAFKA_BROKERS=kafka:29092`
|
||
**降级策略**:Kafka 不可达时 CDC 消费者不启动,事件发布静默失败
|
||
|
||
### 2.4 Redis(基础设施)— P1
|
||
|
||
| # | 依赖项 | 用途 | 状态 |
|
||
| --- | ----------- | ------------------------------------------------------------------- | ---------------- |
|
||
| 1 | Redis :6379 | DataScope 缓存(5min TTL)+ CDC event_id 去重 + Warning bitmap 去重 | ✅ Docker 已启动 |
|
||
|
||
**环境变量**:`DATA_ANA_REDIS_URL=redis://redis:6379`
|
||
**降级策略**:Redis 不可达时跳过缓存,每次直查 iam gRPC
|
||
|
||
### 2.5 core-edu 服务(ai07 负责)— P1(CDC 依赖)
|
||
|
||
| # | 依赖项 | 用途 | 状态 |
|
||
| --- | --------------------------- | ------------------------------------------------------ | ------------------------- |
|
||
| 1 | MySQL binlog(core_edu 库) | CDC 消费 grades/exams/homework/attendance/classes 变更 | ⏳ 待 core-edu MySQL 就绪 |
|
||
| 2 | Debezium Connect | MySQL → Kafka CDC 管道 | ⏳ 待 Debezium 部署 |
|
||
|
||
### 2.6 content 服务(ai08 负责)— P2(CDC 依赖)
|
||
|
||
| # | 依赖项 | 用途 | 状态 |
|
||
| --- | -------------------------- | --------------------------------------------------------- | ------------------------ |
|
||
| 1 | MySQL binlog(content 库) | CDC 消费 content_knowledge_points 变更 → Redis 知识点缓存 | ⏳ 待 content MySQL 就绪 |
|
||
|
||
### 2.7 ai 服务(ai12 负责)— P2(事件消费)
|
||
|
||
| # | 依赖项 | 用途 | 状态 |
|
||
| --- | ---------------------------------- | ------------------------------------- | ----------------------------------- |
|
||
| 1 | Kafka topic `edu.insight.ai.usage` | 消费 AIUsageEvent → ai_usage_log 宽表 | ✅ events.proto 已补全 AIUsageEvent |
|
||
|
||
---
|
||
|
||
## 3. 下游依赖(谁依赖 data-ana)
|
||
|
||
### 3.1 teacher-bff(ai03 负责)— P0
|
||
|
||
| # | gRPC RPC | 用途 | 状态 |
|
||
| --- | ------------------------------------- | ---------------------------- | --------- |
|
||
| 1 | `GetStudentWeakness(classId)` :50055 | `studentWeakness` 查询 | ✅ 已实现 |
|
||
| 2 | `GetLearningTrend(classId)` :50055 | `learningTrend` 查询 | ✅ 已实现 |
|
||
| 3 | `GetClassPerformance(classId)` :50055 | `classPerformance` 查询 | ✅ 已实现 |
|
||
| 4 | `GetAdminDashboard(input)` :50055 | `adminDashboard` AI 用量区块 | ✅ 已实现 |
|
||
|
||
**需求来源**:[teacher-bff nextstep.md](../../teacher-bff/docs/nextstep.md) §2.4
|
||
**环境变量**(teacher-bff 侧):`DATA_ANA_GRPC_TARGET=data-ana:50055`
|
||
|
||
### 3.2 student-bff(ai04 负责)— P0
|
||
|
||
| # | gRPC RPC | 用途 | 状态 |
|
||
| --- | -------------------------------------------------- | ----------------------- | --------- |
|
||
| 1 | `GetStudentWeakness(studentId)` :50055 | `myWeakness` 查询 | ✅ 已实现 |
|
||
| 2 | `GetLearningTrend(studentId)` :50055 | `myTrend` 查询 | ✅ 已实现 |
|
||
| 3 | `GetStudentMastery(studentId)` :50055 | `myMasterySummary` 查询 | ✅ 已实现 |
|
||
| 4 | `GetStudentDashboard(studentId)` :50055 | `studentDashboard` 查询 | ✅ 已实现 |
|
||
| 5 | `GetMasteryDistribution(classId)` :50055 | 班级掌握度分布 | ✅ 已实现 |
|
||
| 6 | HTTP `GET /analytics/student/{id}/errorbook` :3006 | `myErrorBook` 查询 | ✅ 已实现 |
|
||
|
||
**需求来源**:[student-bff nextstep.md](../../student-bff/docs/nextstep.md) §3.4
|
||
**说明**:student-bff nextstep.md 中列出的 `GetStudentGrowth`/`GetAssignmentAnalysis`/`ListDiagnosticReports`/`ListErrorBookItems`/`ListPracticeSessionsByStudent`/`StartPracticeSession`/`SubmitPracticeAnswer` 等 RPC 在 analytics.proto 中未定义,data-ana 通过现有 12 RPC + HTTP 端点覆盖这些需求。
|
||
|
||
### 3.3 parent-bff(ai05 负责)— P1
|
||
|
||
| # | gRPC RPC | 用途 | 状态 |
|
||
| --- | -------------------------------------- | ------------------------------- | --------- |
|
||
| 1 | `GetStudentWeakness(studentId)` :50055 | `childWeakness` 查询 | ✅ 已实现 |
|
||
| 2 | `GetLearningTrend(studentId)` :50055 | `childTrend` 查询 | ✅ 已实现 |
|
||
| 3 | `GetClassPerformance(classId)` :50055 | `classRank`/`classAverage` 计算 | ✅ 已实现 |
|
||
|
||
**需求来源**:[parent-bff nextstep.md](../../parent-bff/docs/nextstep.md) §4.3
|
||
**说明**:parent-bff nextstep.md 中列出的 `childGrowthArchive`/`childLearningPath`/`childErrorBookStats`/`childTopWrongQuestions`/`childWeakKps`/`childMasterySummary`/`childDiagnosticReports`/`childPracticeStats`/`childPracticeSessions` 等查询在当前 RPC 中未直接覆盖,parent-bff 通过降级模式返回空数据。data-ana 可通过 HTTP 端点 `/analytics/student/{id}/errorbook` 等补充覆盖。
|
||
|
||
### 3.4 api-gateway(ai01 负责)— P0
|
||
|
||
| # | 路由 | 用途 | 状态 |
|
||
| --- | ------------------------------------- | ---------------------- | --------------------- |
|
||
| 1 | `/api/v1/analytics/*` → data-ana:3006 | data-ana HTTP 端点代理 | ✅ api-gateway 已配置 |
|
||
| 2 | `/api/v1/dashboard/*` → data-ana:3006 | 仪表盘代理 | ✅ api-gateway 已配置 |
|
||
|
||
**需求来源**:[api-gateway nextstep.md](../../api-gateway/docs/nextstep.md) §5.2
|
||
|
||
---
|
||
|
||
## 4. Docker 本地测试
|
||
|
||
### 4.1 镜像构建
|
||
|
||
```bash
|
||
# 在仓库根目录执行(Docker Hub 不可达时先 docker pull + docker tag python:3.12-slim)
|
||
docker build -t edu/data-ana:test -f services/data-ana/Dockerfile services/data-ana/
|
||
```
|
||
|
||
### 4.2 容器启动(接入 edu-full_default 网络)
|
||
|
||
```bash
|
||
docker run -d \
|
||
--name edu-data-ana-test \
|
||
--network edu-full_default \
|
||
-p 3006:3006 -p 50055:50055 \
|
||
-e DATA_ANA_CLICKHOUSE_HOST=clickhouse \
|
||
-e DATA_ANA_CLICKHOUSE_PORT=8123 \
|
||
-e DATA_ANA_CLICKHOUSE_DATABASE=edu_analytics \
|
||
-e DATA_ANA_KAFKA_BROKERS=kafka:29092 \
|
||
-e DATA_ANA_REDIS_URL=redis://redis:6379 \
|
||
-e DATA_ANA_DEV_MODE=true \
|
||
-e OTEL_TRACES_EXPORTER=none \
|
||
-e OTEL_METRICS_EXPORTER=none \
|
||
-e OTEL_LOGS_EXPORTER=none \
|
||
edu/data-ana:test
|
||
```
|
||
|
||
### 4.3 健康检查验证
|
||
|
||
```bash
|
||
# liveness
|
||
curl http://localhost:3006/healthz
|
||
|
||
# readiness(下游不可达时返回 degraded)
|
||
curl http://localhost:3006/readyz
|
||
```
|
||
|
||
### 4.4 ClickHouse DDL + 种子数据
|
||
|
||
```bash
|
||
# 建表
|
||
docker exec edu-clickhouse clickhouse-client --password clickhouse --multiquery < services/data-ana/scripts/clickhouse_ddl.sql
|
||
|
||
# 种子数据(需安装 clickhouse-connect)
|
||
cd services/data-ana && python scripts/seed_clickhouse.py
|
||
```
|
||
|
||
### 4.5 测试结果(2026-07-13 已通过)
|
||
|
||
| # | 测试项 | 结果 | 说明 |
|
||
| --- | ------------------------------------------- | ---- | ------------------------------------------------------------------- |
|
||
| 1 | Docker 镜像构建 | ✅ | `edu/data-ana:test` 构建成功 |
|
||
| 2 | 容器启动 + 健康检查 | ✅ | `/healthz` 200 OK, `/readyz` ready=true |
|
||
| 3 | ClickHouse 5 表 DDL | ✅ | 4 ReplacingMergeTree + 1 MergeTree |
|
||
| 4 | 种子数据写入 | ✅ | student_dashboard_view(8) + student_errors(3) + mastery_snapshot(6) |
|
||
| 5 | HTTP `/analytics/student/stu-001/weakness` | ✅ | 返回 2 个薄弱知识点(kp-math-002 mastery=0.35/0.45) |
|
||
| 6 | HTTP `/analytics/student/dashboard` | ✅ | 返回 8 条学情记录 + 薄弱点 + 趋势 + 掌握度 |
|
||
| 7 | HTTP `/analytics/student/stu-001/trend` | ✅ | 返回 8 个趋势点 |
|
||
| 8 | HTTP `/analytics/student/stu-001/errorbook` | ✅ | 返回 3 条错题记录 |
|
||
| 9 | HTTP `/analytics/student/stu-001/mastery` | ✅ | 返回 4 个知识点掌握度,overallMastery=0.6875 |
|
||
| 10 | gRPC `GetStudentWeakness` :50055 | ✅ | 返回 2 个 weak_points |
|
||
| 11 | gRPC `GetStudentMastery` :50055 | ✅ | 返回 4 个 knowledge_points,overall_mastery=0.6875 |
|
||
| 12 | gRPC `GetLearningTrend` :50055 | ✅ | 返回 8 个 trend points |
|
||
| 13 | ruff lint | ✅ | 零错误 |
|
||
|
||
**降级说明**:iam gRPC 未配置(`not_configured`),HTTP 响应标记 `degraded: true` + `degraded_reason: iam_grpc_unavailable_fallback`,但 ClickHouse 真实数据正常返回。班级级查询(`class/performance`、`class/mastery-distribution`)因 DataScope 校验降级返回空数据,iam 就绪后自动恢复。
|
||
|
||
---
|
||
|
||
## 5. 环境变量清单(Docker 部署)
|
||
|
||
| 变量 | 必填 | 示例值 | 说明 |
|
||
| ------------------------------ | ---- | -------------------- | -------------------------------------- |
|
||
| `DATA_ANA_HTTP_PORT` | 是 | `3006` | HTTP 监听端口 |
|
||
| `DATA_ANA_GRPC_PORT` | 是 | `50055` | gRPC 监听端口 |
|
||
| `DATA_ANA_DEV_MODE` | 否 | `true`/`false` | 开发模式(跳过部分校验) |
|
||
| `DATA_ANA_CLICKHOUSE_HOST` | 是 | `clickhouse` | ClickHouse 主机 |
|
||
| `DATA_ANA_CLICKHOUSE_PORT` | 否 | `8123` | ClickHouse HTTP 端口 |
|
||
| `DATA_ANA_CLICKHOUSE_DATABASE` | 否 | `edu_analytics` | ClickHouse 数据库 |
|
||
| `DATA_ANA_KAFKA_BROKERS` | 是 | `kafka:29092` | Kafka broker 地址 |
|
||
| `DATA_ANA_REDIS_URL` | 是 | `redis://redis:6379` | Redis 连接地址 |
|
||
| `DATA_ANA_IAM_GRPC_TARGET` | 是 | `iam:50052` | iam gRPC 目标 |
|
||
| `OTEL_TRACES_EXPORTER` | 否 | `none` | 禁用 OTel traces(collector 不可达时) |
|
||
|
||
---
|
||
|
||
## 6. 剩余工作
|
||
|
||
### 6.1 Docker 本地测试(已完成 2026-07-13)
|
||
|
||
| # | 工作项 | 状态 |
|
||
| --- | ------------------------------ | --------- |
|
||
| 1 | Docker 镜像构建 | ✅ 已通过 |
|
||
| 2 | ClickHouse 容器启动 + DDL 建表 | ✅ 已通过 |
|
||
| 3 | 种子数据写入 | ✅ 已通过 |
|
||
| 4 | data-ana 容器启动 + 健康检查 | ✅ 已通过 |
|
||
| 5 | HTTP 端点测试(无 mock 数据) | ✅ 已通过 |
|
||
| 6 | gRPC 端点测试 | ✅ 已通过 |
|
||
|
||
### 6.2 P6 硬化任务
|
||
|
||
| # | 工作项 | 状态 |
|
||
| --- | ------------------------------------ | --------- |
|
||
| 1 | CDC 多实例水平扩展 | ⏳ 未开始 |
|
||
| 2 | ExamCache Redis 化 | ⏳ 未开始 |
|
||
| 3 | 容量规划 + TTL 归档策略 | ⏳ 未开始 |
|
||
| 4 | 监控告警完善(Prometheus + Grafana) | ⏳ 未开始 |
|
||
| 5 | readyz 深度硬化(超时控制) | ⏳ 未开始 |
|
||
|
||
### 6.3 端到端联调
|
||
|
||
| # | 工作项 | 阻塞条件 | 状态 |
|
||
| --- | --------------------- | ------------------------------------- | ---- |
|
||
| 1 | teacher-bff gRPC 联调 | teacher-bff 配置 DATA_ANA_GRPC_TARGET | ⏳ |
|
||
| 2 | student-bff gRPC 联调 | student-bff 配置 DATA_ANA_GRPC_TARGET | ⏳ |
|
||
| 3 | parent-bff gRPC 联调 | parent-bff 配置 DATA_ANA_GRPC_TARGET | ⏳ |
|
||
| 4 | CDC 通道联调 | core-edu MySQL + Debezium 就绪 | ⏳ |
|
||
| 5 | AIUsageEvent 消费联调 | ai 服务发布事件 | ⏳ |
|
||
|
||
---
|
||
|
||
## 7. 关键文件路径
|
||
|
||
| 文件 | 用途 |
|
||
| -------------------------------------------------------------------- | ------------------------------------------------ |
|
||
| `services/data-ana/src/data_ana/main.py` | HTTP 14 端点 + lifespan(gRPC + CDC 启动) |
|
||
| `services/data-ana/src/data_ana/grpc_server.py` | gRPC 12 RPC(含 server-streaming) |
|
||
| `services/data-ana/src/data_ana/cdc_consumer.py` | CDC 消费者(5 表 + AIUsageEvent) |
|
||
| `services/data-ana/src/data_ana/analytics_service.py` | 4 端 Dashboard + DataScope 注入 |
|
||
| `services/data-ana/src/data_ana/mastery_service.py` | 掌握度算法(加权滑动平均 + 遗忘曲线) |
|
||
| `services/data-ana/src/data_ana/warning_service.py` | 5 类预警 + Redis 去重 |
|
||
| `services/data-ana/src/data_ana/config.py` | 全配置项(DATA_ANA_ 前缀) |
|
||
| `services/data-ana/src/data_ana/repository/clickhouse_repository.py` | ClickHouse 查询(FINAL/argMax 去重) |
|
||
| `services/data-ana/src/data_ana/repository/iam_client.py` | iam gRPC + Redis 缓存 + 降级 |
|
||
| `services/data-ana/src/data_ana/repository/kafka_producer.py` | Kafka 事件发布(idempotent) |
|
||
| `services/data-ana/src/generated_proto/` | Python protobuf 生成代码(analytics/iam/events) |
|
||
| `services/data-ana/scripts/clickhouse_ddl.sql` | 5 宽表建表脚本 |
|
||
| `services/data-ana/scripts/seed_clickhouse.py` | 种子数据脚本 |
|
||
| `services/data-ana/Dockerfile` | 多阶段构建(python:3.12-slim) |
|
||
| `packages/shared-proto/proto/analytics.proto` | gRPC 12 RPC 契约 |
|
||
|
||
---
|
||
|
||
**本文件由 ai11 维护。data-ana 已完成 P2-P5 全部代码实现 + Docker 本地测试通过(无 mock 数据,真实 ClickHouse 查询)。等待 iam 容器就绪后即可端到端联调。**
|