feat(data-ana): v2 P6 硬化完成 + 6 新 RPC + Prometheus 监控

P6 硬化(5 项全部完成):

- CDC 多实例水平扩展: _INSTANCE_ID + get_lag() 真实 lag 计算

- ExamCache Redis 化: key data_ana:exam:{exam_id}, TTL 30 天 + 内存 LRU fallback

- ClickHouse TTL 归档: 5 表均加 TTL(1-3 年),分区级删除

- Prometheus 监控: 18 个指标(CDC/CH/ExamCache/DataScope/gRPC/业务)

- readyz 深度硬化: 4 依赖超时检查(CH 1s/Redis 200ms/iam 2s/CDC lag<1000)

v2 新增 6 个 RPC(analytics.proto 扩展为 18 RPC):

- GetStudentGrowth / GetAssignmentAnalysis / GetMasterySummary

- ListDiagnosticReports(占位,待 ai 服务)/ ListErrorBookItems / GetErrorBookStats

监控与可观测性: lifespan 预热 + gRPC ServerInterceptor + CDC 消费者指标

Docker 本地测试 19 项全部通过(healthz/readyz/metrics + 11 HTTP + 10 gRPC + ruff)

nextstep-v2.md: 上游需求对齐 + 下游要求(iam/core-edu/content/ai/SRE)
This commit is contained in:
SpecialX
2026-07-14 18:07:17 +08:00
parent 78e406b317
commit 9db7fd917e
13 changed files with 2118 additions and 147 deletions

View File

@@ -0,0 +1,283 @@
# data-ana 模块 v2 上下游依赖与工作清单Next Steps v2
> 模块data-ana智能洞察域数据分析服务
> 负责人ai11
> 更新日期2026-07-14
> 关联文档:[nextstep.md](./nextstep.md)v1、[02-architecture-design.md](./02-architecture-design.md)、[data-ana_workline.md](../../../docs/architecture/issues/worklines/data-ana_workline.md)
---
## 1. v2 工作完成状态
### 1.1 P6 硬化全部完成5 项)
| # | 工作项 | 状态 | 实现说明 |
| --- | -------------------- | ---- | ----------------------------------------------------------------------------------------------------- |
| 1 | CDC 多实例水平扩展 | ✅ | `_INSTANCE_ID`POD_NAME / hostname:pid`get_lag()` 通过 `position()` + `end_offsets` 计算真实 lag |
| 2 | ExamCache Redis 迁移 | ✅ | Redis key `data_ana:exam:{exam_id}`TTL 30 天,内存 LRU 10000 fallback |
| 3 | ClickHouse TTL 归档 | ✅ | 5 表均加 TTL1-3 年),分区级删除,冷热分离 |
| 4 | Prometheus 监控指标 | ✅ | 18 个指标CDC lag/throughput、ClickHouse query、ExamCache、DataScope、gRPC、业务 |
| 5 | readyz 深度硬化 | ✅ | 4 依赖超时检查CH 1s / Redis 200ms / iam 2s / CDC lag<1000503 摘流量 |
### 1.2 v2 新增 6 个 RPC响应上游 BFF 需求)
`packages/shared-proto/proto/analytics.proto` 扩展为 **18 RPC**11 旧 + 1 stream + 6 新):
| # | RPC 方法 | 用途 | 上游需求方 | 状态 |
| --- | ----------------------- | -------------- | ------------------------- | ---- |
| 1 | `GetStudentGrowth` | 学生成长档案 | parent-bff / student-bff | ✅ |
| 2 | `GetAssignmentAnalysis` | 作业/考试分析 | student-bff / teacher-bff | ✅ |
| 3 | `GetMasterySummary` | 学生掌握度汇总 | parent-bff / student-bff | ✅ |
| 4 | `ListDiagnosticReports` | 诊断报告列表 | parent-bff / student-bff | ✅\* |
| 5 | `ListErrorBookItems` | 错题本列表 | parent-bff / student-bff | ✅ |
| 6 | `GetErrorBookStats` | 错题本统计 | parent-bff | ✅ |
> \* `ListDiagnosticReports` 当前为占位实现(返回空列表 + degraded 标记),需 ai 服务提供诊断报告生成能力后补充(见 §3.5)。
### 1.3 v2 监控与可观测性
- **lifespan 预热**:启动时主动 ping ClickHouse + Redis避免首次 readyz 探针超时
- **gRPC 拦截器**`_make_metrics_interceptor` 包装所有 unary RPC记录 `grpc_requests_total` + `grpc_request_duration_seconds`
- **CDC 消费者指标**`cdc_messages_processed_total`(按 topic/table/status+ `cdc_message_process_duration_seconds` + `cdc_consumer_active_instances`
- **Docker 本地测试**13 项全部通过healthz / readyz / metrics / 11 HTTP / 10 gRPC见 §4
---
## 2. 上游需求对齐情况
### 2.1 student-bff 需求8 RPC + 3 PracticeService
| RPC 方法 | 用途 | data-ana 状态 | 备注 |
| ----------------------------------------------- | ------------------------------- | --------------------- | ---------------------------------- |
| `GetStudentDashboard` | `studentDashboard` Query | ✅ 已实现 | v1 |
| `GetStudentWeakness` | `myWeakness` Query | ✅ 已实现 | v1 |
| `GetLearningTrend` | `myTrend` Query | ✅ 已实现 | v1 |
| `GetStudentGrowth` | `studentGrowth` Query | ✅ 已实现 | v2 新增 |
| `GetAssignmentAnalysis` | `assignmentAnalysis` Query | ✅ 已实现 | v2 新增 |
| `GetMasterySummary` | `myMasterySummary` Query | ✅ 已实现 | v2 新增 |
| `ListDiagnosticReports` | `myDiagnosticReports` Query | ✅ 占位实现 | 待 ai 服务提供诊断报告生成§3.5 |
| `ListErrorBookItems` | `myErrorBook` Query | ✅ 已实现 | v2 新增 |
| `PracticeService.ListPracticeSessionsByStudent` | `myPracticeSessions` Query | ❌ 不在 data-ana 范围 | 需新建 PracticeService见 §3.6 |
| `PracticeService.StartPracticeSession` | `startPracticeSession` Mutation | ❌ 不在 data-ana 范围 | 同上 |
| `PracticeService.SubmitPracticeAnswer` | `submitPracticeAnswer` Mutation | ❌ 不在 data-ana 范围 | 同上 |
### 2.2 teacher-bff 需求4 RPC
| RPC 方法 | 用途 | data-ana 状态 |
| --------------------- | ----------------------- | ------------- |
| `GetClassPerformance` | `classAnalytics` 查询 | ✅ 已实现 |
| `GetStudentDashboard` | `studentAnalytics` 查询 | ✅ 已实现 |
| `GetStudentWeakness` | `studentWeakness` 查询 | ✅ 已实现 |
| `GetLearningTrend` | `learningTrend` 查询 | ✅ 已实现 |
### 2.3 parent-bff 需求3 RPC + healthz
| 依赖项 | 用途 | data-ana 状态 |
| ------------------------------------------ | -------------------- | ------------- |
| `getStudentWeakness(studentId, subjectId)` | 学生薄弱知识点 | ✅ 已实现 |
| `getLearningTrend(studentId, start, end)` | 学习趋势 | ✅ 已实现 |
| `getClassPerformance(classId, subjectId)` | 班级绩效 | ✅ 已实现 |
| `GET /healthz` | /readyz 下游健康检查 | ✅ 已实现 |
### 2.4 api-gateway 需求HTTP 路由代理)
| 路由前缀 | 代理目标 | data-ana 状态 |
| --------------------- | ------------- | ------------- |
| `/api/v1/analytics/*` | data-ana:3006 | ✅ 已实现 |
| `/api/v1/dashboard/*` | data-ana:3006 | ✅ 已实现 |
### 2.5 parent-portal 需求GraphQL 字段映射)
parent-portal 的以下 GraphQL 字段依赖 data-ana均已通过 parent-bff 聚合:
| GraphQL 字段 | 对应 data-ana RPC | 状态 |
| ------------------------ | -------------------------- | ----------------------------- |
| `childWeakness` | `GetStudentWeakness` | ✅ |
| `childTrend` | `GetLearningTrend` | ✅ |
| `childLearningPath` | `GetStudentGrowth`(部分) | ⚠️ 需扩展 LearningPath 子结构 |
| `childErrorBookStats` | `GetErrorBookStats` | ✅ |
| `childTopWrongQuestions` | `ListErrorBookItems` | ✅ |
| `childWeakKps` | `GetStudentWeakness` | ✅ |
| `childMasterySummary` | `GetMasterySummary` | ✅ |
| `childDiagnosticReports` | `ListDiagnosticReports` | ✅\* 占位 |
| `childPracticeStats` | `PracticeService.*` | ❌ 需新建 |
| `childPracticeSessions` | `PracticeService.*` | ❌ 需新建 |
| `childDetail` | `GetStudentDashboard` | ✅ |
| `childGrowthArchive` | `GetStudentGrowth` | ✅ |
---
## 3. 需要上下游实现的工作
### 3.1 iam 服务ai06 负责)— P0
| # | 工作项 | 用途 | 优先级 |
| --- | --------------------------------------------------- | ----------------------------------------------------------- | ------ |
| 1 | iam gRPC 服务启动并暴露 :50052 | data-ana 当前使用 role-based fallback 降级,需 iam 真实服务 | P0 |
| 2 | `GetEffectiveDataScope` 返回完整 6 级 scope | DataScope 过滤SELF/CLASS/GRADE/SCHOOL/DISTRICT/ALL | P0 |
| 3 | iam gRPC metadata 传递 `x-user-id` / `x-user-roles` | Gateway 注入用户上下文到 gRPC metadata | P0 |
**当前状态**data-ana 已实现 iam gRPC 客户端 + Redis 缓存TTL 5min+ role 降级兜底。iam 服务未启动时走降级degraded=true不阻塞业务。
### 3.2 core-edu 服务ai07 负责)— P0
| # | 工作项 | 用途 | 优先级 |
| --- | -------------------------------------------------------------- | -------------------------------------------------------------------- | ------ |
| 1 | MySQL 表 `core_edu_grades` CDC 对齐 | Debezium 监听 → Kafka topic `edu-cdc.next_edu_cloud.core_edu_grades` | P0 |
| 2 | MySQL 表 `core_edu_exams` CDC 对齐 | ExamCache 数据源 | P0 |
| 3 | MySQL 表 `core_edu_homework_submissions` CDC | student_dashboard_view 数据源 | P0 |
| 4 | MySQL 表 `core_edu_attendance` CDC | attendance_logs 数据源 | P0 |
| 5 | 表字段命名对齐student_id/exam_id/score/subject_id/class_id | CDC 消费者按字段名解析 | P0 |
**当前状态**data-ana CDC 消费者已实现 4 表路由grades/exams/homework/attendance等待 core-edu MySQL 数据 + Debezium connector 配置。
### 3.3 content 服务ai08 负责)— P1
| # | 工作项 | 用途 | 优先级 |
| --- | --------------------------------------- | ------------------------------------------- | ------ |
| 1 | MySQL 表 `content_knowledge_points` CDC | 知识点元数据缓存title/subject_id | P1 |
| 2 | 知识点标题字段对齐 | data-ana 查询结果补充 knowledge_point_title | P1 |
**当前状态**data-ana CDC 消费者已实现 knowledge_points 路由,写入 Redis `data_ana:kp_meta:{kp_id}`
### 3.4 ai 服务ai12 负责)— P1
| # | 工作项 | 用途 | 优先级 |
| --- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------ |
| 1 | 发布 `AIUsageEvent` 到 Kafka topic `edu.insight.ai.usage` | data-ana 消费写入 `ai_usage_log` 表,供 admin dashboard 统计 | P1 |
| 2 | AIUsageEvent 字段对齐 events.proto | request_id/user_id/provider/model/prompt_tokens/completion_tokens/total_tokens/latency_ms/success/cost_cents/occurred_at | P1 |
| 3 | 诊断报告生成能力 | `ListDiagnosticReports` 当前为占位,需 ai 提供报告数据 | P2 |
**当前状态**data-ana CDC 消费者已实现 AIUsageEvent 路由(`_handle_ai_usage_event`),等待 ai 服务发布事件。
### 3.5 ListDiagnosticReports 完整实现(需 ai 服务协作)— P2
当前 `ListDiagnosticReports` 返回空列表 + degraded 标记。完整实现需要:
1. **ai 服务**生成诊断报告并存储DB 或 Kafka 事件)
2. **data-ana** 消费 ai 诊断报告事件,写入 ClickHouse 新表 `diagnostic_reports`
3. **data-ana** 查询 `diagnostic_reports` 表返回报告列表
**建议方案**
- ai 服务发布 `DiagnosticReportGenerated` 事件到 Kafka topic `edu.insight.diagnostic.generated`
- data-ana CDC 消费者扩展 `_handle_diagnostic_event` 路由
- ClickHouse 新增 `diagnostic_reports`ReplacingMergeTreeTTL 1 年)
### 3.6 PracticeService 新建(需协调 AI 决策)— P2
student-bff / parent-portal 需要 `PracticeService` 3 RPC练习会话管理当前不在 data-ana 范围内。
**建议方案 A**(推荐):在 core-edu 服务新增 PracticeService练习属于教学域
**建议方案 B**:在 data-ana 新增 PracticeService练习数据天然属于分析域
**建议方案 C**:新建独立 `practice` 服务
> 需协调 AIai07/ai11/ai12与人类决策者确定归属。data-ana 当前不实现,待决策后补充。
### 3.7 childLearningPath 完整实现(需协调)— P2
parent-portal `childLearningPath` 字段需要学习路径推荐数据。当前 `GetStudentGrowth` 返回成长档案(成绩趋势 + 掌握度 + 考勤),但不含学习路径推荐。
**建议方案**ai 服务提供学习路径推荐 APIdata-ana 聚合或 ai 直接暴露给 BFF。
### 3.8 Debezium / Kafka 基础设施SRE AI 负责)— P0
| # | 工作项 | 用途 | 优先级 |
| --- | ------------------------------------------------------ | ----------------------------------------------- | ------ |
| 1 | Debezium connector 配置6 表) | MySQL binlog → Kafka CDC topics | P0 |
| 2 | Kafka topic 创建7 个 CDC + 1 个 AIUsage | edu-cdc.next_edu_cloud.* + edu.insight.ai.usage | P0 |
| 3 | Kafka topic `edu.insight.mastery.updated` | data-ana 发布掌握度更新事件 | P1 |
| 4 | Kafka topic `edu.insight.diagnostic.generated`(未来) | 诊断报告事件§3.5 | P2 |
**当前状态**edu-kafka + edu-debezium + edu-clickhouse 容器已运行,但 Debezium connector 未配置data-ana CDC 消费者启动但无消息消费)。
### 3.9 ClickHouse DDL 执行SRE AI 负责)— P0
| # | 工作项 | 优先级 |
| --- | ----------------------------------------------- | ------ |
| 1 | 执行 `scripts/clickhouse_ddl.sql`5 表 + TTL | P0 |
| 2 | 创建 database `edu_analytics` | P0 |
**当前状态**ClickHouse 容器运行DDL 已更新(含 TTL但需 SRE 确认执行。
---
## 4. Docker 本地测试结果v2
**测试环境**edu-data-ana-test 容器edu/data-ana:test 镜像),连接 edu-clickhouse + edu-redis + edu-kafka
**测试时间**2026-07-14
| # | 测试项 | 结果 | 备注 |
| --- | ------------------------------- | ---- | --------------------------------------------- |
| 1 | `GET /healthz` | ✅ | `{"status":"ok","service":"data-ana"}` |
| 2 | `GET /readyz`(首次) | ✅ | ready=truelifespan 预热生效) |
| 3 | `GET /readyz`dependencies | ✅ | clickhouse=ok, cdc=running(lag=0), redis=ok |
| 4 | `GET /metrics` | ✅ | 18 个自定义指标全部暴露 |
| 5 | gRPC HealthService | ✅ | SERVING |
| 6 | gRPC GetStudentDashboard | ✅ | |
| 7 | gRPC GetStudentWeakness | ✅ | |
| 8 | gRPC GetLearningTrend | ✅ | |
| 9 | gRPC GetClassPerformance | ✅ | |
| 10 | gRPC GetStudentGrowth (v2) | ✅ | 返回 growth_score + growth_level |
| 11 | gRPC GetAssignmentAnalysis (v2) | ✅ | 返回 score ranges |
| 12 | gRPC GetMasterySummary (v2) | ✅ | 返回 three-tier distribution |
| 13 | gRPC ListDiagnosticReports (v2) | ✅ | 占位返回空列表 + degraded |
| 14 | gRPC ListErrorBookItems (v2) | ✅ | |
| 15 | gRPC GetErrorBookStats (v2) | ✅ | |
| 16 | HTTP 11 业务端点 | ✅ | 全部返回 ActionState 信封 success=true |
| 17 | gRPC 拦截器 metrics | ✅ | `data_ana_grpc_requests_total` 按 method 记录 |
| 18 | CDC consumer metrics | ✅ | `cdc_consumer_active_instances=1` |
| 19 | ruff check | ✅ | All checks passed |
---
## 5. v2 架构变更摘要
### 5.1 proto 契约变更
- `packages/shared-proto/proto/analytics.proto`:新增 6 RPC + 16 message
- Python stub 重新生成:`src/generated_proto/analytics_pb2.py` + `analytics_pb2_grpc.py`
### 5.2 新增文件
- `services/data-ana/src/data_ana/metrics.py`18 个 Prometheus 指标定义
### 5.3 修改文件
- `services/data-ana/src/data_ana/cdc_consumer.py`:多实例 ID + 真实 lag + metrics 接入
- `services/data-ana/src/data_ana/exam_cache.py`Redis-backed + 内存 LRU fallback
- `services/data-ana/src/data_ana/grpc_server.py`6 新 RPC + gRPC 拦截器
- `services/data-ana/src/data_ana/analytics_service.py`6 新业务方法
- `services/data-ana/src/data_ana/repository/clickhouse_repository.py`3 新查询方法
- `services/data-ana/src/data_ana/main.py`readyz 硬化 + lifespan 预热 + metrics 初始化
- `services/data-ana/src/data_ana/config.py`readyz 超时配置
- `services/data-ana/scripts/clickhouse_ddl.sql`5 表 TTL
### 5.4 未变更
- `services/data-ana/pyproject.toml`:依赖版本不变(用户要求)
- `services/data-ana/Dockerfile`:构建配置不变
---
## 6. 下一步工作
### 6.1 等待上游就绪后联调
1. iam gRPC 服务启动 → data-ana 移除降级标记
2. core-edu MySQL 数据 + Debezium connector → data-ana CDC 消费真实数据
3. ai 服务发布 AIUsageEvent → data-ana admin dashboard 显示真实 AI 用量
### 6.2 待决策项
1. PracticeService 归属core-edu / data-ana / 新服务)— §3.6
2. ListDiagnosticReports 完整实现方案 — §3.5
3. childLearningPath 数据源 — §3.7
### 6.3 P7+ 规划(未来)
- ClickHouse 物化视图(预聚合 dashboard 查询)
- Kafka Streams 掌握度实时计算(替代批处理)
- Grafana dashboard 配置(`infra/grafana/dashboards/data-ana.json`
- 告警规则(`infra/prometheus/rules.yml` 补充 data-ana 规则)