Files
Edu/docs/architecture/004_architecture_impact_map.md
SpecialX 2ba4250165
Some checks failed
CI Go / test (push) Has been cancelled
CI Proto / lint (push) Has been cancelled
CI Python / test (push) Has been cancelled
CI TypeScript / test (push) Has been cancelled
feat(p1): complete P1 foundation stage
- monorepo: pnpm workspace + go.work + pyproject.toml + commitlint/husky
- infra: docker-compose (minimal + full profiles) + init-sql + prometheus
- arch-scan: multi-language scanner skeleton (TS/Go/Python/Proto)
- shared-proto: buf v2 + classes.proto (ClassService CRUD contract)
- api-gateway: Go/Gin + JWT HS256 auth + reverse proxy + request ID
- classes: NestJS golden template (error system + observability + middleware + CRUD + tests)
- teacher-portal: Next.js + paper-feel UI design system
- CI/CD: 4 workflows (go/ts/py/proto)
- docs: migration guide + project_rules + coding-standards + git-workflow + ui-design-system + 004 + 9 module READMEs + known-issues + spec/plan migration + roadmap
2026-07-07 23:39:37 +08:00

946 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 架构影响地图(微服务版)
> 版本1.0
> 日期2026-07-07
> 状态:基线发布
> 适用范围Edu 微服务架构DDD + EDA + CQRS
> 关联文档:
> - [理想蓝图](./0010_architecture.md)
> - [项目规则](../../project_rules.md)
> - [路线图](./roadmap/README.md)
---
## 目录
1. [项目概述](#1-项目概述)
2. [技术栈](#2-技术栈)
3. [分层架构](#3-分层架构)
4. [服务依赖图](#4-服务依赖图)
5. [认证与权限](#5-认证与权限)
6. [数据访问与缓存](#6-数据访问与缓存)
7. [事件驱动架构](#7-事件驱动架构)
8. [跨服务协作](#8-跨服务协作)
9. [核心业务流程](#9-核心业务流程)
10. [可观测性](#10-可观测性)
11. [契约与 API 架构](#11-契约与-api-架构)
12. [架构约束](#12-架构约束)
13. [ADR 记录](#13-adr-记录)
14. [附录6 阶段路线图](#14-附录6-阶段路线图)
---
## 1. 项目概述
### 1.1 系统边界
```mermaid
graph TB
subgraph Users["用户层"]
Teacher[教师]
Student[学生]
Parent[家长]
Admin[管理员]
end
subgraph MFE["微前端层Module Federation"]
TeacherPortal[teacher-portal]
StudentPortal[student-portal]
ParentPortal[parent-portal]
AdminPortal[admin-portal]
end
subgraph Gateway["网关层Go"]
APIGateway[api-gateway<br/>Gin + JWT + 限流]
PushGateway[push-gateway<br/>WebSocket/SSE]
end
subgraph BFF["BFF 聚合层NestJS"]
TeacherBFF[teacher-bff<br/>GraphQL]
StudentBFF[student-bff<br/>GraphQL]
ParentBFF[parent-bff<br/>GraphQL]
end
subgraph Services["业务微服务NestJS + FastAPI"]
IAM[iam<br/>身份认证]
CoreEdu[core-edu<br/>教学核心]
Content[content<br/>内容资源]
DataAna[data-ana<br/>数据分析 Python]
Msg[msg<br/>消息通知]
AI[ai<br/>AI 网关 Python]
end
subgraph Bus["事件总线"]
Kafka[(Kafka)]
Debezium[Debezium CDC]
end
subgraph Data["数据层"]
MySQL[(MySQL<br/>每服务独占)]
Redis[(Redis<br/>缓存/会话)]
ClickHouse[(ClickHouse<br/>读模型宽表)]
Neo4j[(Neo4j<br/>知识图谱)]
ES[(Elasticsearch<br/>题库检索)]
end
Teacher --> TeacherPortal
Student --> StudentPortal
Parent --> ParentPortal
Admin --> AdminPortal
TeacherPortal --> APIGateway
StudentPortal --> APIGateway
ParentPortal --> APIGateway
AdminPortal --> APIGateway
TeacherPortal -.推送.-> PushGateway
StudentPortal -.推送.-> PushGateway
APIGateway --> TeacherBFF
APIGateway --> StudentBFF
APIGateway --> ParentBFF
TeacherBFF --> IAM
TeacherBFF --> CoreEdu
TeacherBFF --> Content
TeacherBFF --> DataAna
StudentBFF --> IAM
StudentBFF --> CoreEdu
ParentBFF --> IAM
ParentBFF --> CoreEdu
CoreEdu <--> Kafka
Content <--> Kafka
DataAna <--> Kafka
Msg <--> Kafka
IAM <--> Kafka
MySQL --> Debezium
Debezium --> Kafka
IAM --> MySQL
CoreEdu --> MySQL
Content --> Neo4j
DataAna --> ClickHouse
Msg --> MySQL
AI --> ES
IAM --> Redis
CoreEdu --> Redis
```
### 1.2 服务清单
| 类别 | 服务名 | 语言/框架 | 限界上下文 | 阶段 |
|------|--------|-----------|-----------|------|
| 基础设施 | api-gateway | Go (Gin) | 网关 | P1 |
| 基础设施 | push-gateway | Go (Gin) | 推送 | P5 |
| BFF | teacher-bff | TS (NestJS) | 教师聚合 | P2 |
| BFF | student-bff | TS (NestJS) | 学生聚合 | P3 |
| BFF | parent-bff | TS (NestJS) | 家长聚合 | P4 |
| 业务 | iam | TS (NestJS) | 身份认证 | P2 |
| 业务 | core-edu | TS (NestJS) | 教学核心 | P3 |
| 业务 | content | TS (NestJS) | 内容资源 | P4 |
| 业务 | data-ana | Python (FastAPI) | 数据分析 | P4 |
| 业务 | msg | TS (NestJS) | 消息通知 | P5 |
| 业务 | ai | Python (FastAPI) | AI 网关 | P5 |
| 微前端 | teacher-portal | TS (Next.js) | 教师端 | P2 |
| 微前端 | student-portal | TS (Next.js) | 学生端 | P3 |
| 微前端 | parent-portal | TS (Next.js) | 家长端 | P4 |
| 微前端 | admin-portal | TS (Next.js) | 管理端 | P6 |
| 共享包 | shared-proto | TS | protobuf 契约 | P1 |
| 共享包 | shared-ts | TS | TS 共享工具 | P1 |
| 共享包 | shared-go | Go | Go 共享工具 | P1 |
| 共享包 | shared-py | Python | Python 共享工具 | P4 |
### 1.3 CICD → Edu 模块映射
| CICD 模块(旧) | Edu 服务(新) | 迁移阶段 |
|----------------|---------------|----------|
| auth + users + rbac | iam | P2 |
| classes + subjects + enrollment | core-edu | P3 |
| courses + lessons + schedule + attendance | core-edu | P3 |
| assignments + grades + exams | core-edu | P3 |
| textbooks + knowledge-points | content | P4 |
| questions + grading | content | P4 |
| messaging + notifications | msg | P5 |
| analytics + dashboard + diagnostic | data-ana | P4 |
| ai + lesson-preparation | ai | P5 |
| search | content (ES) | P4 |
---
## 2. 技术栈
### 2.1 多语言技术栈矩阵
| 层级 | 语言 | 框架 | 用途 |
|------|------|------|------|
| 网关层 | Go 1.22+ | Gin | API Gateway、Push Gateway |
| 业务服务 | TypeScript 5.5+ | NestJS 10 | IAM、CoreEdu、Content、Msg |
| 分析/AI | Python 3.12+ | FastAPI | DataAna、AI 网关 |
| BFF | TypeScript 5.5+ | NestJS 10 + GraphQL | 教师/学生/家长聚合 |
| 微前端 | TypeScript 5.5+ | Next.js 15 + Module Federation | 4 端门户 |
| 契约 | protobuf | buf | 跨语言契约定义 |
### 2.2 多存储矩阵
| 存储 | 用途 | 使用服务 |
|------|------|----------|
| MySQL 8 | 写模型主库(每服务独占) | IAM、CoreEdu、Content、Msg |
| Redis 7 | 缓存、会话、限流计数 | 全部服务 |
| ClickHouse | 读模型宽表、分析聚合 | DataAna、CoreEdu读模型 |
| Neo4j | 知识图谱、前置依赖 | Content |
| Elasticsearch | 题库全文检索 | Content、AI |
### 2.3 基础设施矩阵
| 组件 | 用途 |
|------|------|
| Kafka | 事件总线,领域事件异步通信 |
| Debezium | CDCMySQL Binlog → Kafka 实时同步 |
| Temporal | 工作流编排考试生命周期、AI 编排) |
| OpenTelemetry | 分布式追踪 |
| Loki | 日志聚合 |
| Tempo | 分布式 Trace 存储 |
| Prometheus | 指标采集 |
| Grafana | 可观测性可视化 |
| Vault | 密钥管理P6 |
---
## 3. 分层架构
### 3.1 六层架构
```mermaid
graph TB
subgraph L1["L1 客户端层"]
Browser[浏览器]
Mobile[移动端]
end
subgraph L2["L2 微前端层"]
MFE[Module Federation<br/>4 端门户]
end
subgraph L3["L3 网关层"]
GW[API Gateway Go<br/>路由+鉴权+限流+熔断]
Push[Push Gateway Go<br/>WebSocket/SSE]
end
subgraph L4["L4 BFF 聚合层"]
BFF[BFF NestJS<br/>聚合+裁剪+协议转换]
end
subgraph L5["L5 业务微服务层"]
SVC[6 业务服务<br/>DDD+CQRS]
end
subgraph L6["L6 数据与总线层"]
DB[(MySQL/CH/Neo4j/ES)]
KAFKA[(Kafka)]
TEMPORAL[Temporal]
end
Browser --> MFE
Mobile --> MFE
MFE --> GW
MFE -.推送.-> Push
GW --> BFF
BFF --> SVC
SVC --> DB
SVC <--> KAFKA
SVC --> TEMPORAL
```
### 3.2 依赖方向
```
L1 客户端 → L2 微前端 → L3 网关 → L4 BFF → L5 业务服务 → L6 数据/总线
```
**严格规则**
1. L3 网关层只做路由、鉴权、限流、熔断,**不写业务逻辑**
2. L4 BFF 层只做聚合、裁剪、协议转换,**不持有业务状态**
3. L5 业务服务之间通过 gRPC同步或 Kafka 事件(异步)通信,**不直接访问对方数据库**
4. L6 数据层每个微服务独占自身数据库,**禁止跨库联表**
---
## 4. 服务依赖图
```mermaid
graph TB
subgraph Gateway["网关层"]
APIGW[api-gateway]
PushGW[push-gateway]
end
subgraph BFF["BFF 层"]
TBFF[teacher-bff]
SBFF[student-bff]
PBFF[parent-bff]
end
subgraph Services["业务服务"]
IAM[iam]
CoreEdu[core-edu]
Content[content]
DataAna[data-ana]
Msg[msg]
AI[ai]
end
subgraph Shared["共享包"]
Proto[shared-proto]
SharedTS[shared-ts]
end
APIGW --> TBFF
APIGW --> SBFF
APIGW --> PBFF
PushGW --> Msg
TBFF --> IAM
TBFF --> CoreEdu
TBFF --> Content
TBFF --> DataAna
TBFF --> AI
SBFF --> IAM
SBFF --> CoreEdu
SBFF --> Content
SBFF --> DataAna
PBFF --> IAM
PBFF --> CoreEdu
CoreEdu -.事件.-> Content
CoreEdu -.事件.-> DataAna
CoreEdu -.事件.-> Msg
Content -.事件.-> DataAna
IAM -.事件.-> CoreEdu
IAM -.事件.-> Msg
AI -.gRPC.-> Content
AI -.gRPC.-> DataAna
IAM --> Proto
CoreEdu --> Proto
Content --> Proto
DataAna --> Proto
Msg --> Proto
AI --> Proto
IAM --> SharedTS
CoreEdu --> SharedTS
Content --> SharedTS
Msg --> SharedTS
```
### 4.1 服务间通信矩阵
| 调用方 → 被调用方 | 协议 | 场景 |
|-------------------|------|------|
| api-gateway → BFF | gRPC | 请求路由 |
| BFF → 业务服务 | gRPC | 同步查询聚合 |
| CoreEdu → Content | Kafka 事件 | 教学内容变更通知 |
| CoreEdu → DataAna | Kafka 事件 | 学情数据投递 |
| CoreEdu → Msg | Kafka 事件 | 通知触发 |
| IAM → CoreEdu | Kafka 事件 | 用户变更同步 |
| AI → Content | gRPC | 题库查询 |
| AI → DataAna | gRPC | 学情数据查询 |
| push-gateway → Msg | gRPC | 推送通道建立 |
---
## 5. 认证与权限
### 5.1 JWT RS256 认证流程
```mermaid
sequenceDiagram
participant U as 用户
participant GW as API Gateway
participant IAM as IAM 服务
participant SVC as 业务服务
rect rgb(240, 248, 255)
Note over U,IAM: 阶段 1: 登录签发
U->>GW: POST /auth/login {username, password}
GW->>IAM: gRPC Login(username, password)
IAM->>IAM: 校验密码 + 查询权限
IAM->>IAM: 生成 JWTRS256 私钥签发)
IAM-->>GW: {accessToken, refreshToken, userInfo}
GW-->>U: 200 {accessToken, refreshToken}
end
rect rgb(240, 255, 240)
Note over U,SVC: 阶段 2: 请求鉴权
U->>GW: GET /api/classes + Authorization: Bearer <token>
GW->>GW: RS256 公钥校验签名
GW->>GW: 校验 exp/iss/aud
GW->>GW: 提取 userId/role/dataScope
GW->>SVC: gRPC 请求 + 透传 userId/role/dataScope metadata
SVC->>SVC: 权限校验requirePermission
SVC-->>GW: 响应数据
GW-->>U: 200 响应
end
```
### 5.2 三层角色模型
| 层级 | 来源 | 示例 | 优先级 |
|------|------|------|--------|
| 系统角色 | 系统预设 | admin、teacher、student、parent | 最高 |
| 组织角色 | 学校/班级分配 | 年级组长、班主任、学科组长 | 中 |
| 临时角色 | 临时授权 | 代课教师、临时代理 | 最低 |
**规则**:权限取三层角色权限的并集,拒绝权限取交集(任一层拒绝则拒绝)。
### 5.3 DataScope 6 级数据范围
| 级别 | 名称 | 数据范围 | 典型角色 |
|------|------|----------|----------|
| L0 | SELF | 仅本人数据 | 学生、家长 |
| L1 | CLASS | 本班数据 | 班主任、学生 |
| L2 | GRADE | 本年级数据 | 年级组长 |
| L3 | SCHOOL | 本校数据 | 校管理员 |
| L4 | DISTRICT | 本区数据 | 区教研员 |
| L5 | ALL | 全部数据 | 系统管理员 |
**实现**:业务服务在 Repository 层根据 dataScope 级别动态注入 WHERE 条件。
---
## 6. 数据访问与缓存
### 6.1 CQRS 读写分离
```mermaid
graph LR
subgraph Write["写路径"]
Cmd[Command 命令] --> App[Application Service]
App --> Domain[Domain 领域模型]
Domain --> Repo[Repository 写模型]
Repo -->[(MySQL 主库)]
App --> Outbox[(Outbox 表<br/>同事务)]
end
subgraph Sync["同步链路"]
Outbox --> Relay[Relay Worker]
Relay --> Kafka[(Kafka)]
Kafka --> Proj[Projection]
Proj -->[(ClickHouse 宽表)]
Proj -->[(Redis 缓存)]
Proj -->[(ES 索引)]
end
subgraph Read["读路径"]
Query[Query 查询] --> ReadModel[Read Model]
ReadModel -->[(ClickHouse 宽表)]
ReadModel -->[(Redis 缓存)]
ReadModel -->[(ES 索引)]
end
```
### 6.2 BFF 混合读策略
```mermaid
flowchart TD
Q[BFF 收到查询请求] --> C1{Redis 命中?}
C1 -- 是 --> R1[返回缓存]
C1 -- 否 --> C2{需要聚合多服务?}
C2 -- 否 --> C3[直接 gRPC 调用单一服务]
C3 --> C4[写入 Redis]
C4 --> R2[返回]
C2 -- 是 --> C5[并行 gRPC 调用多服务]
C5 --> C6[内存聚合裁剪]
C6 --> C7[写入 Redis 5-30s 短缓存]
C7 --> R3[返回聚合结果]
```
### 6.3 缓存策略矩阵
| 数据类型 | 存储 | TTL | 失效策略 |
|----------|------|-----|----------|
| 用户会话 | Redis | 30 分钟 | 滑动过期 |
| 权限列表 | Redis | 5 分钟 | 事件驱动失效 |
| 班级/年级列表 | Redis | 5 分钟 | 事件驱动失效 |
| 教学资源详情 | Redis | 30 秒 | 短 TTL |
| BFF 聚合结果 | Redis | 5-30 秒 | 短 TTL |
| 学情宽表 | ClickHouse | 实时 | CDC 同步 |
| 题库检索 | ES | 实时 | CDC 同步 |
---
## 7. 事件驱动架构
### 7.1 Outbox + Kafka + CDC 全链路
```mermaid
graph LR
subgraph Service["业务服务"]
Cmd[Command 处理]
Domain[Domain 聚合]
Repo[Repository]
Outbox[(Outbox 表)]
end
subgraph MySQL[("MySQL 主库")]
BizTable[(业务表)]
OutboxTable[(outbox 表)]
end
subgraph Relay["Relay Worker"]
Poll[轮询 outbox<br/>每 100ms]
Publish[发布到 Kafka]
Mark[标记 processed]
end
subgraph Bus["事件总线"]
Kafka[(Kafka topic)]
end
subgraph Consumers["消费者"]
Proj[Projection<br/>更新读模型]
OtherSvc[其他服务<br/>业务订阅]
end
Cmd --> Domain
Domain --> Repo
Repo --> BizTable
Repo --> OutboxTable
OutboxTable --> Poll
Poll --> Publish
Publish --> Kafka
Kafka --> Proj
Kafka --> OtherSvc
Proj -->[(ClickHouse/Redis/ES)]
```
### 7.2 事件 Topic 分类
| Topic 模式 | 示例 | 生产者 | 消费者 |
|-----------|------|--------|--------|
| `edu.identity.user.created` | 用户创建 | IAM | CoreEdu、Msg |
| `edu.identity.user.updated` | 用户更新 | IAM | CoreEdu、Msg |
| `edu.org.class.created` | 班级创建 | CoreEdu | DataAna |
| `edu.teaching.assignment.submitted` | 作业提交 | CoreEdu | DataAna、Msg |
| `edu.teaching.exam.published` | 考试发布 | CoreEdu | Msg |
| `edu.teaching.grade.recorded` | 成绩录入 | CoreEdu | DataAna、Msg |
| `edu.content.question.published` | 题目发布 | Content | AI、ES |
| `edu.insight.mastery.updated` | 掌握度更新 | DataAna | CoreEdu、Msg |
### 7.3 核心领域事件
| 事件 | 触发场景 | 消费者动作 |
|------|----------|-----------|
| UserRegistered | 新用户注册 | CoreEdu 初始化默认班级关联Msg 发送欢迎通知 |
| ExamPublished | 考试发布 | Msg 推送考试通知给学生DataAna 创建考试分析骨架 |
| HomeworkSubmitted | 学生提交作业 | DataAna 记录提交行为Msg 通知教师 |
| HomeworkGraded | 教师批改完成 | DataAna 更新掌握度Msg 通知学生 |
| MasteryUpdated | 掌握度计算完成 | CoreEdu 推荐个性化练习Msg 触发预警 |
| NotificationRequested | 通知请求 | Msg 投递通知到多渠道 |
---
## 8. 跨服务协作
### 8.1 同步 vs 异步决策
```mermaid
flowchart TD
Req[跨服务协作需求] --> C1{需要强一致性?}
C1 -- 是 --> C2{调用方需要立即结果?}
C2 -- 是 --> Sync[同步 gRPC 调用]
C2 -- 否 --> Saga[Saga 编排<br/>Temporal]
C1 -- 否 --> C3{需要事件最终一致?}
C3 -- 是 --> Async[异步 Kafka 事件]
C3 -- 否 --> C4{仅查询读取?}
C4 -- 是 --> Read[读模型冗余]
C4 -- 否 --> Sync
```
### 8.2 BFF 同步聚合
```mermaid
sequenceDiagram
participant U as 教师端
participant BFF as teacher-bff
participant IAM as iam
participant CoreEdu as core-edu
participant DataAna as data-ana
U->>BFF: 查询班级仪表盘
BFF->>BFF: 解析 token 获取 userId
par 并行查询
BFF->>IAM: gRPC GetUser(userId)
IAM-->>BFF: 用户信息
and
BFF->>CoreEdu: gRPC GetClassesByTeacher(userId)
CoreEdu-->>BFF: 班级列表
and
BFF->>DataAna: gRPC GetTeacherDashboardStats(userId)
DataAna-->>BFF: 统计数据
end
BFF->>BFF: 内存聚合裁剪
BFF-->>U: 仪表盘聚合数据
```
### 8.3 异步事件闭环
```mermaid
flowchart LR
A[教师录入成绩] --> B[CoreEdu 写入 MySQL + Outbox]
B --> C[Outbox Relay 发布事件]
C --> D[teaching.grade.recorded]
D --> E[DataAna 消费更新掌握度]
D --> F[Msg 消费通知学生]
E --> G[insight.mastery.updated]
G --> H[CoreEdu 消费推荐练习]
G --> I[Msg 消费掌握度预警]
```
### 8.4 Temporal 工作流编排
```mermaid
flowchart TD
Start[考试发布] --> A1[Activity: 创建考试实例]
A1 --> A2[Activity: 通知学生]
A2 --> A3[Activity: 等待作答窗口]
A3 --> A4[Activity: 收集提交]
A4 --> C1{是否全部提交?}
C1 -- 否 --> A5[Activity: 自动提交未答]
C1 -- 是 --> A6[Activity: 批改]
A5 --> A6
A6 --> A7[Activity: 发布成绩]
A7 --> A8[Activity: 生成分析]
A8 --> End[工作流完成]
```
---
## 9. 核心业务流程
### 9.1 考试生命周期
```mermaid
sequenceDiagram
participant T as 教师
participant BFF as teacher-bff
participant Core as core-edu
participant Msg as msg
participant DA as data-ana
participant S as 学生
rect rgb(240, 248, 255)
Note over T,Core: 阶段 1: 创建发布
T->>BFF: 创建考试
BFF->>Core: gRPC CreateExam
Core->>Core: 写入 MySQL + Outbox
Core-->>BFF: examId
BFF-->>T: 创建成功
Core->>Msg: ExamPublished 事件
Msg->>S: 推送考试通知
end
rect rgb(240, 255, 240)
Note over S,Core: 阶段 2: 作答提交
S->>BFF: 提交答卷
BFF->>Core: gRPC SubmitExam
Core->>Core: 写入答卷 + Outbox
Core-->>BFF: 提交成功
Core->>DA: ExamSubmitted 事件
DA->>DA: 记录提交行为
end
rect rgb(255, 240, 245)
Note over T,DA: 阶段 3: 批改出分
T->>BFF: 批改答卷
BFF->>Core: gRPC GradeExam
Core->>Core: 写入成绩 + Outbox
Core-->>BFF: 批改完成
Core->>DA: GradeRecorded 事件
DA->>DA: 更新掌握度
Core->>Msg: GradeRecorded 事件
Msg->>S: 推送成绩通知
end
```
### 9.2 高并发提交
```mermaid
flowchart TD
S[学生提交] --> GW[API Gateway]
GW --> GW1{限流检查}
GW1 -- 通过 --> BFF[BFF]
GW1 -- 拒绝 --> R1[429 限流响应]
BFF --> Core[CoreEdu]
Core --> C1{Redis 分布式锁}
C1 -- 获取锁 --> C2[写入答卷]
C2 --> C3[Outbox 事件]
C3 --> C4[释放锁]
C4 --> R2[成功]
C1 -- 锁竞争 --> C5[排队等待 500ms]
C5 --> C1
C5 --> C6{超时?}
C6 -- 是 --> R3[排队中,请稍后]
```
### 9.3 AI 辅助出题
```mermaid
sequenceDiagram
participant T as 教师
participant BFF as teacher-bff
participant AI as ai 网关
participant Content as content
participant DA as data-ana
T->>BFF: 请求 AI 出题
BFF->>AI: gRPC GenerateQuestions
AI->>Content: gRPC 查询知识点
Content-->>AI: 知识点列表
AI->>DA: gRPC 查询班级学情
DA-->>AI: 学情数据
AI->>AI: LLM 调用生成题目
AI-->>BFF: 生成的题目列表
BFF-->>T: 返回题目供教师审核
T->>BFF: 确认入库
BFF->>Content: gRPC CreateQuestions
Content-->>BFF: 入库成功
```
---
## 10. 可观测性
### 10.1 三支柱可观测性
```mermaid
graph TB
subgraph App["应用层"]
SVC[业务服务]
GW[网关]
BFF[BFF]
end
subgraph Collect["采集层"]
OTEL[OpenTelemetry SDK]
PROM[Prometheus Exporter]
end
subgraph Storage["存储层"]
LOKI[(Loki<br/>日志)]
TEMPO[(Tempo<br/>Trace)]
PROMDB[(Prometheus<br/>指标)]
end
subgraph Vis["可视化层"]
GRAFANA[Grafana<br/>统一面板]
ALERT[AlertManager<br/>告警]
end
SVC --> OTEL
GW --> OTEL
BFF --> OTEL
OTEL --> LOKI
OTEL --> TEMPO
SVC --> PROM
GW --> PROM
PROM --> PROMDB
LOKI --> GRAFANA
TEMPO --> GRAFANA
PROMDB --> GRAFANA
PROMDB --> ALERT
```
### 10.2 Trace 上下文传播
```mermaid
flowchart LR
A[客户端请求] --> B[API Gateway<br/>生成 traceId]
B --> C[BFF<br/>继承 traceId]
C --> D[业务服务<br/>继承 traceId]
D --> E[Kafka 事件<br/>traceId 写入 header]
E --> F[消费者服务<br/>继承 traceId]
F --> G[数据存储<br/>span 记录]
```
**规则**
- 所有跨服务调用必须透传 W3C Trace Context
- Kafka 事件必须将 traceId 写入消息 header
- 日志必须包含 traceId 用于关联查询
- 关键业务操作必须创建 span创建考试、提交作业、批改等
---
## 11. 契约与 API 架构
### 11.1 Protobuf 契约体系
```mermaid
graph TB
subgraph Proto["protobuf 契约仓库"]
Identity[identity/v1<br/>user/role/permission]
Org[org/v1<br/>class/subject/enrollment]
Teaching[teaching/v1<br/>course/assignment/exam]
Content[content/v1<br/>textbook/question]
Comm[comm/v1<br/>message/notification]
Insight[insight/v1<br/>report/mastery]
end
subgraph Gen["代码生成"]
Buf[buf generate]
TS[TS 生成代码<br/>@bufbuild/protobuf]
Go[Go 生成代码<br/>protobuf-go]
Py[Python 生成代码<br/>betterproto]
end
subgraph Services["消费服务"]
SvcTS[NestJS 服务]
SvcGo[Go 网关]
SvcPy[Python 服务]
end
Identity --> Buf
Org --> Buf
Teaching --> Buf
Content --> Buf
Comm --> Buf
Insight --> Buf
Buf --> TS
Buf --> Go
Buf --> Py
TS --> SvcTS
Go --> SvcGo
Py --> SvcPy
```
### 11.2 契约规则
| 规则 | 说明 |
|------|------|
| 包命名 | `edu.[context].[aggregate].v[version]` |
| 版本化 | 破坏性变更必须升版本v1 → v2 |
| 字段编号 | 禁止复用已删除字段编号,使用 reserved |
| 消息命名 | PascalCase |
| 字段命名 | snake_case |
| 注释 | 每个 message 和字段必须注释 |
| CI 强制 | buf lint + buf breaking 必须通过 |
### 11.3 BFF 聚合模式
```mermaid
graph LR
subgraph Client["客户端"]
Q[GraphQL 查询]
end
subgraph BFF["BFF 层"]
Resolver[GraphQL Resolver]
DataLoader[DataLoader 批量去重]
Cache[Redis 短缓存]
end
subgraph Services["业务服务"]
S1[服务 A]
S2[服务 B]
S3[服务 C]
end
Q --> Resolver
Resolver --> Cache
Cache --> DataLoader
DataLoader --> S1
DataLoader --> S2
DataLoader --> S3
```
---
## 12. 架构约束
### 12.1 服务独立性约束
| 约束 | 说明 |
|------|------|
| 数据库独占 | 每个微服务独占自身数据库,禁止跨库联表 |
| 契约先行 | 所有跨服务通信必须先定义 protobuf 契约 |
| Outbox 强制 | 所有领域事件必须通过 Outbox 模式发布 |
| 幂等消费 | 所有事件消费者必须实现幂等性 |
| 单一职责 | 每个服务只负责一个限界上下文 |
| 无状态服务 | 业务服务不持有会话状态Redis 承载) |
### 12.2 通信约束
| 场景 | 允许 | 禁止 |
|------|------|------|
| 客户端 → Gateway | REST + WebSocket | 直连业务服务 |
| Gateway → BFF | gRPC | REST |
| BFF → 业务服务 | gRPC | 直接访问 DB |
| 业务服务之间(同步) | gRPC + 必要时 | REST、直接 DB |
| 业务服务之间(异步) | Kafka 事件 | 直接 producer 调用 |
| 事件发布 | Outbox 模式 | 直接 Kafka producer |
### 12.3 数据一致性约束
| 场景 | 一致性级别 | 实现 |
|------|-----------|------|
| 聚合内 | 强一致 | 单事务 |
| 聚合间 | 最终一致 | Kafka 事件 |
| 服务间 | 最终一致 | Kafka 事件 / Saga |
| 读模型 | 最终一致 | Projection 异步更新 |
| 缓存 | 最终一致 | 事件驱动失效 + 短 TTL |
---
## 13. ADR 记录
| 编号 | 决策 | 原因 | 状态 |
|------|------|------|------|
| ADR-001 | 采用 DDD 限界上下文划分服务 | 业务边界清晰,独立演进 | 已采纳 |
| ADR-002 | 采用 NestJS 作为业务服务框架 | TS 生态成熟,装饰器 + DI 适合 DDD | 已采纳 |
| ADR-003 | 采用 Go 作为网关语言 | 高并发、低内存、适合网关场景 | 已采纳 |
| ADR-004 | 采用 Python 作为分析/AI 语言 | 数据科学/AI 生态丰富 | 已采纳 |
| ADR-005 | 采用 CQRS 读写分离 | 读多写少,读模型可独立优化 | 已采纳 |
| ADR-006 | 采用 Outbox 模式发布事件 | 保证事务与事件最终一致 | 已采纳 |
| ADR-007 | 采用 Kafka 作为事件总线 | 高吞吐、持久化、成熟生态 | 已采纳 |
| ADR-008 | 采用 Debezium CDC | 解耦 Outbox Relay减少业务侵入 | 已采纳 |
| ADR-009 | 采用 protobuf + buf 契约先行 | 多语言契约统一、版本化、CI 强制 | 已采纳 |
| ADR-010 | 采用 JWT RS256 非对称签名 | 网关公钥校验无需共享私钥 | 已采纳 |
| ADR-011 | 采用 DataScope 6 级数据范围 | 满足 K12 多层级数据隔离 | 已采纳 |
| ADR-012 | 采用 Module Federation 微前端 | 独立部署、技术栈无关、渐进迁移 | 已采纳 |
| ADR-013 | 采用 Temporal 工作流编排 | 长流程编排、可观测、可回滚 | 已采纳 |
| ADR-014 | 采用 ClickHouse 读模型宽表 | 分析查询亚秒级响应 | 已采纳 |
---
## 14. 附录6 阶段路线图
### 14.1 阶段总览
```mermaid
graph LR
P1[P1 地基<br/>M1-M3] --> P2[P2 身份<br/>M4-M6]
P2 --> P3[P3 核心教学<br/>M7-M10]
P3 --> P4[P4 内容分析<br/>M11-M13]
P4 --> P5[P5 沟通AI<br/>M14-M16]
P5 --> P6[P6 硬化<br/>M17-M18]
```
### 14.2 服务与阶段映射
| 阶段 | 周期 | 交付服务 | 退出标准 |
|------|------|----------|----------|
| P1 地基 | M1-M3 | api-gateway、classes黄金模板、shared-proto | classes 域 CRUD 端到端跑通 |
| P2 身份 | M4-M6 | iam、teacher-bff、teacher-portal 骨架 | 教师可登录并看到空白 Dashboard |
| P3 核心教学 | M7-M10 | core-edu合并 classes、student-bff、student-portal | 考试→作答→批改→成绩全链路 |
| P4 内容分析 | M11-M13 | content、data-ana、parent-bff、parent-portal | 知识图谱查询 + 学情宽表 5s |
| P5 沟通AI | M14-M16 | msg、push-gateway、ai | 全校广播 + AI 辅助出题 |
| P6 硬化 | M17-M18 | admin-portal、Service Mesh | 99.9% 可用性 + 独立扩缩容 |
> 详细规划见 [路线图目录](./roadmap/README.md)