feat: 添加前端页面和业务说明书
refactor(server): 重构服务层代码结构 feat(server): 添加基础设施、跨境电商、AI决策等核心服务 docs: 完善前端业务说明书和开发进度文档 style: 格式化代码和文档
This commit is contained in:
402
docs/02_Backend/Config_Driven.md
Normal file
402
docs/02_Backend/Config_Driven.md
Normal file
@@ -0,0 +1,402 @@
|
||||
# 配置驱动文档 (Crawlful Hub)
|
||||
|
||||
> **定位**:Crawlful Hub 配置驱动设计文档 - 说明如何实现可配置的系统参数,避免硬编码。
|
||||
> **更新日期**: 2026-03-18
|
||||
> **最高优先级参考**: [Service_Design.md](./Service_Design.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 配置驱动概述
|
||||
|
||||
### 1.1 定义
|
||||
|
||||
配置驱动是指将系统参数(如 ROI 阈值、库存预警值等)从代码中分离出来,通过配置文件或数据库进行管理,实现系统的灵活性和可维护性。
|
||||
|
||||
### 1.2 重要性
|
||||
|
||||
配置驱动的好处:
|
||||
- **灵活性**:无需修改代码即可调整系统行为
|
||||
- **可维护性**:集中管理配置,便于维护
|
||||
- **安全性**:敏感配置可以单独管理
|
||||
- **可扩展性**:易于添加新的配置项
|
||||
- **可监控性**:可以监控配置的使用情况
|
||||
|
||||
---
|
||||
|
||||
## 2. 配置管理
|
||||
|
||||
### 2.1 配置存储
|
||||
|
||||
#### 2.1.1 配置文件
|
||||
|
||||
**适用场景**:静态配置,如数据库连接信息、API 密钥等
|
||||
|
||||
**实现**:
|
||||
- 使用 YAML、JSON、ENV 等格式
|
||||
- 按环境分离配置文件(开发、测试、生产)
|
||||
- 使用配置文件加载工具
|
||||
|
||||
**示例**:
|
||||
```yaml
|
||||
# config.yaml
|
||||
database:
|
||||
host: localhost
|
||||
port: 3306
|
||||
username: root
|
||||
password: password
|
||||
database: crawlful_hub
|
||||
|
||||
api:
|
||||
timeout: 30000
|
||||
retry: 3
|
||||
|
||||
business:
|
||||
roi_threshold: 1.5
|
||||
inventory_alert: 10
|
||||
max_order_quantity: 100
|
||||
```
|
||||
|
||||
#### 2.1.2 数据库
|
||||
|
||||
**适用场景**:动态配置,如业务规则、阈值等
|
||||
|
||||
**实现**:
|
||||
- 创建配置表
|
||||
- 支持配置的版本管理
|
||||
- 支持配置的生效时间
|
||||
|
||||
**示例**:
|
||||
```sql
|
||||
CREATE TABLE cf_config (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
key VARCHAR(100) NOT NULL UNIQUE,
|
||||
value JSON NOT NULL,
|
||||
description VARCHAR(255),
|
||||
tenant_id VARCHAR(50),
|
||||
shop_id VARCHAR(50),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 插入配置
|
||||
INSERT INTO cf_config (key, value, description) VALUES
|
||||
('roi_threshold', '1.5', 'ROI 阈值'),
|
||||
('inventory_alert', '10', '库存预警值'),
|
||||
('max_order_quantity', '100', '最大订单数量');
|
||||
```
|
||||
|
||||
#### 2.1.3 缓存
|
||||
|
||||
**适用场景**:频繁访问的配置
|
||||
|
||||
**实现**:
|
||||
- 使用 Redis 等缓存工具
|
||||
- 配置变更时自动更新缓存
|
||||
- 设置合理的缓存过期时间
|
||||
|
||||
**示例**:
|
||||
```typescript
|
||||
// 配置服务
|
||||
class ConfigService {
|
||||
private cache: Map<string, any> = new Map();
|
||||
|
||||
async getConfig(key: string): Promise<any> {
|
||||
// 先从缓存获取
|
||||
if (this.cache.has(key)) {
|
||||
return this.cache.get(key);
|
||||
}
|
||||
|
||||
// 从数据库获取
|
||||
const config = await this.configRepository.findByKey(key);
|
||||
if (config) {
|
||||
this.cache.set(key, config.value);
|
||||
return config.value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async updateConfig(key: string, value: any): Promise<void> {
|
||||
// 更新数据库
|
||||
await this.configRepository.update(key, value);
|
||||
|
||||
// 更新缓存
|
||||
this.cache.set(key, value);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 配置加载
|
||||
|
||||
#### 2.2.1 启动时加载
|
||||
|
||||
**实现**:
|
||||
- 在应用启动时加载所有配置
|
||||
- 缓存到内存中
|
||||
- 提供配置访问接口
|
||||
|
||||
**示例**:
|
||||
```typescript
|
||||
// 配置加载
|
||||
class ConfigLoader {
|
||||
private config: any = {};
|
||||
|
||||
async load(): Promise<void> {
|
||||
// 加载配置文件
|
||||
const fileConfig = await this.loadFromFile();
|
||||
|
||||
// 加载数据库配置
|
||||
const dbConfig = await this.loadFromDatabase();
|
||||
|
||||
// 合并配置
|
||||
this.config = { ...fileConfig, ...dbConfig };
|
||||
}
|
||||
|
||||
get(key: string, defaultValue?: any): any {
|
||||
const keys = key.split('.');
|
||||
let value = this.config;
|
||||
|
||||
for (const k of keys) {
|
||||
if (value[k] === undefined) {
|
||||
return defaultValue;
|
||||
}
|
||||
value = value[k];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用
|
||||
const configLoader = new ConfigLoader();
|
||||
await configLoader.load();
|
||||
const roiThreshold = configLoader.get('business.roi_threshold', 1.5);
|
||||
```
|
||||
|
||||
#### 2.2.2 动态加载
|
||||
|
||||
**实现**:
|
||||
- 配置变更时自动加载
|
||||
- 支持热更新
|
||||
- 无需重启应用
|
||||
|
||||
**示例**:
|
||||
```typescript
|
||||
// 配置监听器
|
||||
class ConfigListener {
|
||||
constructor(private configService: ConfigService) {
|
||||
// 监听配置变更
|
||||
this.listenForChanges();
|
||||
}
|
||||
|
||||
private listenForChanges(): void {
|
||||
// 监听数据库变更
|
||||
this.configService.on('configChanged', (key: string, value: any) => {
|
||||
console.log(`Config changed: ${key} = ${value}`);
|
||||
// 处理配置变更
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 配置分类
|
||||
|
||||
### 3.1 系统配置
|
||||
|
||||
- **数据库配置**:连接信息、池大小等
|
||||
- **API 配置**:超时时间、重试次数等
|
||||
- **缓存配置**:缓存大小、过期时间等
|
||||
- **安全配置**:密钥、加密算法等
|
||||
|
||||
### 3.2 业务配置
|
||||
|
||||
- **定价配置**:ROI 阈值、定价策略等
|
||||
- **库存配置**:预警值、安全库存等
|
||||
- **订单配置**:最大数量、处理规则等
|
||||
- **物流配置**:物流渠道、运费规则等
|
||||
|
||||
### 3.3 租户配置
|
||||
|
||||
- **租户特定配置**:每个租户的个性化配置
|
||||
- **店铺配置**:每个店铺的特定配置
|
||||
|
||||
---
|
||||
|
||||
## 4. 配置管理界面
|
||||
|
||||
### 4.1 配置列表
|
||||
|
||||
- **展示所有配置**:按分类展示配置项
|
||||
- **搜索配置**:支持按关键字搜索
|
||||
- **过滤配置**:按类型、租户、店铺等过滤
|
||||
|
||||
### 4.2 配置编辑
|
||||
|
||||
- **编辑配置值**:修改配置的当前值
|
||||
- **配置历史**:查看配置的修改历史
|
||||
- **配置生效**:设置配置的生效时间
|
||||
|
||||
### 4.3 配置验证
|
||||
|
||||
- **格式验证**:验证配置值的格式
|
||||
- **范围验证**:验证配置值的范围
|
||||
- **依赖验证**:验证配置之间的依赖关系
|
||||
|
||||
---
|
||||
|
||||
## 5. 最佳实践
|
||||
|
||||
### 5.1 配置命名规范
|
||||
|
||||
- **使用点号分隔**:如 `business.roi_threshold`
|
||||
- **使用小写字母**:避免大小写混淆
|
||||
- **使用下划线**:代替空格
|
||||
- **语义清晰**:配置名称应清晰表达其用途
|
||||
|
||||
### 5.2 配置默认值
|
||||
|
||||
- **设置合理的默认值**:确保系统在没有配置时也能正常运行
|
||||
- **文档化默认值**:在文档中说明默认值的含义
|
||||
- **环境特定默认值**:为不同环境设置不同的默认值
|
||||
|
||||
### 5.3 配置安全
|
||||
|
||||
- **敏感配置加密**:加密存储敏感配置
|
||||
- **配置访问控制**:限制配置的访问权限
|
||||
- **配置审计**:记录配置的修改历史
|
||||
|
||||
### 5.4 配置版本管理
|
||||
|
||||
- **版本控制**:记录配置的版本
|
||||
- **回滚机制**:支持配置的回滚
|
||||
- **变更通知**:通知相关人员配置变更
|
||||
|
||||
---
|
||||
|
||||
## 6. 实现示例
|
||||
|
||||
### 6.1 配置服务
|
||||
|
||||
```typescript
|
||||
// 配置服务
|
||||
class ConfigService {
|
||||
private config: Map<string, any> = new Map();
|
||||
private listeners: Map<string, Function[]> = new Map();
|
||||
|
||||
constructor(private configRepository: ConfigRepository) {
|
||||
this.loadConfig();
|
||||
}
|
||||
|
||||
private async loadConfig(): Promise<void> {
|
||||
const configs = await this.configRepository.findAll();
|
||||
configs.forEach(config => {
|
||||
this.config.set(config.key, config.value);
|
||||
});
|
||||
}
|
||||
|
||||
async get(key: string, defaultValue?: any): Promise<any> {
|
||||
if (this.config.has(key)) {
|
||||
return this.config.get(key);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
async set(key: string, value: any): Promise<void> {
|
||||
await this.configRepository.upsert(key, value);
|
||||
this.config.set(key, value);
|
||||
this.notifyListeners(key, value);
|
||||
}
|
||||
|
||||
private notifyListeners(key: string, value: any): void {
|
||||
if (this.listeners.has(key)) {
|
||||
this.listeners.get(key)?.forEach(listener => {
|
||||
listener(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
on(key: string, listener: Function): void {
|
||||
if (!this.listeners.has(key)) {
|
||||
this.listeners.set(key, []);
|
||||
}
|
||||
this.listeners.get(key)?.push(listener);
|
||||
}
|
||||
|
||||
off(key: string, listener: Function): void {
|
||||
if (this.listeners.has(key)) {
|
||||
const listeners = this.listeners.get(key)?.filter(l => l !== listener);
|
||||
this.listeners.set(key, listeners || []);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 配置使用示例
|
||||
|
||||
```typescript
|
||||
// 定价服务
|
||||
class PricingService {
|
||||
constructor(private configService: ConfigService) {}
|
||||
|
||||
async calculateROI(product: Product, price: number): Promise<number> {
|
||||
// 获取 ROI 阈值配置
|
||||
const roiThreshold = await this.configService.get('business.roi_threshold', 1.5);
|
||||
|
||||
// 计算成本
|
||||
const cost = await this.calculateCost(product);
|
||||
|
||||
// 计算 ROI
|
||||
const roi = (price - cost) / cost;
|
||||
|
||||
// 检查是否达到阈值
|
||||
if (roi < roiThreshold) {
|
||||
this.logger.warn(`ROI below threshold: ${roi} < ${roiThreshold}`, {
|
||||
productId: product.id,
|
||||
price,
|
||||
cost
|
||||
});
|
||||
}
|
||||
|
||||
return roi;
|
||||
}
|
||||
}
|
||||
|
||||
// 库存服务
|
||||
class InventoryService {
|
||||
constructor(private configService: ConfigService) {}
|
||||
|
||||
async checkInventory(productId: string): Promise<void> {
|
||||
// 获取库存预警配置
|
||||
const inventoryAlert = await this.configService.get('business.inventory_alert', 10);
|
||||
|
||||
// 获取库存
|
||||
const inventory = await this.inventoryRepository.findByProductId(productId);
|
||||
|
||||
// 检查库存是否低于预警值
|
||||
if (inventory.quantity < inventoryAlert) {
|
||||
this.logger.warn(`Inventory below alert level: ${inventory.quantity} < ${inventoryAlert}`, {
|
||||
productId,
|
||||
quantity: inventory.quantity,
|
||||
alert: inventoryAlert
|
||||
});
|
||||
|
||||
// 发送库存预警
|
||||
await this.notificationService.sendInventoryAlert(productId, inventory.quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 相关文档
|
||||
|
||||
- [Service_Design.md](./Service_Design.md)
|
||||
- [Data_Consistency.md](./Data_Consistency.md)
|
||||
- [Observability.md](./Observability.md)
|
||||
|
||||
---
|
||||
|
||||
*本文档基于服务设计文档,最后更新: 2026-03-18*
|
||||
Reference in New Issue
Block a user