- 基于 axum + sqlx + tokio 的 Rust 后端服务 - 实现多数据源管理(东方财富/新浪/腾讯)含 failover 容错 - 数据源健康检查、请求日志记录与重放诊断 - 股票公司列表、历史K线、实时行情数据获取 - 配置 .gitignore:忽略 target 构建产物、.env 密钥、data 数据库
5.5 KiB
5.5 KiB
📡 多数据源管理系统
支持多个金融数据源,自动降级、负载均衡、健康监控。
🏗️ 架构设计
┌─────────────────────┐
│ 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"