data-ana 数据分析服务
版本:1.0(P4 完整版)
阶段:D6 智能洞察领域(仲裁已对齐,v2 实现版)
端口:HTTP 3006(Gateway 直连降级)+ gRPC 50055(主入口,BFF/ai 调用)
日期:2026-07-10
职责
数据分析限界上下文(Python/FastAPI 微服务),消费 core-edu / content / iam / ai 的 CDC 事件,
构建 ClickHouse 学情宽表,计算知识点掌握度,评估预警,为前端提供 4 端 Dashboard 查询服务。
核心能力
- 5 张宽表:student_dashboard_view / student_errors / mastery_snapshot / attendance_logs / ai_usage_log
- CDC 链路:Debezium → Kafka → data-ana 消费 → ClickHouse(at-least-once + 手动 commit + ReplacingMergeTree 去重)
- 掌握度算法:WEIGHTED_MOVING_AVG(w_i=0.6^i)+ FORGETTING_CURVE(半衰期 30 天)取 max
- 预警评估:5 类预警(LOW_MASTERY / CRITICAL_LOW / SCORE_DROP / ABSENT_FREQUENT / TREND_DECLINE)+ Redis 25h 去重
- DataScope 过滤:6 级(SELF/CLASS/GRADE/SCHOOL/DISTRICT/ALL),iam gRPC + 角色降级
- gRPC 12 RPC:AnalyticsService(含 server-streaming SubscribeMasteryUpdate)+ HealthService
- HTTP 14 端点:3 基础 + 11 业务(ActionState 信封 + degraded 标记)
架构图
技术栈
- Python 3.12+ / FastAPI 0.115+(HTTP 端点)
- grpcio 1.66+ / grpcio-health-checking(gRPC server + HealthService)
- clickhouse-connect 0.7+(ClickHouse 宽表查询,支持 FINAL/argMax)
- aiokafka 0.11+(CDC 消费者,手动 commit + 幂等去重)
- redis 5.0+(DataScope 缓存 + 事件去重 + 预警位图)
- pydantic 2.9+ / pydantic-settings 2.5+(模型校验 + 配置)
- structlog 24.4+(结构化 JSON 日志)
- prometheus-client 0.20+(/metrics 指标)
- opentelemetry-sdk 1.27+(OTLP 链路追踪)
- protobuf 5.28+(buf generate 生成的 stub 运行时)
模块结构
开发
配置项
所有配置使用 DATA_ANA_ 前缀(pydantic-settings env_prefix)。
基础配置
| 变量 |
默认值 |
说明 |
DATA_ANA_HTTP_PORT |
3006 |
HTTP 端口(Gateway 直连降级) |
DATA_ANA_GRPC_PORT |
50055 |
gRPC 端口(AnalyticsService 主入口) |
DATA_ANA_DEV_MODE |
true |
开发模式(关闭签名校验) |
DATA_ANA_LOG_LEVEL |
info |
日志级别(debug/info/warning/error) |
DATA_ANA_OTEL_ENDPOINT |
http://localhost:4318 |
OpenTelemetry OTLP 端点 |
外部依赖(全部可选,未配置则降级模式)
| 变量 |
默认值 |
说明 |
DATA_ANA_CLICKHOUSE_HOST |
"" |
ClickHouse 主机(空字符串=降级模式) |
DATA_ANA_CLICKHOUSE_PORT |
8123 |
ClickHouse HTTP 端口 |
DATA_ANA_CLICKHOUSE_DATABASE |
edu_analytics |
ClickHouse 数据库 |
DATA_ANA_CLICKHOUSE_USER |
"" |
ClickHouse 用户名 |
DATA_ANA_CLICKHOUSE_PASSWORD |
"" |
ClickHouse 密码 |
DATA_ANA_KAFKA_BROKERS |
"" |
Kafka broker 列表(逗号分隔,空=禁用 CDC) |
DATA_ANA_KAFKA_GROUP_ID |
data-ana-cdc |
消费者组 ID |
DATA_ANA_REDIS_URL |
"" |
Redis URL(空=禁用缓存/去重) |
DATA_ANA_IAM_GRPC_ENDPOINT |
"" |
iam gRPC 端点(空=角色降级) |
降级模式说明
- ClickHouse 未配置/不可达:查询返回骨架数据(空数组 + degraded=true)
- Kafka 未配置:CDC 消费者不启动,
/readyz 仍就绪
- Redis 未配置/不可达:缓存失效,每次查询重新计算 DataScope
- iam gRPC 未配置/不可达:基于 JWT 角色 fallback(teacher→CLASS,student→SELF)
- grpcio 未安装:gRPC server 不启动,HTTP 仍可用
端点清单
基础端点(3 个)
| 方法 |
路径 |
说明 |
| GET |
/ |
根信息(服务名/版本/端点列表) |
| GET |
/healthz |
liveness 检查(进程存活即 ok) |
| GET |
/readyz |
readiness 检查(5 依赖状态:clickhouse/cdc/redis/iam/grpc) |
| GET |
/metrics |
Prometheus 指标 |
业务端点(11 个,全部返回 ActionState[T])
| 方法 |
路径 |
说明 |
| GET |
/analytics/class/{class_id}/performance |
班级成绩分析(平均分/及格率) |
| GET |
/analytics/class/{class_id}/mastery-distribution |
班级掌握度分布(三档) |
| GET |
/analytics/student/{student_id}/weakness |
学生薄弱知识点(mastery < 0.6) |
| GET |
/analytics/student/{student_id}/mastery |
学生掌握度明细 |
| GET |
/analytics/student/{student_id}/trend |
学习趋势(历史成绩曲线) |
| GET |
/analytics/student/{student_id}/errorbook |
学生错题本 |
| GET |
/analytics/teacher/dashboard |
教师仪表盘 |
| GET |
/analytics/student/dashboard |
学生仪表盘 |
| GET |
/analytics/parent/dashboard |
家长仪表盘 |
| GET |
/analytics/admin/dashboard |
管理员仪表盘 |
| GET |
/analytics/warnings |
预警列表 |
| POST |
/analytics/warnings/trigger |
手动触发预警 |
ActionState 信封格式
降级时 degraded=true,data 返回骨架数据(空数组/零值)。
gRPC 契约
AnalyticsService(12 RPC,端口 50055)
| RPC |
类型 |
说明 |
| GetClassPerformance |
unary |
班级成绩分析 |
| GetStudentWeakness |
unary |
学生薄弱知识点 |
| GetLearningTrend |
unary |
学习趋势 |
| GetTeacherDashboard |
unary |
教师仪表盘 |
| GetStudentDashboard |
unary |
学生仪表盘 |
| GetParentDashboard |
unary |
家长仪表盘 |
| GetAdminDashboard |
unary |
管理员仪表盘 |
| GetWarnings |
unary |
预警列表 |
| TriggerWarning |
unary |
手动触发预警 |
| GetMasteryDistribution |
unary |
班级掌握度分布 |
| GetStudentMastery |
unary |
学生掌握度明细 |
| SubscribeMasteryUpdate |
server-streaming |
掌握度更新订阅(P5+ AI 个性化通道) |
HealthService
grpc.health.v1.Health 标准 K8s 探针。
proto 定义
packages/shared-proto/proto/analytics.proto(12 RPC + 全部消息)
packages/shared-proto/proto/events.proto(MasteryEvent + AIUsageEvent)
packages/shared-proto/proto/iam.proto(GetEffectiveDataScope)
CDC 事件消费
消费的 7 类事件
| 事件源 |
Topic |
处理 |
| core-edu.exams |
edu-cdc.next_edu_cloud.core_edu_exams |
写 exam_cache |
| core-edu.grades |
edu-cdc.next_edu_cloud.core_edu_grades |
写 student_dashboard_view |
| core-edu.homework |
edu-cdc.next_edu_cloud.core_edu_homework |
写 student_dashboard_view |
| core-edu.attendance |
edu-cdc.next_edu_cloud.core_edu_attendance |
写 attendance_logs |
| content.knowledge_points |
edu-cdc.next_edu_cloud.content_knowledge_points |
知识点元数据 |
| ai.ai_usage |
edu.insight.ai.usage |
写 ai_usage_log |
幂等保证
- Kafka producer:
enable_idempotence=True + transactional_id
- Consumer 去重:Redis SETNX
data_ana:dedup:{event_id} TTL 7 天
- ClickHouse 去重:ReplacingMergeTree(last_updated) + FINAL/argMax 查询
- 手动 commit:仅在 ClickHouse 写入成功后 commit(at-least-once 语义)
发布的派生数据事件
| 事件 |
Topic |
触发条件 |
Outbox 豁免 |
| MasteryUpdated |
edu.insight.mastery.updated |
掌握度计算完成 |
✅(004 §12.2 仲裁) |
| WarningTriggered |
edu.insight.mastery.updated(复用) |
预警阈值触发 |
✅(004 §15.3 #6 仲裁) |
Outbox 豁免理由:派生数据事件,无业务状态变更,重复消费幂等。
ClickHouse 宽表
DDL 位置:scripts/clickhouse-init.sql
| 表名 |
引擎 |
ORDER BY |
用途 |
| student_dashboard_view |
ReplacingMergeTree(last_updated) |
(student_id, exam_id, knowledge_point_id) |
学情宽表 |
| student_errors |
ReplacingMergeTree(last_error_time) |
(student_id, question_id) |
错题本 |
| mastery_snapshot |
MergeTree |
(student_id, knowledge_point_id, calculated_at) |
掌握度历史快照 |
| ai_usage_log |
ReplacingMergeTree(occurred_at) |
(request_id,) |
AI 用量计费 |
| attendance_logs |
ReplacingMergeTree(occurred_at) |
(student_id, class_id, attendance_date) |
考勤记录 |
Mock 数据:scripts/data-ana-mock-data.sql
掌握度算法
公式
分类
| 区间 |
label |
说明 |
| ≥ 0.8 |
mastered |
已掌握 |
| 0.4 - 0.8 |
progressing |
进展中 |
| < 0.4 |
weak |
薄弱 |
降级规则
- 近 5 次成绩不足 5 次 → 降级 SIMPLE_AVG
- 无历史数据 → 返回 0.0 + label=weak
预警类型
| 类型 |
阈值 |
severity |
说明 |
| LOW_MASTERY |
mastery < 0.4 |
WARN |
掌握度低 |
| CRITICAL_LOW |
mastery < 0.2 |
CRITICAL |
严重低 |
| SCORE_DROP |
下降 ≥ 20% |
WARN |
成绩下降 |
| ABSENT_FREQUENT |
≥ 3 次/周 |
WARN |
频繁缺勤 |
| TREND_DECLINE |
连续 3 次降 |
INFO |
趋势下降 |
去重
- Redis key:
data_ana:warning:{target_id}:{type}:{date}
- TTL:25 小时(跨日保证)
DataScope 过滤
6 级
| 级别 |
scope_ids 含义 |
| SELF |
学生本人 ID |
| CLASS |
可见 class_id 列表 |
| GRADE |
可见 grade_id 列表 |
| SCHOOL |
可见 school_id 列表 |
| DISTRICT |
可见 district_id 列表 |
| ALL |
无过滤 |
解析链
角色降级(iam 不可用时)
| JWT 角色 |
降级 scope |
| teacher |
CLASS(自己教的班级) |
| student |
SELF(本人) |
| parent |
SELF(本人 + 孩子) |
| admin |
ALL |
部署
Docker
健康检查
- HTTP
/healthz:进程存活即 ok
- HTTP
/readyz:检查 5 依赖(clickhouse/cdc/redis/iam/grpc)
- gRPC
grpc.health.v1.Health:K8s 探针
对外契约
- gRPC proto:
packages/shared-proto/proto/analytics.proto
- HTTP OpenAPI:启动后访问
/docs
- CDC topic 命名:
edu-cdc.next_edu_cloud.<table>(Debezium 标准)
- 派生事件 topic:
edu.insight.mastery.updated / edu.insight.ai.usage
相关文档