trading-discipline-backend/docs/DATA_SOURCES.md
刘华勇 c19ca2aa4c feat: 初始化交易纪律系统后端
- 基于 axum + sqlx + tokio 的 Rust 后端服务
- 实现多数据源管理(东方财富/新浪/腾讯)含 failover 容错
- 数据源健康检查、请求日志记录与重放诊断
- 股票公司列表、历史K线、实时行情数据获取
- 配置 .gitignore:忽略 target 构建产物、.env 密钥、data 数据库
2026-06-17 15:46:48 +08:00

5.5 KiB
Raw Blame History

📡 多数据源管理系统

支持多个金融数据源,自动降级、负载均衡、健康监控。

🏗️ 架构设计

                    ┌─────────────────────┐
                    │   DataSourceManager │  ← 统一调度入口
                    │   (调度/降级/聚合)   │
                    └──────────┬──────────┘
                               │
        ┌──────────┬───────────┼───────────┬──────────┐
        ▼          ▼           ▼           ▼          ▼
  ┌──────────┐┌─────────┐┌──────────┐┌─────────┐┌────────┐
  │EastMoney ││  Sina   ││ Tencent  ││ Tushare ││  Mock  │
  │东方财富  ││新浪财经 ││腾讯财经  ││(需Token)││(测试用)│
  │priority:1││  pri:2  ││  pri:3   ││  pri:1  ││ pri:99 │
  └──────────┘└─────────┘└──────────┘└─────────┘└────────┘
        │          │           │
        ▼          ▼           ▼
   免费无需Token东方财富/新浪/腾讯)

🎯 运行模式

模式 说明 配置值
Failover (默认) 按优先级依次尝试,失败自动降级到下一个源 failover
Aggregate 同时请求多个源,取最快返回结果 aggregate
PrimaryOnly 仅使用主源,失败不降级 primary_only

📊 数据源能力对比

数据源 公司列表 历史K线 实时行情 是否免费 限流
东方财富 免费 宽松
新浪财经 免费 中等
腾讯财经 免费 宽松
Tushare 🔑 需Token 严格
Mock -

⚙️ 配置说明

编辑 backend/.env

# 运行模式
DATA_SOURCE_MODE=failover        # failover | aggregate | primary_only
DATA_SOURCE_PRIMARY=eastmoney    # 主数据源
DATA_SOURCE_TIMEOUT=15           # 超时秒数

# Tushare可选
TUSHARE_TOKEN=your_token_here

📡 管理 API

查看数据源状态

GET /api/datasources

响应示例:

{
  "code": 200,
  "data": {
    "mode": "failover",
    "primary": "eastmoney",
    "sources": [
      {
        "name": "eastmoney",
        "type": "eastmoney",
        "status": "healthy",
        "priority": 1,
        "success_rate": "100.0%",
        "avg_latency_ms": 133
      }
    ]
  }
}

触发健康检查

POST /api/datasources/health

切换运行模式

PUT /api/datasources/mode
Content-Type: application/json

{ "mode": "aggregate" }

测试单个数据源

GET /api/datasources/eastmoney/test

🔄 降级机制详解

以 Failover 模式获取 K线为例

请求: GET /api/stocks/daily?code=600519&start=2026-01-01&end=2026-06-15

① 尝试 eastmoney (优先级1)
   → 失败(网络/解析错误)
   → 重试 2 次,仍失败

② 自动降级到 sina (优先级2)
   → 请求成功 ✅
   → 返回数据

如果 sina 也失败:

③ 自动降级到 tencent (优先级3)
   → 请求成功 ✅

如果全部失败:

④ 最终降级到 mock (优先级99)
   → 返回模拟数据
   → 保证系统不报错

📈 健康状态

每个数据源维护以下指标:

指标 说明
status healthy / degraded / down / unknown
request_count 总请求数
success_count 成功次数
success_rate 成功率
avg_latency_ms 平均延迟
last_success 最后成功时间
last_error 最后错误信息

自动状态判定规则

  • healthy: 成功率 > 90%
  • degraded: 成功率 50%-90%
  • down: 成功率 < 50% 且请求 > 5 次

🛠️ 扩展新数据源

1. 实现 DataSource trait

// src/services/sources/my_source.rs
use crate::services::traits::DataSource;

pub struct MySource { /* ... */ }

#[async_trait]
impl DataSource for MySource {
    fn name(&self) -> &str { "mysource" }
    fn source_type(&self) -> &'static str { "mysource" }
    async fn health_check(&self) -> anyhow::Result<bool> { /* ... */ }

    fn supports_daily(&self) -> bool { true }

    async fn fetch_daily_quotes(&self, code: &str, start: NaiveDate, end: NaiveDate)
        -> anyhow::Result<Vec<StockDaily>> { /* ... */ }
}

2. 注册到管理器

// src/services/sources/mod.rs
pub mod my_source;

// src/services/manager.rs DataSourceManager::new()
match src_cfg.source_type {
    SourceType::MySource => Arc::new(MySource::new(timeout)),
}

3. 添加配置

// src/services/config.rs
pub enum SourceType {
    MySource,
}

🚀 快速测试

# 启动后端
cd backend && ./start.sh

# 测试公司列表
curl "http://localhost:8080/api/companies?page=1&page_size=5"

# 测试K线真实数据
curl "http://localhost:8080/api/stocks/daily?code=600519&start=2026-01-01&end=2026-06-15"

# 测试实时行情
curl "http://localhost:8080/api/stocks/latest?codes=000100,600519"

# 查看数据源状态
curl "http://localhost:8080/api/datasources"