Files
sanguo_vnpy_v2/docs/design/dev-test-prod-env-design.md
claude_dev f953764fef docs(design): 三机开发-测试-生产环境分离设计spec
数据session评估收敛:VPS生产/Mac开发/NAS测试+备份物理隔离。
含硬件基线实测/数据热冷分布/Mac本地副本(非直读NAS SQLite避跨网锁坏)/
docker复用(amd64一致)/单向同步流/数据安全两层防护/4阶段实施步骤。
输入给独立三环境session实施。
2026-07-29 13:44:47 +08:00

184 lines
9.1 KiB
Markdown
Raw Permalink 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.
# 开发-测试-生产三机环境设计(spec)
> 数据层已闭环(方案A)。本 spec 定义**开发/测试与生产分离**的三机环境,让 provider/策略/数据代码改动先在隔离环境验,不污染 VPS 生产、不打断采集/实盘。
> 评估依据:2026-07-29 数据 session 实证(硬件实测 + 代码引用 grep + 网络/磁盘基准)。
> 实施由独立的「三环境 session」负责;本 spec 是它的输入。
---
## 1. 背景与目标
**痛点(实证教训)**
- 开发调试直接在生产 VPS 做 → 风险打断采集/实盘定时任务。
- 数据更新曾**覆盖正确数据**(如指数/个股 6 位码同名碰撞 000852,SZSE 股票≡中证指数),生产数据被错误写入。
**目标**
- 开发(Mac)/ 测试(NAS)/ 生产(VPS**物理隔离**。
- NAS/Mac 用**只读数据副本****永不写回 VPS** → 调试出 bug 只毁副本,碰不到生产。
- 实盘(miniQMTWindows only+ xtdata 采集**必须留 VPS**,不可挪。
---
## 2. 硬件基线(2026-07-29 实测)
| 机 | CPU | 内存 | 磁盘 | 架构 | 现状 |
|----|-----|------|------|------|------|
| **VPS** 49.232.102.198 | 4核 | 16G | 180G **SSD** | AMD64 / Windows | 最强;跑采集+实盘+生产前后端;数据 ~18G(含 dbbardata) |
| **NAS** 192.168.2.154 (ssh sanguo-nas) | 2核 | 7.7G(可用5.6) | 3.5T(剩845G) **HDD** raid1 | x86_64 / Synology | 已跑 plane(9容器)+gitea+redisPython 3.8 旧 |
| **Mac Mini** | M系列(arm64) | — | 228G(剩~24G) | **arm64** / macOS | 开发机;homebrew Python 3.14(与 lock 3.10 冲突);已有 `venv310`(Py3.10.14) |
**网络基准**Mac↔NAS 局域网延迟 4ms、NAS HDD 顺序 98MB/sVPS↔NAS 跨公网。
---
## 3. 三机角色定位
| 机 | 角色 | 跑什么 | 不跑什么 |
|----|------|--------|---------|
| **VPS 生产** | 采集+实盘+生产前后端+生产回测 | xtdata 采集 / miniQMT 实盘 / 生产 API+前端 / 生产回测 | ❌ 不做开发调试 |
| **Mac 开发** | 改代码+调试+单元测试 | provider/策略/数据代码改动、venv 调试、相关单元测试 | ❌ 不碰生产数据、不跑生产回测、不跑容器 |
| **NAS 测试+备份** | 全量回归+备份+冷归档 | docker 容器跑全量 pytest、每日数据备份、冷归档 | ❌ 不采集、不实盘、不扛生产 DB、不参与开发 |
---
## 4. 数据分布(热随算力,冷随容量)
| 数据类型 | VPS | NAS | Mac |
|---------|-----|-----|-----|
| **热数据**dbbardata/parquet/三表/复权因子)| ✅ 权威本地 SSD(**唯一写入源**)| rsync 只读副本 | 本地 SSD 副本(从 NAS 拉)|
| 每日备份 | — | ✅ raid1 冗余 | — |
| 冷归档 | — | ✅ 3.5T 容量 | — |
### 4.1 关键评估结论:Mac 不直读 NAS,用本地副本
Mac↔NAS 虽是局域网(延迟 4ms,可用),但 **Mac 不直接挂载读 NAS 的 SQLite**
- dbbardata 是 SQLite**跨网络文件系统(NFS/SMB)锁机制不可靠**(官方警告,macOS SMB oplock 问题),有**锁坏库风险**。
- HDD 随机 IOPS 低,SQLite 查询每次 IO 叠加网络延迟,回测/全表扫慢。
**结论**Mac 用**本地 SSD 副本**(从 NAS rsync,~10G),本地读零延迟零风险、离线可开发。NAS 副本只作 Mac 的**数据源** + NAS 自身测试容器在容器内本地读(不跨网)。
---
## 5. 环境配置
### 5.1 VPS(不变)
生产,零改动。
### 5.2 Mac(开发)
- **用已有 `venv310`Py3.10.14**,装 `requirements-lock.txt`Py3.10/pandas2.3.3/numpy2.2.6/TA-Lib0.6.8)。
- **不污染 homebrew Python 3.14**(系统其他工具用)。
- provider 配置指向**本地 SSD 数据副本**(从 NAS 拉)。
- vnpy 源码经 `sys.path.insert(0, vnpy_v4.4.0)` 引用(不 pip install,同生产)。
- 已清:`__pycache__`/`data_cache`/`venv`3.14/`venv311`/旧`data`2026-07-29)。
### 5.3 NAS(测试)
- **docker 容器复用 VPS 镜像**(见 §6),隔离 NAS Python 3.8。
- 已有 `docker/Dockerfile.nas` + `deploy-synology.sh`NAS 部署链路已设计)。
- 挂载 VPS rsync 副本为**只读测试数据源**。
- 内存紧(7.7G):测试容器**限内存、不并发猛跑**。
---
## 6. docker 镜像复用策略
| 判断 | 结论 |
|------|------|
| CPU 架构 | VPS=AMD64NAS=x86_64(同 amd64)→ **一致,镜像可直接复用**。Mac=arm64 不同,但 Mac 用 venv 不跑容器,无影响 |
| OS 差异 | Windows(WSL2) vs Synology(Linux) 跑的都是 Linux 容器(`python:3.10-slim`),跨宿主 OS 无碍 |
| 镜像传输(选一)| ① VPS `docker save`→scp→NAS `docker load`(无 registry 最简)② NAS 本地 build`Dockerfile.nas`2核慢一次性)③ Gitea container registryNAS 已有 gitea,最干净) |
---
## 7. 数据同步流(单向,VPS 权威)
```
VPS 采集(每日增量,唯一写入源)
│ ssh+压缩 rsync(每日1次:备份+测试源+Mac数据源)
NAS /volume1/.../sanguo_vnpy_test/ ──rsync测试子集──► Mac 本地 SSD 副本
(只读;NAS/Mac 永不写回 VPS
```
- VPS→NAS:每日 rsync 活跃数据(static+minute_15+valuation+dbbardata ≈10G),首次几分钟、后续增量秒级。
- Mac←NAS:按需 rsync 测试子集。
- 避开 VPS 采集时段(18:05-21:00 schtask 错峰窗口)。
---
## 8. 测试工作流(dev→test→prod 单向晋升)
```
Mac 改代码 → venv310 跑相关单元测试(本地小数据) → commit
↓ rsync 代码到 NAS
NAS 容器跑全量 pytest(真实数据副本) → 回归确认
↓ rsync 代码到 VPS
VPS 生产生效(容器 reload 或 docker restart
```
以后改 provider/数据代码:**Mac 写 → NAS 验 → VPS 上**,全程不碰生产数据、不打断定时任务。
---
## 9. 数据安全隔离(两层防护,根治"覆盖事故")
| 层 | 机制 | 防什么 |
|----|------|--------|
| ① 开发/测试不碰生产 | NAS/Mac 只用**只读副本****永不写回 VPS** | 调试出 bug(如再写错同名编号)只毁副本,碰不到生产 |
| ② VPS 唯一写入源 | 只有 VPS 受控采集/实盘能写;**staging→验证→合并**铁律把关 | 生产更新本身质量(同名碰撞已在 VPS 修 `exchange=SSE` |
---
## 10. 实施步骤(分阶段)
### Phase 1Mac 开发环境(见效最快)
1. `venv310``requirements-lock.txt`(验证 pandas/numpy/TA-Lib/vnpy import)。
2. provider 配置本地数据副本路径(`config/` 或环境变量)。
3. 从 NAS(或 VPSrsync 测试数据子集到 Mac 本地。
4.`tests/portfolio/` + `tests/data_platform/` 确认开发环境可用。
5. 验证:Mac 上改一行 provider → 本地 pytest 通过 → 确认不依赖 VPS。
### Phase 2NAS 测试环境
1. VPS `docker save` 镜像 → scp → NAS `docker load`(或 NAS 本地 build `Dockerfile.nas`)。
2. NAS 起 sanguo 测试容器,挂载 rsync 副本为只读数据源。
3. 容器内跑全量 pytest,确认通过。
4. 验证:NAS 容器能独立跑完整测试套件。
### Phase 3:数据同步管线
1. VPS 加 rsync 定时任务(每日,避开采集窗口)→ NAS。
2. Mac 按需 rsync 脚本(从 NAS 拉测试子集)。
3. 验证:VPS 当日采集 → 次日 NAS/Mac 副本同步。
### Phase 4:流水线固化
- Mac→NAS→VPS 代码晋升脚本(rsync + 容器 reload)。
- 文档化操作 runbook。
---
## 11. 约束与铁律
- **实证 over 推断**:任何"够不够/能不能"先实测(硬件/网络/代码引用 grep),不靠猜。
- **VPS 是唯一数据写入源**;NAS/Mac 副本只读,永不写回。
- **下载 staging→验证→合并**,绝不直接写主库(用户铁律)。
- **baostock 单进程单登录不并发**(封 IP);日 ≤ 48000 次。
- **provider 读本地数据不调 online**(用户铁律)。
- **Mac Mini 防休眠**:长任务/后台前 `caffeinate -i -s`
- **VPS Windows 访问坑**`python -X utf8`、反斜杠路径 via ssh 易被转义(用 powershell `-EncodedCommand`)、GBK 控制台用 ASCII 脚本。
- **commit ≠ 部署 VPS**:改完代码 `scp` 到 VPS + `findstr` 验证。
- **策略逻辑归策略 session**;数据 + 环境归三环境 session。
---
## 12. 已知问题 / 待确认
- **VPS `_deprecated/`**2026-07-29 隔离 ~4Gdaily_baostock/daily/delisted_kline/minute_5 等):观察 1-2 周(约 8/12)确认无影响再删。
- **VPS qfq/raw~1.6G**LocalParquetProvider 旧版引用,LocalUnifiedProvider 不读;中置信废弃,回退旧 provider 需重下。
- **VPS minute_15/minute_kline~4G**`sanguo_data.datareader.read_parquet_15min` 引用(配置驱动),需确认配置指向再决定。
- NAS 当前**无数据副本**`/volume1/stock/sanguo_vnpy/data/` 空),Phase 3 首次 rsync 建立。
- 实盘只做主板+创业板(`filter_kcbj_stock` 排除科创北交,用户未开户 50 万门槛)。
---
## 关联
- 数据层总览:`docs/data-platform/README.md`
- 数据融合权威 spec`docs/superpowers/specs/2026-07-21-data-source-fusion-design.md`(§14
- NAS 部署脚本:`docker/Dockerfile.nas` + `docker/deploy-synology.sh`
- 依赖基线:`requirements-lock.txt`