cosmo/ARCHITECTURE_PLAN.md

10 KiB
Raw Blame History

Cosmo 平台架构升级规划

一、现状分析

当前架构

  • 前端数据静态JSON文件galaxies, constellations, stars, probe-models
  • 后端数据NASA Horizons API实时查询 + 简单内存缓存
  • 资源存储纹理和3D模型在前端 public/ 目录
  • 缓存策略:内存缓存(进程级别,重启失效)

痛点

  1. 数据管理分散前端JSON + 后端代码硬编码
  2. 缓存不持久服务重启后需要重新查询NASA API
  3. 资源管理混乱:纹理、模型路径分散在前后端
  4. 扩展困难:添加新天体类型需要修改多处代码
  5. 无历史数据:无法查询天体历史轨迹
  6. 性能问题NASA API查询慢每个天体1-2秒

未来需求

  • 支持更多天体类型(彗星、小行星、系外行星等)
  • 用户自定义天体
  • 历史轨迹查询和时间旅行
  • 性能优化减少NASA API调用
  • 统一的资源管理
  • 可能的多用户支持

二、技术方案

2.1 数据库方案

推荐PostgreSQL + SQLAlchemy

选择理由

  1. 功能强大支持复杂查询、全文搜索、JSON字段
  2. PostGIS扩展:专门处理空间数据(未来可能需要)
  3. 时间序列优化通过TimescaleDB扩展支持高效时间序列查询
  4. 成熟生态Python生态支持好asyncpg, SQLAlchemy 2.0异步支持)
  5. 扩展性:支持大规模数据和并发

备选方案

  • SQLite:适合单机部署,但功能和性能有限
  • MongoDB文档型数据库但对关系查询支持不如PostgreSQL

数据库设计

-- 天体类型枚举
CREATE TYPE celestial_type AS ENUM ('star', 'planet', 'moon', 'probe', 'comet', 'asteroid', 'galaxy', 'constellation');

-- 天体基本信息表
CREATE TABLE celestial_bodies (
    id VARCHAR(50) PRIMARY KEY,  -- JPL Horizons ID 或自定义ID
    name VARCHAR(200) NOT NULL,
    name_zh VARCHAR(200),
    type celestial_type NOT NULL,
    description TEXT,
    metadata JSONB,  -- 灵活存储各种元数据launch_date, status等
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

-- 位置历史表(时间序列数据)
CREATE TABLE positions (
    id BIGSERIAL PRIMARY KEY,
    body_id VARCHAR(50) REFERENCES celestial_bodies(id),
    time TIMESTAMP NOT NULL,
    x DOUBLE PRECISION NOT NULL,  -- AU
    y DOUBLE PRECISION NOT NULL,
    z DOUBLE PRECISION NOT NULL,
    source VARCHAR(50),  -- 'nasa_horizons', 'calculated', 'user_defined'
    created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_positions_body_time ON positions(body_id, time DESC);

-- 资源管理表(纹理、模型等)
CREATE TABLE resources (
    id SERIAL PRIMARY KEY,
    body_id VARCHAR(50) REFERENCES celestial_bodies(id),
    type VARCHAR(50) NOT NULL,  -- 'texture', 'model', 'icon'
    file_path VARCHAR(500) NOT NULL,  -- 相对于upload目录的路径
    file_size INTEGER,
    mime_type VARCHAR(100),
    metadata JSONB,  -- 分辨率、格式等信息
    created_at TIMESTAMP DEFAULT NOW()
);

-- 静态数据表(星座、星系等不变数据)
CREATE TABLE static_data (
    id SERIAL PRIMARY KEY,
    category VARCHAR(50) NOT NULL,  -- 'constellation', 'galaxy', 'star'
    name VARCHAR(200) NOT NULL,
    name_zh VARCHAR(200),
    data JSONB NOT NULL,  -- 完整的静态数据
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

-- NASA API缓存表持久化缓存
CREATE TABLE nasa_cache (
    cache_key VARCHAR(500) PRIMARY KEY,
    body_id VARCHAR(50),
    start_time TIMESTAMP,
    end_time TIMESTAMP,
    step VARCHAR(10),
    data JSONB NOT NULL,
    expires_at TIMESTAMP NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_nasa_cache_expires ON nasa_cache(expires_at);

2.2 缓存策略

三层缓存架构

请求 → L1 (内存) → L2 (Redis) → L3 (数据库) → L4 (NASA API)

L1: 进程内存缓存(已有)

  • TTL: 10分钟
  • 用途:当前时间的天体位置(最热数据)
  • 实现Python dict + TTL已有cache.py

L2: Redis缓存(新增)

  • TTL:
    • 当前时间数据1小时
    • 历史数据7天
    • 静态数据:永久(手动失效)
  • 用途:
    • NASA API响应缓存
    • 会话数据
    • 预计算结果
  • 好处:
    • 进程间共享
    • 持久化(重启不丢失)
    • 分布式支持

L3: PostgreSQL数据库

  • 持久化存储
  • 历史数据查询
  • 复杂查询和统计

L4: NASA Horizons API

  • 最终数据源
  • 只在缓存未命中时调用

缓存键设计

# L1/L2 缓存键格式
"positions:{body_id}:{start}:{end}:{step}"
"static:{category}:{name}"
"texture:{body_id}:{type}"

# 示例
"positions:-31:2025-11-27:2025-11-27:1d"
"static:constellation:orion"

2.3 文件存储方案

目录结构

cosmo/
├── backend/
│   ├── upload/              # 统一上传目录
│   │   ├── textures/
│   │   │   ├── planets/     # 行星纹理
│   │   │   ├── stars/       # 恒星纹理
│   │   │   └── probes/      # 探测器图标
│   │   ├── models/
│   │   │   ├── probes/      # 探测器3D模型
│   │   │   └── spacecraft/
│   │   └── data/            # 数据文件备份
│   └── app/
│       └── api/
│           └── static.py    # 静态文件服务API

文件访问

# 后端提供统一的静态文件API
GET /api/static/textures/planets/earth.jpg
GET /api/static/models/probes/voyager1.glb

# 数据库记录
{
  "body_id": "399",
  "type": "texture",
  "file_path": "textures/planets/2k_earth_daymap.jpg",
  "url": "/api/static/textures/planets/2k_earth_daymap.jpg"
}

2.4 数据迁移路径

阶段1数据库基础设施1-2天

  1. 安装PostgreSQL和Redis
  2. 设置SQLAlchemy ORM
  3. 创建数据库表结构
  4. 数据迁移脚本:
    • CELESTIAL_BODIES dict → celestial_bodies
    • 前端JSON文件 → static_data

阶段2缓存层升级1天

  1. 集成Redis客户端
  2. 实现三层缓存逻辑
  3. NASA API结果持久化到数据库

阶段3资源管理迁移1天

  1. 迁移纹理文件到 backend/upload/textures/
  2. 迁移3D模型到 backend/upload/models/
  3. 建立资源表记录
  4. 实现静态文件服务API

阶段4API重构1-2天

  1. 新增数据库查询API
  2. 前端调整为从后端API获取所有数据
  3. 移除前端静态JSON文件依赖

阶段5优化和测试1天

  1. 性能测试
  2. 缓存命中率监控
  3. 数据一致性验证

三、技术栈

后端新增依赖

Python包

# ORM和数据库
sqlalchemy>=2.0.0          # ORM框架支持async
asyncpg>=0.29.0            # PostgreSQL异步驱动
alembic>=1.12.0            # 数据库迁移工具

# Redis缓存
redis>=5.0.0               # Redis客户端
aioredis>=2.0.0            # 异步Redis可选redis 5.0+已内置async支持

# 文件处理
python-multipart>=0.0.6    # 文件上传支持
aiofiles>=23.0.0           # 异步文件操作
Pillow>=10.0.0             # 图片处理(缩略图等)

系统依赖

PostgreSQL 15+

# macOS
brew install postgresql@15
brew services start postgresql@15

# 创建数据库
createdb cosmo_db

Redis 7+

# macOS
brew install redis
brew services start redis

# 验证
redis-cli ping  # 应返回 PONG

前端调整

  • 移除静态JSON文件依赖
  • 所有数据通过API获取
  • 静态资源URL指向后端API

四、性能优化

预期改进

  1. NASA API调用减少90%:通过数据库+Redis缓存
  2. 首次加载加速:从缓存/数据库读取无需等待NASA API
  3. 支持历史查询:数据库存储历史位置数据
  4. 并发能力提升Redis支持分布式缓存

监控指标

  • 缓存命中率L1/L2/L3
  • NASA API调用次数
  • 数据库查询时间
  • API响应时间

五、成本分析

开发成本

  • 总工时约6-7天
  • 可分阶段实施,每阶段独立可用

运行成本

  • PostgreSQL~100MB内存小规模
  • Redis~50MB内存
  • 磁盘:~500MB-1GB数据+资源文件)

维护成本

  • 数据库备份:每日自动备份
  • 缓存清理:自动过期,无需人工干预
  • 资源管理:统一后端管理,更容易维护

六、风险和备选方案

风险

  1. PostgreSQL依赖:需要额外安装和维护
    • 备选先用SQLite后续迁移
  2. 数据迁移复杂度:现有数据分散
    • 缓解:编写完善的迁移脚本和回滚方案
  3. Redis单点故障Redis挂了影响性能
    • 缓解Redis只是缓存挂了仍可从数据库读取

回滚方案

  • 保留现有代码分支
  • 数据库和缓存作为可选功能
  • 降级到内存缓存 + NASA API直连

七、实施建议

推荐方案:完整实施

理由:

  1. 项目正处于扩展期,早期投入架构收益大
  2. PostgreSQL+Redis是成熟方案风险可控
  3. 支持未来功能扩展(用户系统、自定义天体等)
  4. 性能提升明显(缓存命中后响应 <50ms

简化方案(如果资源有限)

  1. 只用PostgreSQL不用Redis

    • 降级为两层:内存 → 数据库 → NASA API
    • 仍可实现持久化和历史查询
    • 性能略低但可接受
  2. 只用Redis不用PostgreSQL

    • 只做缓存,不做持久化
    • 适合小规模、不需要历史数据的场景
    • 不推荐(失去了数据管理能力)

八、下一步

确认方案后,我将:

  1. 准备安装脚本自动化安装PostgreSQL和Redis
  2. 生成数据库Schema完整的SQL DDL
  3. 编写迁移脚本:将现有数据导入数据库
  4. 实现缓存层:三层缓存逻辑
  5. 重构API:支持数据库查询
  6. 迁移静态资源:统一到后端管理

附录:配置示例

PostgreSQL连接配置

# .env
DATABASE_URL=postgresql+asyncpg://cosmo:password@localhost:5432/cosmo_db

Redis连接配置

# .env
REDIS_URL=redis://localhost:6379/0

数据库连接池配置

# app/database.py
engine = create_async_engine(
    DATABASE_URL,
    pool_size=20,
    max_overflow=10,
    pool_pre_ping=True,
)