Files
makemd/docs/02_Backend/04_Config_Driven.md

402 lines
9.4 KiB
Markdown
Raw Normal View History

# 配置驱动文档 (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*