Files
ljwx-health/docs/02-architecture/phase1-profile-scheduling-architecture.md
T
brunoandClaude Sonnet 4.5 332c032ef9
CI/CD Pipeline / test-admin (push) Waiting to run
CI/CD Pipeline / test-bigscreen (push) Waiting to run
CI/CD Pipeline / build-push (ljwx-admin) (push) Blocked by required conditions
CI/CD Pipeline / build-push (ljwx-bigscreen) (push) Blocked by required conditions
CI/CD Pipeline / build-push (ljwx-boot) (push) Blocked by required conditions
CI/CD Pipeline / update-deploy (push) Blocked by required conditions
CI/CD Pipeline / build-pr (ljwx-admin) (push) Blocked by required conditions
CI/CD Pipeline / build-pr (ljwx-bigscreen) (push) Blocked by required conditions
CI/CD Pipeline / build-pr (ljwx-boot) (push) Blocked by required conditions
CI/CD Pipeline / security-scan (push) Has been cancelled
CI/CD Pipeline / test-build-boot (push) Has been cancelled
feat: 健康监测系统架构升级 - Profile层、风险评估、质量告警
新增核心功能:
- 健康画像生成系统(用户/部门/组织基线)
- 风险评估框架(心血管/运动/呼吸/睡眠)
- 行为画像分析(饮食/运动/睡眠/健康关注度)
- 数据质量评分和告警

数据库迁移:
- V1.3.0~V1.7.0 健康监测表结构

前端增强:
- ljwx-admin: BigScreen集成、健康搜索优化
- ljwx-bigscreen: SSO认证、登录界面

文档体系:
- 强制文档管理规范(kebab-case、分类、Git hooks)
- 架构文档、开发指南、运维手册
- 工程蓝图 v2.1

CI/CD:
- 文档验证工作流
- 生产就绪性检查脚本
- 完整测试覆盖

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-20 21:06:00 +08:00

18 KiB
Raw Blame History

Phase 1 画像调度架构设计

任务 ID: T1.2.1 设计人: Backend Dev 1 设计日期: 2026-01-20 评审状态: 待评审


1. 架构概览

1.1 设计目标

核心问题: 当前系统中,画像生成与评分计算耦合在一起,导致:

  • 评分计算依赖实时画像生成,性能差
  • 画像数据无法复用,重复计算
  • 调度策略不灵活

解决方案: 实现画像层独立调度,解耦画像生成与评分计算。

1.2 架构原则

  1. 单一职责: 画像生成服务只负责生成画像,不参与评分计算
  2. 数据持久化: 画像数据持久化到数据库,供评分层使用
  3. 独立调度: 画像生成和评分计算独立调度,互不影响
  4. 增量更新: 支持增量更新画像数据,减少计算量

2. 系统架构

2.1 层次架构

┌─────────────────────────────────────────────────────────────┐
│                    评分层 (Scoring Layer)                    │
│  HealthScoreService - 依赖画像数据计算健康评分              │
└─────────────────────────────────────────────────────────────┘
                            ▲
                            │ 读取画像数据
                            │
┌─────────────────────────────────────────────────────────────┐
│                    画像层 (Profile Layer) ⭐ 新增            │
│  HealthProfileService - 从状态数据生成健康画像               │
│  HealthProfileScheduledTask - 定时调度画像生成              │
└─────────────────────────────────────────────────────────────┘
                            ▲
                            │ 读取状态数据
                            │
┌─────────────────────────────────────────────────────────────┐
│                    状态层 (State Layer)                      │
│  原始健康数据: heart_rate, blood_oxygen, temperature...     │
└─────────────────────────────────────────────────────────────┘

2.2 核心组件

2.2.1 HealthProfileService

职责: 从状态数据生成用户健康画像

核心方法:

// 为单个用户生成画像
HealthProfile generateUserProfile(Long userId, LocalDate date);

// 批量生成画像(性能优化)
List<HealthProfile> batchGenerateProfiles(List<Long> userIds, LocalDate date);

// 增量更新画像(仅更新变化的指标)
HealthProfile updateProfileIncremental(Long userId, LocalDate date);

2.2.2 HealthProfileScheduledTask

职责: 定时调度画像生成任务

调度策略:

  • 触发时间: 每日 01:30(避开业务高峰)
  • 执行范围: 所有活跃用户(过去 7 天有数据的用户)
  • 批处理: 每批 200 用户(避免 OOM)
  • 错误处理: 失败任务记录日志,不影响其他用户

伪代码:

@Scheduled(cron = "0 30 1 * * ?")
public void generateDailyProfiles() {
    LocalDate yesterday = LocalDate.now().minusDays(1);

    // 1. 获取活跃用户列表
    List<Long> activeUserIds = getActiveUsers(yesterday);

    // 2. 分批处理
    Lists.partition(activeUserIds, 200).forEach(batch -> {
        try {
            healthProfileService.batchGenerateProfiles(batch, yesterday);
        } catch (Exception e) {
            log.error("Failed to generate profiles for batch", e);
        }
    });

    // 3. 更新调度任务状态
    updateTaskStatus("profile_generation", yesterday, "COMPLETED");
}

2.2.3 HealthProfileRepository

职责: 画像数据持久化

核心方法:

// 保存画像
void save(HealthProfile profile);

// 批量保存
void batchSave(List<HealthProfile> profiles);

// 查询画像
HealthProfile findByUserIdAndDate(Long userId, LocalDate date);

// 查询最新画像
HealthProfile findLatestByUserId(Long userId);

3. 数据模型

3.1 画像数据表结构

表名: t_user_health_profile

字段名 类型 说明 索引
id BIGINT 主键(自增) PK
user_id BIGINT 用户 ID IDX
customer_id BIGINT 租户 ID IDX
profile_date DATE 画像日期 IDX
heart_rate_avg DECIMAL(5,2) 平均心率 -
heart_rate_max DECIMAL(5,2) 最大心率 -
heart_rate_min DECIMAL(5,2) 最小心率 -
heart_rate_variability DECIMAL(5,2) 心率变异性 (HRV) -
blood_oxygen_avg DECIMAL(5,2) 平均血氧 -
blood_oxygen_min DECIMAL(5,2) 最低血氧 -
temperature_avg DECIMAL(5,2) 平均体温 -
pressure_high_avg DECIMAL(5,2) 平均收缩压 -
pressure_low_avg DECIMAL(5,2) 平均舒张压 -
stress_level_avg DECIMAL(5,2) 平均压力水平 -
sleep_duration INT 睡眠时长(分钟) -
sleep_deep_duration INT 深睡时长(分钟) -
sleep_quality_score DECIMAL(5,2) 睡眠质量评分 -
step_count INT 步数 -
calorie_burned INT 消耗卡路里 -
distance_meters INT 运动距离(米) -
data_completeness DECIMAL(5,2) 数据完整度(0-100) -
created_at TIMESTAMP 创建时间 -
updated_at TIMESTAMP 更新时间 -

索引设计:

-- 唯一索引: 用户 + 日期(防止重复)
CREATE UNIQUE INDEX idx_user_date
ON t_user_health_profile(user_id, profile_date);

-- 组合索引: 租户 + 日期(多租户查询优化)
CREATE INDEX idx_customer_date
ON t_user_health_profile(customer_id, profile_date);

-- 索引: 用户 ID(查询最新画像)
CREATE INDEX idx_user_id
ON t_user_health_profile(user_id);

3.2 画像生成任务状态表

表名: t_profile_task_status

字段名 类型 说明 索引
id BIGINT 主键(自增) PK
task_name VARCHAR(100) 任务名称 IDX
task_date DATE 任务日期 IDX
status VARCHAR(20) 任务状态 (PENDING/RUNNING/COMPLETED/FAILED) -
total_users INT 总用户数 -
processed_users INT 已处理用户数 -
failed_users INT 失败用户数 -
start_time TIMESTAMP 开始时间 -
end_time TIMESTAMP 结束时间 -
error_message TEXT 错误信息 -
created_at TIMESTAMP 创建时间 -
updated_at TIMESTAMP 更新时间 -

4. 时序图

4.1 画像生成流程

┌─────────┐         ┌────────────────┐         ┌─────────────────┐         ┌──────────┐
│ Quartz  │         │ScheduledTask   │         │ProfileService   │         │Repository│
└────┬────┘         └───────┬────────┘         └────────┬────────┘         └────┬─────┘
     │                      │                           │                       │
     │  01:30 触发          │                           │                       │
     ├─────────────────────>│                           │                       │
     │                      │                           │                       │
     │                      │ 1. 获取活跃用户列表        │                       │
     │                      ├──────────────────────────>│                       │
     │                      │                           │  SELECT user_id       │
     │                      │                           ├──────────────────────>│
     │                      │                           │<──────────────────────┤
     │                      │<──────────────────────────┤  List<userId>         │
     │                      │                           │                       │
     │                      │ 2. 分批处理(200/批)     │                       │
     │                      │  for each batch:          │                       │
     │                      │                           │                       │
     │                      │ 3. 批量生成画像            │                       │
     │                      ├──────────────────────────>│                       │
     │                      │                           │                       │
     │                      │                           │ 4. 查询状态数据        │
     │                      │                           │  (heart_rate,         │
     │                      │                           │   blood_oxygen...)    │
     │                      │                           ├──────────────────────>│
     │                      │                           │<──────────────────────┤
     │                      │                           │                       │
     │                      │                           │ 5. 计算画像指标        │
     │                      │                           │  (avg, max, min...)   │
     │                      │                           │                       │
     │                      │                           │ 6. 批量保存画像        │
     │                      │                           ├──────────────────────>│
     │                      │                           │<──────────────────────┤
     │                      │<──────────────────────────┤                       │
     │                      │                           │                       │
     │                      │ 7. 更新任务状态            │                       │
     │                      ├──────────────────────────────────────────────────>│
     │                      │<──────────────────────────────────────────────────┤
     │                      │                           │                       │

4.2 评分层调用画像数据

┌────────────┐         ┌──────────────┐         ┌─────────────┐
│ScoreService│         │ProfileService│         │Repository   │
└─────┬──────┘         └──────┬───────┘         └──────┬──────┘
      │                       │                        │
      │ 1. 计算用户健康评分     │                        │
      │                       │                        │
      │ 2. 获取用户画像         │                        │
      ├──────────────────────>│                        │
      │                       │  SELECT * FROM profile │
      │                       ├───────────────────────>│
      │                       │<───────────────────────┤
      │<──────────────────────┤  HealthProfile         │
      │                       │                        │
      │ 3. 基于画像计算评分     │                        │
      │  (heart_rate_score,   │                        │
      │   blood_oxygen_score...) │                     │
      │                       │                        │
      │ 4. 返回评分结果         │                        │

5. API 接口设计

5.1 画像生成接口

POST /api/health/profile/generate

描述: 手动触发画像生成(用于测试或补数)

请求参数:

{
  "userIds": [1001, 1002, 1003],
  "startDate": "2026-01-01",
  "endDate": "2026-01-07"
}

响应:

{
  "code": 200,
  "message": "成功",
  "data": {
    "totalUsers": 3,
    "processedUsers": 3,
    "failedUsers": 0,
    "duration": 1234
  }
}

5.2 查询画像接口

GET /api/health/profile/{userId}

描述: 查询用户健康画像

请求参数:

  • userId (路径参数): 用户 ID
  • date (查询参数, 可选): 指定日期,默认最新

响应:

{
  "code": 200,
  "message": "成功",
  "data": {
    "userId": 1001,
    "profileDate": "2026-01-19",
    "heartRate": {
      "avg": 72.5,
      "max": 120,
      "min": 55,
      "variability": 45.2
    },
    "bloodOxygen": {
      "avg": 97.8,
      "min": 95
    },
    "temperature": {
      "avg": 36.5
    },
    "sleep": {
      "duration": 420,
      "deepDuration": 120,
      "qualityScore": 85.5
    },
    "activity": {
      "stepCount": 8500,
      "calorieBurned": 2100,
      "distanceMeters": 6200
    },
    "dataCompleteness": 92.5
  }
}

5.3 任务状态查询接口

GET /api/health/profile/task/status

描述: 查询画像生成任务状态

请求参数:

  • taskName (查询参数): 任务名称,默认 "profile_generation"
  • date (查询参数, 可选): 任务日期,默认今天

响应:

{
  "code": 200,
  "message": "成功",
  "data": {
    "taskName": "profile_generation",
    "taskDate": "2026-01-20",
    "status": "COMPLETED",
    "totalUsers": 1000,
    "processedUsers": 1000,
    "failedUsers": 0,
    "startTime": "2026-01-20T01:30:00",
    "endTime": "2026-01-20T01:35:23",
    "duration": 323
  }
}

6. 性能优化

6.1 批处理策略

  • 批量大小: 200 用户/批
  • 并发控制: 使用 @Async + 线程池(核心线程 4,最大线程 8)
  • 数据库批量插入: 使用 MyBatis-Plus saveBatch()

6.2 查询优化

  • 索引优化: 为 user_id + profile_date 创建唯一索引
  • 连接池: Druid 连接池(基础 30,最大 80)
  • 缓存: 最新画像数据缓存 5 分钟(Redis)

6.3 计算优化

  • 增量计算: 如果当天已有画像,仅更新变化的指标
  • 数据预聚合: 状态数据按天预聚合,减少计算量

7. 监控与告警

7.1 性能指标

指标 目标 监控方式
画像生成时长 1000 用户 <5 分钟 Prometheus + Grafana
任务成功率 >99% 任务状态表统计
数据完整度 平均 >90% 画像数据 data_completeness 字段
数据库查询 P99 <100ms Druid 监控

7.2 告警规则

  • 任务失败: 任务状态 = FAILED,立即告警
  • 任务超时: 任务执行时间 >10 分钟,告警
  • 数据完整度低: 平均完整度 <80%,告警

8. 风险评估

风险 概率 影响 应对措施
大批量用户导致 OOM 中 高 分批处理 + JVM 内存监控
数据库锁表 低 高 使用批量插入 + 避免高峰期执行
调度任务延期 中 中 监控任务执行时长,调整调度时间
画像数据质量差 中 中 数据完整度评分 + 异常值过滤

9. 测试计划

9.1 单元测试

  • HealthProfileService:

    • 测试画像生成逻辑(正常数据)
    • 测试画像生成逻辑(缺失数据)
    • 测试批量生成性能
  • HealthProfileScheduledTask:

    • 测试调度任务触发
    • 测试错误处理

9.2 集成测试

  • 端到端测试: 状态数据 → 画像生成 → 评分计算
  • 性能测试: 1000 用户画像生成 <5 分钟

9.3 验收标准

  • ✅ 单元测试覆盖率 >80%
  • ✅ 画像生成成功率 >99%
  • ✅ 性能达标: 1000 用户 <5 分钟
  • ✅ 数据完整度 >90%
  • ✅ Code Review 通过

10. 实施计划

任务 负责人 工期 依赖
T1.2.1: 架构设计 Backend Dev 1 2天 -
T1.2.2: 实现画像生成服务 Backend Dev 1 3天 T1.2.1
T1.2.3: 实现调度任务 Backend Dev 1 2天 T1.2.2
T1.2.4: 修改评分任务依赖 Backend Dev 1 2天 T1.2.3
T1.2.5: 集成测试 QA 2天 T1.2.4
T1.2.6: Code Review Team 1天 T1.2.5

11. 附录

11.1 参考文档

11.2 变更记录

日期 版本 变更内容 变更人
2026-01-20 v1.0 初始版本 Backend Dev 1

评审签字:

  • Tech Lead: _____________ 日期: _______
  • Backend Dev 2: _____________ 日期: _______
  • DevOps: _____________ 日期: _______