- docker-compose: 下线 Python backend/config-service,切换至 config-service-rs - archive: 归档 legacy Python 目录至 archive/python/* - services: 新增/更新 common-contracts、api-gateway、各 provider、report-generator-service、config-service-rs - data-persistence-service: API/system 模块与模型/DTO 调整 - frontend: 更新 useApi 与 API 路由 - docs: 更新路线图并勾选光荣退役 - cleanup: 移除 data-distance-service 占位测试
156 lines
7.0 KiB
Markdown
156 lines
7.0 KiB
Markdown
# 架构规范:系统模块(SystemModule)设计准则
|
||
|
||
## 1. 引言
|
||
|
||
### 1.1. 文档目的
|
||
|
||
本文档旨在为我们的事件驱动微服务架构定义一套**“主规则” (Master Rules)**。它通过提出一个概念性的 **`SystemModule` Trait**,形式化地规定了任何一个希望融入本系统的独立微服务所必须遵循的**行为契约和接口规范**。
|
||
|
||
此规范的目标是确保系统中的每一个模块(服务)都是:
|
||
- **可观测的 (Observable)**: 外部系统(如监控面板、API Gateway)可以清晰地了解其健康状况和当前任务。
|
||
- **配置驱动的 (Configuration-Driven)**: 模块的行为和连接信息可以通过外部配置进行管理。
|
||
- **契约绑定的 (Contract-Bound)**: 模块与系统其他部分的交互(消息、事件)遵循共享的、强类型的契约。
|
||
- **生命周期可控的 (Lifecycle-Managed)**: 模块的启动、运行和关闭遵循标准模式。
|
||
|
||
## 2. 架构核心组件回顾
|
||
|
||
一个标准的`SystemModule`存活在以下核心组件构成的环境中:
|
||
- **Message Bus**: 异步通信的唯一通道。
|
||
- **Data Persistence Service**: 持久化数据的唯一入口。
|
||
- **Shared Contracts Crate (`common-contracts`)**: 所有数据模型、消息定义的唯一事实源。
|
||
- **Configuration Source**: 环境变量或配置服务,为模块提供启动参数。
|
||
|
||
## 3. `SystemModule` Trait:模块的行为契约
|
||
|
||
我们可以将一个“合格”的微服务需要满足的条件,抽象地描述为以下Rust Trait。**注意:这并非一个需要真实实现的Rust Trait**,而是一个**设计隐喻**,用于清晰地定义每个独立服务(二进制程序)必须对外暴露的行为。
|
||
|
||
```rust
|
||
/// 设计隐喻:一个合格的系统微服务必须提供的能力
|
||
pub trait SystemModule {
|
||
// --- 1. 自我描述与配置 ---
|
||
|
||
/// 返回模块的唯一、人类可读的名称,如 "finnhub-provider-service"
|
||
fn module_id(&self) -> &'static str;
|
||
|
||
/// 声明本模块需要从外部获取的所有配置项
|
||
/// 用于自动生成文档、部署脚本和配置校验
|
||
fn required_configuration(&self) -> Vec<ConfigSpec>;
|
||
|
||
// --- 2. 消息契约 ---
|
||
|
||
/// 声明本模块会订阅(监听)哪些命令 (Commands)
|
||
/// 用于生成系统交互图和验证消息路由
|
||
fn subscribed_commands(&self) -> Vec<MessageType>;
|
||
|
||
/// 声明本模块会发布(产生)哪些事件 (Events)
|
||
fn published_events(&self) -> Vec<MessageType>;
|
||
|
||
// --- 3. 可观测性接口 (核心) ---
|
||
|
||
/// [必须实现为HTTP GET /health]
|
||
/// 提供模块当前的健康状态
|
||
async fn get_health_status(&self) -> HealthStatus;
|
||
|
||
/// [必须实现为HTTP GET /tasks]
|
||
/// 报告模块当前正在处理的所有任务及其进度
|
||
/// 这是实现分布式进度追踪的关键
|
||
async fn get_current_tasks(&self) -> Vec<TaskProgress>;
|
||
|
||
// --- 4. 生命周期 ---
|
||
|
||
/// 模块的主运行循环
|
||
/// 包含连接到Message Bus、处理消息、响应健康检查等逻辑
|
||
async fn run(&mut self) -> Result<(), ModuleError>;
|
||
}
|
||
```
|
||
|
||
## 4. `SystemModule` Trait 的具象化实现
|
||
|
||
上述Trait中的每一项都必须在微服务中以具体的技术形式落地。
|
||
|
||
**每个微服务都必须:**
|
||
|
||
1. **提供一个 `Dockerfile`** 用于容器化部署。
|
||
2. 在启动时,根据`required_configuration()`的定义,**从环境变量或配置服务中读取配置**。缺少必要配置必须启动失败。
|
||
3. 在启动后,**连接到 Message Bus**,并严格按照`subscribed_commands()`和`published_events()`的声明进行订阅和发布。
|
||
4. **实现一个内置的HTTP服务器** (e.g., using Axum),并暴露**两个强制性的API端点**:
|
||
- `GET /health`: 返回`HealthStatus`的JSON表示。用于服务发现、负载均衡和健康检查。
|
||
- `GET /tasks`: 返回`Vec<TaskProgress>`的JSON表示。用于外部系统查询当前模块正在执行什么任务。
|
||
|
||
### 4.1. 可观测性接口的数据结构
|
||
|
||
这些结构体将被定义在`common-contracts`中,供所有模块和监控系统使用。
|
||
|
||
```rust
|
||
// common-contracts/src/observability.rs
|
||
|
||
#[derive(Serialize, Deserialize, Debug)]
|
||
pub enum ServiceStatus {
|
||
Ok, // 一切正常
|
||
Degraded, // 功能部分受损,但仍在运行
|
||
Unhealthy, // 服务异常
|
||
}
|
||
|
||
#[derive(Serialize, Deserialize, Debug)]
|
||
pub struct HealthStatus {
|
||
pub module_id: String,
|
||
pub status: ServiceStatus,
|
||
pub version: String,
|
||
pub details: HashMap<String, String>, // e.g., "message_bus_connection": "ok"
|
||
}
|
||
|
||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||
pub struct TaskProgress {
|
||
pub request_id: Uuid, // 关联到最初的用户请求
|
||
pub task_name: String, // e.g., "fetch_financials_for_aapl"
|
||
pub status: String, // e.g., "in_progress", "retrying", "blocked"
|
||
pub progress_percent: u8, // 0-100
|
||
pub details: String, // 人类可读的详细状态
|
||
pub started_at: DateTime<Utc>,
|
||
}
|
||
```
|
||
|
||
## 5. 示范设计 (Example Designs)
|
||
|
||
### 示例一: `finnhub-provider-service`
|
||
|
||
这是一个相对简单的、无状态的数据拉取服务。
|
||
|
||
- **`module_id`**: `"finnhub-provider-service"`
|
||
- **`required_configuration`**: `FINNHUB_API_KEY`, `MESSAGE_BUS_URL`, `DATA_PERSISTENCE_URL`
|
||
- **`subscribed_commands`**: `FetchCompanyDataCommand`
|
||
- **`published_events`**: `CompanyProfilePersistedEvent`, `FinancialsPersistedEvent`
|
||
- **`GET /health` 返回**: `{ "module_id": "...", "status": "Ok", ... }`
|
||
- **`GET /tasks` 返回**:
|
||
- 空闲时: `[]`
|
||
- 正在为AAPL拉取数据时: `[{ "request_id": "...", "task_name": "fetch_data_for_aapl", "status": "in_progress", "progress_percent": 50, "details": "Fetching financial statements...", ... }]`
|
||
|
||
### 示例二: `report-generator-service`
|
||
|
||
这是一个更复杂的、有状态的业务逻辑服务。
|
||
|
||
- **`module_id`**: `"report-generator-service"`
|
||
- **`required_configuration`**: `GEMINI_API_KEY`, `MESSAGE_BUS_URL`, `DATA_PERSISTENCE_URL`
|
||
- **`subscribed_commands`**: `GenerateReportCommand` (一个新的命令,由API Gateway发起)
|
||
- **`published_events`**: `ReportGenerationStarted`, `ReportSectionCompleted`, `ReportCompletedEvent`, `ReportFailedEvent`
|
||
- **`GET /health` 返回**: `{ "module_id": "...", "status": "Ok", ... }`
|
||
- **`GET /tasks` 返回**:
|
||
- 空闲时: `[]`
|
||
- 正在为600519.SH生成报告时:
|
||
```json
|
||
[
|
||
{
|
||
"request_id": "abc-123",
|
||
"task_name": "generate_report_for_600519.SH",
|
||
"status": "in_progress",
|
||
"progress_percent": 66,
|
||
"details": "Generating bull_case analysis, waiting for AI model response.",
|
||
"started_at": "..."
|
||
}
|
||
]
|
||
```
|
||
|
||
## 6. 结论
|
||
|
||
`SystemModule`规范为我们的微服务生态系统提供了骨架和纪律。通过强制要求所有模块实现标准的可观测性接口和消息契约,我们可以构建一个真正健壮、透明且易于管理的分布式系统。所有新服务的开发都将以此规范为起点。
|