fao/docs/架构设计.md
2026-04-23 19:24:46 +08:00

12 KiB
Raw Permalink Blame History

蔬菜价格指数平台 — 架构设计

版本1.2
范围多源价格采集、数据清洗、指数计算、MySQL 存储、接口服务、ECharts 可视化。
目标:轻量落地、成本可控、模块解耦、可迭代扩容。

语言与职责(已定稿)

  • Python仅负责采集层多源适配器、调度、反爬、raw/队列表落库),不承担管理后台、对外 API、治理批处理、指计算。
  • Java全栈后台Spring Boot 为主治理与标准化、指数字典与批算、REST API、鉴权/审计、管理端后端、数据库迁移(Flyway / Liquibase 等,推荐与 Java 工程同仓)。
  • 集成面MySQL 为事实源Python 写 raw及约定内字段Java 服务消费 raw 后写 clean、指标与维表。跨语言不共享运行时只共享表结构契约与可选OpenAPI/内部 HTTP

1. 设计目标与原则

目标 说明
轻量优先 单机或少量节点即可闭环 MVP避免过早引入重中间件
可演进 原始层、治理规则、指算法、接口契约版本化,支持重算与追溯
解耦 按数据源隔离适配器,采集/治理/计算/服务异步与边界清晰
风险可控 反爬、去重、异常、合规与审计可落实在流程与表结构上

原则:原始数据以追加为主;指数计算与抓取失败解耦;对外服务读「指标/维表」而非直扫原始大表(必要时走缓存/汇总表)。


2. 总体分层架构

层级 职责 轻量实现形态
采集层 多源页面/API 抓取、任务调度、反爬与频控 Python 爬虫 + APScheduler 或 Cron
接入/缓冲层 削峰、解耦、失败重试 Redis List/Stream或队列表 + 多 Worker
治理层 去重、单位/品种归一、异常与质量打标 Java 定时任务(如 Spring @Scheduled / XXL-Job 等)+ 可配置规则/维表
计算层 指数据模型、基期、权重、链式/环比等 Java 批算,输入输出可幂等、可版本化
存储层 原始明细、清洗数据、指数结果、元数据 MySQL 8.0+(主库,推荐 InnoDB + utf8mb4
服务层 REST API、鉴权、限流、健康检查、管理后台 API Spring Boot(可 Undertow/Tomcat网关按组织规范
展示层 图表、看板、运营侧配置界面 前端 + ECharts与 Java API 联调

存储说明:优先复用现成 MySQL 实例;大对象/审计快照可接 MinIO/对象存储。热查询与去重可叠加 Redis(可选)。


3. 技术选型

领域 建议 备注
爬虫 Pythonhttpx / aiohttp + selectolax / parsel;强渲染页用 Playwright ingest + adapters/禁止在爬虫工程实现指算法/管理端
爬虫调度 Cron 或 Python 内 APScheduler、独立 worker 进程 Java 治理/指计算 在时间上解耦(可 raw 落库后由 Java 轮询或消息触发)
主库 MySQL 8.0+ Java 与 Python 共用(凭 DSN/账号分离读写权限更佳InnoDB、utf8mb4、分区同前
后台与批算 Java 17+Spring Boot 3.x 治理/指数/REST/管理端一体;批处理可用 Spring 自带任务或接调度平台
表结构迁移 FlywayLiquibase放在 server/ 工程 Python 不持有权威 DDL按迁移脚本对齐
缓存/去重 Redis Java 与可选Python 爬虫共用时,键命名空间须约定,避免互踩
API 契约 对外/前后端以 OpenAPI 为单一描述(可 server 生成 spec Python 侧不暴露业务 API 时,可不建 OpenAPI
前端 Vue 或 React + ECharts 请求 Java 后端
可观测 统一标准:双栈结构化日志 + trace id可 OpenTelemetry Java/Python 用不同 app name 区分
部署 Docker Composejava 服务 + crawl-worker 镜像分离;扩容再上编排

4. 模块解耦

各数据源适配器 (Source A/B/…N)
         │
         ▼
   统一采集契约RawRecord + 来源元数据 (source_id、抓取时间、指纹等)
         │
         ▼
   原始层raw只增不改或软删策略
         │
         ▼
   治理与标准化(品种/市场/单位/别名映射、质量 flag
         │
         ▼
   指数计算引擎 ←── 基期/权重/算法版本配置
         │
         ▼
   指标结果表 + 维表
         │
         ▼
   对外/管理 APIJava/ ECharts
  • 源适配器Python:一源一包; 输出统一 raw 契约;选择器、登录、限频不混入 Java 代码。
  • 治理/指数/服务Java:消费 raw 表, clean 与 index_series 等,对外提供 REST 与运营配置能力
  • 指数字典与算法版本index_codeconfig_version 等字段在 Java 域模型与 Flyway 中一以贯之。
  • 计算幂等:由 Java 批任务保证,按「业务日期 + 指数版本」可重算。

5. 数据流(端到端)

  1. 调度触发各源任务,拉取列表/详情。
  2. 写入 raw(可含 LONGTEXT/JSON 与关键检索列),记录 HTTP 状态与内容指纹。
  3. 去重Java 治理)DB 唯一约束在 Flyway 中统一定义Redis 去重与 Java/爬虫约定 key 前缀。
  4. 标准化Java:单位、市场、品种别名 → 维表由 管理端/导入 维护。
  5. 异常与质量Java:写 clean 与 quality_flag
  6. 指数批算Java:读清洗 + 当版本配置 → 写 index_series
  7. APIJava:读指标与维表;管理端 对规则、维表、重算任务 发令;缓存键与索引策略在 Java 侧实现。

6. MySQL 实践要点

  • 版本与字符集MySQL 8.0+utf8mb4InnoDB。
  • 半结构化JSON 存扩展字段,高筛选字段尽量落普通列+索引8.0 可配合生成列建索引。
  • 大表:按交易日期/入库日期 RANGE 分区,便于归档与冷数据迁出。
  • 多 Worker 队列表:使用 SELECT … FOR UPDATE SKIP LOCKED8.0)实现任务抢占。
  • 备份:定期全量/增量raw 与指标层策略与 RPO 对齐业务要求。

与 PostgreSQL 相比:若未来有极重 JSON 分析或强 GIS 需求,可再评估从库/分析库;当前以结构化为主的指数平台,单 MySQL 可覆盖 MVP 至中期


7. 反爬、质量与合规

主题 建议
反爬 频控、退避、UA/协议合法范围内轮换;优先对接官方或开放 API。
去重 DB 唯一约束 + 指纹/哈希;同日多价按产品规则(如中位、最新)在治理层定稿。
异常 硬规则(负值、超阈)→ 统计(分位/IQR→ 业务产季/地域规则。
指算法 固定文档:公式、基期=100、缺权/缺价处理、品种替代;多版本可并存。
合规 robots/条款与用途评估;最小化存个人类信息;对公示指数附方法论与免责声明。

生产环境长期自动化采集:除上表原则外,须满足《数据源上线清单》中的 授权归档、SLA、观测告警、降级与对外话术 等上线门禁;与《产品设计-蔬菜价格指数平台》中 source_code、来源透传约定一致。


8. 主要风险与缓解

风险 缓解
源站改版 监控解析失败率;适配器独立;原始 HTML/快照 可选入对象存储
数据损坏/误删 raw 追加策略、备份、指数可重算
单库压力 分区、读写分离(从库只读 API、热数据 Redis
指争议与口径变更 配置版本化、可重放历史计算、对账报表

9. 分阶段迭代

阶段 内容 验收参考
阶段 1MVP 12 个稳定源、Python 写 raw、Java 最小治理 + 1 套指数、Spring Boot + ECharts 日任务成功率、指口径可说明、API P95
阶段 2 多源、Java 管理维表/规则、多指数、Redis、监控、指数重算入口 维表覆盖率、重算耗时、跨语言可观测
阶段 3 消息驱动、抓取/计算水平扩展、复杂地理层级、SLA 扩展与容灾指标

10. 扩展预留

  • 表设计早期包含:source_idconfig_version时间维度 便于分区。
  • 表结构以 Java 侧迁移为权威;若 Python 需 Pydantic 模型,由 DDL/OpenAPI/手动同步,避免两真相。
  • Java API 无状态,配置与密钥走 Spring Profile / 环境变量/中心配置。
  • Python 爬虫无状态、可水平扩展,仅依赖 DSN 与 PYTHONPATH/pip install -e .

11. 文档维护

  • 表结构、指数口径与对外方法论文档应与本文件同步更新(可拆子文档:docs/指数字典与口径.md 等)。
  • 生产采集门禁与运维基线见《数据源上线清单》;变更授权或 SLA 时同步评审本文件第 7 节是否需修订。
  • 重大架构变更时递增本文「版本」并记录变更摘要。

版本摘要1.2:增补对《数据源上线清单》的引用,明确上线环境持续采集的文档门禁。


12. 项目目录结构(与实现对齐)

双栈单仓Python 仅爬取Java 为后台主工程

fao/
├── docs/                      # 架构、口径、运维说明
├── server/                    # **Java 主工程**Spring Boot 3 + Maven`pom.xml` 在根下)
│   # `mvn -f server/pom.xml spring-boot:run`;迁移:`src/main/resources/db/migration/`
├── src/
│   └── fao/                   # **仅** Python 采集包pyproject 可 `pip install -e .`
│       ├── common/            # 爬虫子进程:配置、日志
│       ├── db/                 # 仅向 raw/队列写入所需的最小数据访问
│       └── ingest/
│           └── adapters/      # 各数据源一模块
├── scripts/                  # 爬虫/批抓入口(`python -m` 等),**不含**指计算
├── config/                   # 爬虫用 `.env.example` 等
├── db/
│   └── migrations/            # **可选**:与 `server` 中 Flyway **二选一为权威**;建议以 `server/.../db/migration` 为准后此处留空或删
├── tests/
│   ├── unit/                 # 建议拆server 内 surefire + Python pytest 各管各
│   └── integration/
├── web/                      # 前端,对接 **Java API**
├── deploy/                    # 含 `docker-compose`:服务 `app`(Java) + `crawl`(Python) 等
├── pyproject.toml            # 仅 fao 爬虫包
├── setup.py
└── .gitignore
路径 放什么、不放什么
server/ 全部 HTTP、安全、域模型、批治理、指计算、迁移 写爬虫。
src/fao/ingest 抓取、限频、仅 raw/队列 模型与写入;禁止 指算法与维表管理。
src/fao/db 爬虫用 DAO表结构消费 Java Flyway 产出。
scripts 只调度 Python 爬取指数重算/治理 入口放在 Java 或企业调度调 Java 接口。
config 以爬虫侧为主Java 用 serverapplication-*.yml
web 管理端/大屏BFF 为 Java

可选e2e/ 联调;ops/ 运维脚本。前端可拆独立仓库,server 为后台边界


13. 语言边界与数据所有权

项目 约定
表结构 Java 工程迁移脚本 为唯一权威Python 升级前 拉取最新 DDL 或从文档生成模型。
raw 写入 Python(或经审查的 ETL写到约定列 写 clean/指数字段,除非团队明确开例外并文档化。
clean / 指标 Java(及经同一鉴权的运维脚本)。
同一 Redis key 加前缀:crawl: / app: 等。
重算指数 管理端/定时器调 Java 内部服务或 POST /internal/...内网 + 鉴权)。
故障 爬虫挂 → raw 空;Java 报表仍可展示历史指数据;治理/批算在 Java 侧可告警「无新 raw」。

本文档为蔬菜价格指数平台的技术架构说明,实现细节以各模块设计与数据库 DDL 为准。