feat: 添加前端页面和业务说明书

refactor(server): 重构服务层代码结构
feat(server): 添加基础设施、跨境电商、AI决策等核心服务
docs: 完善前端业务说明书和开发进度文档
style: 格式化代码和文档
This commit is contained in:
2026-03-18 19:12:38 +08:00
parent c932a67be2
commit 6d0d2b6157
140 changed files with 23859 additions and 5833 deletions

View 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*

View File

@@ -0,0 +1,442 @@
# 数据一致性文档 (Crawlful Hub)
> **定位**Crawlful Hub 数据一致性设计文档 - 确保系统数据的准确性和可靠性。
> **更新日期**: 2026-03-18
> **最高优先级参考**: [Service_Design.md](./Service_Design.md)
---
## 1. 数据一致性概述
### 1.1 重要性
数据一致性是系统的核心要求,特别是对于涉及资金、库存、订单等关键业务数据的系统。数据不一致可能导致:
- 财务损失
- 库存管理混乱
- 订单处理错误
- 商户信任度下降
- 系统不可用
### 1.2 核心原则
- **原子性**:操作要么全部成功,要么全部失败
- **一致性**:操作前后数据状态保持一致
- **隔离性**:并发操作互不干扰
- **持久性**:数据一旦提交,就永久保存
---
## 2. 事务边界
### 2.1 定义
事务边界是指一组操作的范围,这些操作必须作为一个整体执行,要么全部成功,要么全部失败。
### 2.2 实现方法
#### 2.2.1 数据库事务
**适用场景**:涉及数据库操作的业务流程
**实现**
- 使用 `@Transactional` 注解Java/Spring
- 使用 `transaction` 方法Node.js/Sequelize
- 使用数据库原生事务
**示例**
```typescript
// Node.js/Sequelize 示例
async createOrder(orderData: OrderCreateDto): Promise<Order> {
return await this.sequelize.transaction(async (t) => {
// 1. 创建订单
const order = await Order.create(orderData, { transaction: t });
// 2. 扣减库存
await Inventory.decrement('quantity', {
by: orderData.quantity,
where: { productId: orderData.productId },
transaction: t
});
// 3. 记录交易
await Transaction.create({
orderId: order.id,
amount: order.totalAmount,
type: 'ORDER_CREATED'
}, { transaction: t });
return order;
});
}
```
#### 2.2.2 分布式事务
**适用场景**:跨多个服务或数据源的业务流程
**实现**
- 两阶段提交2PC
- 补偿事务TCC
- 消息队列 + 最终一致性
**示例**
```typescript
// 补偿事务示例
async processOrder(orderId: string): Promise<void> {
// 1. 尝试处理订单
const order = await this.orderRepository.findById(orderId);
try {
// 2. 扣减库存
await this.inventoryService.deductInventory(
order.productId,
order.quantity
);
// 3. 安排物流
const shippingId = await this.logisticsService.createShipping(order);
order.shippingId = shippingId;
// 4. 标记订单为已处理
order.status = 'PROCESSED';
await this.orderRepository.save(order);
} catch (error) {
// 5. 补偿操作
await this.compensateOrder(order);
throw error;
}
}
async compensateOrder(order: Order): Promise<void> {
// 恢复库存
await this.inventoryService.restoreInventory(
order.productId,
order.quantity
);
// 取消物流
if (order.shippingId) {
await this.logisticsService.cancelShipping(order.shippingId);
}
// 标记订单为失败
order.status = 'FAILED';
await this.orderRepository.save(order);
}
```
### 2.3 最佳实践
- **明确事务边界**:只包含必要的操作
- **保持事务简短**:减少锁持有时间
- **合理设置隔离级别**:根据业务需求选择适当的隔离级别
- **处理事务异常**:确保异常情况下能够正确回滚
---
## 3. 幂等性
### 3.1 定义
幂等性是指同一个请求执行多次,结果应该相同。
### 3.2 实现方法
#### 3.2.1 请求ID
**适用场景**:所有外部 API 调用、支付回调等
**实现**
- 生成唯一的 `requestId`
- 记录已处理的 `requestId`
- 检查重复请求
**示例**
```typescript
async processPayment(paymentData: PaymentDto): Promise<Payment> {
// 检查是否已处理
const existingPayment = await this.paymentRepository.findByRequestId(paymentData.requestId);
if (existingPayment) {
return existingPayment;
}
// 处理支付
const payment = await this.paymentRepository.create({
...paymentData,
status: 'PROCESSING'
});
try {
// 调用支付网关
const result = await this.paymentGateway.process(paymentData);
// 更新支付状态
payment.status = result.status;
payment.transactionId = result.transactionId;
await this.paymentRepository.save(payment);
} catch (error) {
// 更新支付状态为失败
payment.status = 'FAILED';
await this.paymentRepository.save(payment);
throw error;
}
return payment;
}
```
#### 3.2.2 乐观锁
**适用场景**:并发更新操作
**实现**
- 使用版本号或时间戳
- 更新时检查版本号
- 版本号不匹配则重试或失败
**示例**
```typescript
async updateProduct(productId: string, updates: Partial<Product>): Promise<Product> {
const product = await this.productRepository.findById(productId);
const currentVersion = product.version;
// 尝试更新
const updated = await this.productRepository.update(
{
...updates,
version: currentVersion + 1
},
{
where: {
id: productId,
version: currentVersion
}
}
);
if (updated[0] === 0) {
// 版本不匹配,说明被其他线程修改
throw new ConflictException('Product has been updated by another process');
}
return await this.productRepository.findById(productId);
}
```
### 3.3 最佳实践
- **为所有外部请求生成唯一ID**
- **存储请求ID和处理结果**
- **设置合理的过期时间**
- **处理重复请求时返回相同的结果**
---
## 4. 状态机
### 4.1 定义
状态机是一种用于描述对象状态及其转换规则的模型。
### 4.2 实现方法
#### 4.2.1 枚举状态
**适用场景**:简单的状态流转
**实现**
- 使用枚举定义状态
- 使用条件判断处理状态转换
**示例**
```typescript
enum OrderStatus {
PENDING = 'PENDING',
PROCESSING = 'PROCESSING',
SHIPPED = 'SHIPPED',
DELIVERED = 'DELIVERED',
CANCELLED = 'CANCELLED',
FAILED = 'FAILED'
}
class OrderStateMachine {
static canTransition(from: OrderStatus, to: OrderStatus): boolean {
const transitions = {
[OrderStatus.PENDING]: [OrderStatus.PROCESSING, OrderStatus.CANCELLED],
[OrderStatus.PROCESSING]: [OrderStatus.SHIPPED, OrderStatus.FAILED, OrderStatus.CANCELLED],
[OrderStatus.SHIPPED]: [OrderStatus.DELIVERED, OrderStatus.FAILED],
[OrderStatus.DELIVERED]: [],
[OrderStatus.CANCELLED]: [],
[OrderStatus.FAILED]: []
};
return transitions[from].includes(to);
}
}
async updateOrderStatus(orderId: string, newStatus: OrderStatus): Promise<Order> {
const order = await this.orderRepository.findById(orderId);
if (!OrderStateMachine.canTransition(order.status, newStatus)) {
throw new BadRequestException(`Cannot transition from ${order.status} to ${newStatus}`);
}
order.status = newStatus;
return await this.orderRepository.save(order);
}
```
#### 4.2.2 状态机库
**适用场景**:复杂的状态流转
**实现**
- 使用专门的状态机库
- 定义状态、事件和转换
- 处理副作用
**示例**
```typescript
// 使用 xstate 库
import { createMachine, interpret } from 'xstate';
const orderMachine = createMachine({
id: 'order',
initial: 'PENDING',
states: {
PENDING: {
on: {
PROCESS: 'PROCESSING',
CANCEL: 'CANCELLED'
}
},
PROCESSING: {
on: {
SHIP: 'SHIPPED',
FAIL: 'FAILED',
CANCEL: 'CANCELLED'
}
},
SHIPPED: {
on: {
DELIVER: 'DELIVERED',
FAIL: 'FAILED'
}
},
DELIVERED: {
type: 'final'
},
CANCELLED: {
type: 'final'
},
FAILED: {
type: 'final'
}
}
});
const orderService = interpret(orderMachine)
.onTransition(state => console.log('Order state:', state.value));
orderService.start();
orderService.send('PROCESS'); // 从 PENDING 到 PROCESSING
orderService.send('SHIP'); // 从 PROCESSING 到 SHIPPED
orderService.send('DELIVER'); // 从 SHIPPED 到 DELIVERED
```
### 4.3 最佳实践
- **明确定义状态和转换规则**
- **使用状态机管理所有状态流转**
- **记录状态转换历史**
- **处理状态转换的副作用**
- **验证状态转换的合法性**
---
## 5. 数据一致性保障措施
### 5.1 数据库层面
- **使用事务**:确保数据操作的原子性
- **设置约束**:使用唯一约束、外键约束等
- **合理索引**:提高查询性能,减少锁竞争
- **定期备份**:防止数据丢失
### 5.2 应用层面
- **实现幂等性**:处理重复请求
- **使用状态机**:管理状态流转
- **异步处理**:使用消息队列处理非实时操作
- **补偿机制**:处理失败的操作
### 5.3 监控和告警
- **数据一致性检查**:定期检查数据一致性
- **异常监控**:监控数据操作异常
- **告警机制**:及时发现和处理数据不一致问题
---
## 6. 常见问题及解决方案
### 6.1 并发更新冲突
**问题**:多个用户同时更新同一条数据
**解决方案**
- 使用乐观锁
- 使用悲观锁
- 实现队列机制
### 6.2 分布式事务
**问题**:跨多个服务或数据源的事务
**解决方案**
- 使用消息队列 + 最终一致性
- 使用 Saga 模式
- 使用 TCC 模式
### 6.3 数据同步延迟
**问题**:不同系统之间的数据同步存在延迟
**解决方案**
- 使用事件驱动架构
- 实现增量同步
- 设置合理的同步频率
---
## 7. 测试策略
### 7.1 单元测试
- 测试单个组件的逻辑
- 模拟依赖
- 验证边界情况
### 7.2 集成测试
- 测试多个组件的交互
- 测试事务边界
- 测试状态转换
### 7.3 压力测试
- 测试并发场景
- 测试系统稳定性
- 测试数据一致性
---
## 8. 相关文档
- [Service_Design.md](./Service_Design.md)
- [Database_Design.md](./Database_Design.md)
- [API_Specs](./API_Specs/)
---
*本文档基于服务设计文档,最后更新: 2026-03-18*

View File

@@ -0,0 +1,492 @@
# 事件驱动文档 (Crawlful Hub)
> **定位**Crawlful Hub 事件驱动设计文档 - 定义核心事件和处理流程,实现系统解耦和可扩展性。
> **更新日期**: 2026-03-18
> **最高优先级参考**: [Service_Design.md](./Service_Design.md)
---
## 1. 事件驱动概述
### 1.1 定义
事件驱动是一种架构模式,通过事件的产生、发布、订阅和处理来实现系统组件之间的通信和协作。
### 1.2 重要性
事件驱动架构的好处:
- **解耦**:组件之间通过事件通信,减少直接依赖
- **可扩展性**:可以轻松添加新的事件处理逻辑
- **异步处理**:事件处理可以异步执行,提高系统性能
- **可靠性**:事件可以持久化,确保消息不丢失
- **可观测性**:可以追踪事件的产生和处理
---
## 2. 核心事件
### 2.1 事件定义
| 事件名称 | 描述 | 触发条件 | 相关服务 |
|----------|------|----------|----------|
| **OrderCreated** | 订单创建 | 用户提交订单 | 订单服务、库存服务、通知服务 |
| **OrderUpdated** | 订单更新 | 订单状态变更 | 订单服务、通知服务 |
| **OrderCompleted** | 订单完成 | 订单状态变为已完成 | 订单服务、结算服务、通知服务 |
| **OrderCancelled** | 订单取消 | 订单状态变为已取消 | 订单服务、库存服务、通知服务 |
| **ProductCreated** | 商品创建 | 创建新商品 | 商品服务、搜索服务 |
| **ProductUpdated** | 商品更新 | 更新商品信息 | 商品服务、搜索服务 |
| **ProductPriceChanged** | 商品价格变更 | 商品价格更新 | 商品服务、定价服务、搜索服务 |
| **InventoryLow** | 库存不足 | 库存低于预警值 | 库存服务、通知服务 |
| **InventoryUpdated** | 库存更新 | 库存数量变更 | 库存服务、商品服务 |
| **PaymentProcessed** | 支付处理 | 支付完成 | 支付服务、订单服务 |
| **SettlementCreated** | 结算创建 | 创建结算单 | 结算服务、通知服务 |
| **MerchantRegistered** | 商户注册 | 新商户注册 | 商户服务、通知服务 |
| **MerchantVerified** | 商户验证 | 商户资质验证通过 | 商户服务、通知服务 |
### 2.2 事件结构
**示例**
```typescript
interface Event {
id: string; // 事件ID
type: string; // 事件类型
timestamp: number; // 事件时间戳
data: any; // 事件数据
metadata: {
tenantId: string; // 租户ID
shopId: string; // 店铺ID
traceId: string; // 追踪ID
source: string; // 事件源
};
}
// 订单创建事件示例
const orderCreatedEvent: Event = {
id: 'event-001',
type: 'OrderCreated',
timestamp: Date.now(),
data: {
orderId: 'order-001',
userId: 'user-001',
items: [
{
productId: 'product-001',
quantity: 2,
price: 99.99
}
],
totalAmount: 199.98,
status: 'PENDING'
},
metadata: {
tenantId: 'tenant-001',
shopId: 'shop-001',
traceId: 'trace-001',
source: 'OrderService'
}
};
```
---
## 3. 事件处理流程
### 3.1 事件发布
**实现**
- 使用事件总线或消息队列
- 事件发布者将事件发送到事件总线
- 事件总线确保事件的传递
**示例**
```typescript
// 事件总线
class EventBus {
private listeners: Map<string, Function[]> = new Map();
publish(event: Event): void {
console.log(`Publishing event: ${event.type}`, event);
if (this.listeners.has(event.type)) {
this.listeners.get(event.type)?.forEach(listener => {
try {
listener(event);
} catch (error) {
console.error(`Error handling event ${event.type}:`, error);
}
});
}
}
subscribe(eventType: string, listener: Function): void {
if (!this.listeners.has(eventType)) {
this.listeners.set(eventType, []);
}
this.listeners.get(eventType)?.push(listener);
}
unsubscribe(eventType: string, listener: Function): void {
if (this.listeners.has(eventType)) {
const listeners = this.listeners.get(eventType)?.filter(l => l !== listener);
this.listeners.set(eventType, listeners || []);
}
}
}
// 订单服务发布事件
class OrderService {
constructor(private eventBus: EventBus) {}
async createOrder(orderData: OrderCreateDto): Promise<Order> {
// 创建订单
const order = await this.orderRepository.create(orderData);
// 发布订单创建事件
const event: Event = {
id: uuidv4(),
type: 'OrderCreated',
timestamp: Date.now(),
data: order,
metadata: {
tenantId: order.tenantId,
shopId: order.shopId,
traceId: orderData.traceId,
source: 'OrderService'
}
};
this.eventBus.publish(event);
return order;
}
}
```
### 3.2 事件订阅
**实现**
- 服务订阅感兴趣的事件
- 当事件发生时,执行相应的处理逻辑
**示例**
```typescript
// 库存服务订阅事件
class InventoryService {
constructor(private eventBus: EventBus) {
// 订阅订单创建事件
this.eventBus.subscribe('OrderCreated', this.handleOrderCreated.bind(this));
// 订阅订单取消事件
this.eventBus.subscribe('OrderCancelled', this.handleOrderCancelled.bind(this));
}
private async handleOrderCreated(event: Event): Promise<void> {
const order = event.data;
// 扣减库存
for (const item of order.items) {
await this.deductInventory(item.productId, item.quantity);
}
}
private async handleOrderCancelled(event: Event): Promise<void> {
const order = event.data;
// 恢复库存
for (const item of order.items) {
await this.restoreInventory(item.productId, item.quantity);
}
}
}
// 通知服务订阅事件
class NotificationService {
constructor(private eventBus: EventBus) {
// 订阅订单相关事件
this.eventBus.subscribe('OrderCreated', this.sendOrderConfirmation.bind(this));
this.eventBus.subscribe('OrderUpdated', this.sendOrderUpdate.bind(this));
this.eventBus.subscribe('OrderCompleted', this.sendOrderCompletion.bind(this));
this.eventBus.subscribe('OrderCancelled', this.sendOrderCancellation.bind(this));
}
private async sendOrderConfirmation(event: Event): Promise<void> {
const order = event.data;
// 发送订单确认通知
await this.sendEmail(order.userId, 'Order Confirmation', `Your order ${order.id} has been created`);
}
private async sendOrderUpdate(event: Event): Promise<void> {
const order = event.data;
// 发送订单更新通知
await this.sendEmail(order.userId, 'Order Update', `Your order ${order.id} has been updated`);
}
private async sendOrderCompletion(event: Event): Promise<void> {
const order = event.data;
// 发送订单完成通知
await this.sendEmail(order.userId, 'Order Completed', `Your order ${order.id} has been completed`);
}
private async sendOrderCancellation(event: Event): Promise<void> {
const order = event.data;
// 发送订单取消通知
await this.sendEmail(order.userId, 'Order Cancelled', `Your order ${order.id} has been cancelled`);
}
}
```
### 3.3 事件持久化
**实现**
- 使用消息队列(如 RabbitMQ、Kafka持久化事件
- 确保事件不丢失
- 支持事件的重试和重放
**示例**
```typescript
// 使用 Kafka
import { Kafka } from 'kafkajs';
const kafka = new Kafka({
clientId: 'crawlful-hub',
brokers: ['localhost:9092']
});
const producer = kafka.producer();
const consumer = kafka.consumer({ groupId: 'inventory-service' });
// 发布事件
async function publishEvent(event: Event): Promise<void> {
await producer.connect();
await producer.send({
topic: 'events',
messages: [
{
key: event.type,
value: JSON.stringify(event)
}
]
});
await producer.disconnect();
}
// 订阅事件
async function subscribeEvents(): Promise<void> {
await consumer.connect();
await consumer.subscribe({ topic: 'events', fromBeginning: false });
await consumer.run({
eachMessage: async ({ message }) => {
const event = JSON.parse(message.value?.toString() || '{}');
console.log('Received event:', event);
// 处理事件
if (event.type === 'OrderCreated') {
await handleOrderCreated(event);
} else if (event.type === 'OrderCancelled') {
await handleOrderCancelled(event);
}
}
});
}
```
---
## 4. 事件驱动架构
### 4.1 架构图
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ │ │ │ │ │
│ 服务 A │────>│ 事件总线 │────>│ 服务 B │
│ │ │ │ │ │
└─────────────┘ └─────────────┘ └─────────────┘
^ │ ^
│ │ │
│ v │
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ │ │ │ │ │
│ 服务 D │<────│ 消息队列 │<────│ 服务 C │
│ │ │ │ │ │
└─────────────┘ └─────────────┘ └─────────────┘
```
### 4.2 核心组件
- **事件发布者**:产生事件的服务
- **事件总线**:传递事件的中间件
- **消息队列**:持久化事件的存储
- **事件订阅者**:处理事件的服务
- **事件处理器**:执行具体的事件处理逻辑
### 4.3 优势
- **松耦合**:服务之间通过事件通信,减少直接依赖
- **可扩展性**:可以轻松添加新的服务和事件处理逻辑
- **可靠性**:事件可以持久化,确保消息不丢失
- **灵活性**:事件处理可以异步执行,提高系统性能
- **可观测性**:可以追踪事件的产生和处理
---
## 5. 最佳实践
### 5.1 事件设计
- **事件命名**:使用清晰、语义化的事件名称
- **事件结构**:统一事件结构,包含必要的字段
- **事件数据**:只包含必要的数据,避免过大
- **事件版本**:考虑事件的版本管理
### 5.2 事件处理
- **幂等性**:确保事件处理的幂等性
- **错误处理**:妥善处理事件处理过程中的错误
- **重试机制**:实现事件处理的重试机制
- **死信队列**:处理无法正常处理的事件
### 5.3 性能优化
- **批量处理**:批量处理事件,减少网络开销
- **异步处理**:使用异步处理提高性能
- **缓存**:合理使用缓存,减少重复计算
- **限流**:实现事件处理的限流机制
### 5.4 监控和告警
- **事件监控**:监控事件的产生和处理
- **事件延迟**:监控事件处理的延迟
- **错误率**:监控事件处理的错误率
- **告警机制**:设置合理的告警阈值
---
## 6. 实现示例
### 6.1 事件总线
```typescript
// 事件总线实现
class EventBus {
private listeners: Map<string, Function[]> = new Map();
private queue: Event[] = [];
private processing = false;
publish(event: Event): void {
this.queue.push(event);
if (!this.processing) {
this.processQueue();
}
}
private async processQueue(): Promise<void> {
this.processing = true;
while (this.queue.length > 0) {
const event = this.queue.shift();
if (event) {
await this.processEvent(event);
}
}
this.processing = false;
}
private async processEvent(event: Event): Promise<void> {
console.log(`Processing event: ${event.type}`, event);
if (this.listeners.has(event.type)) {
const listeners = this.listeners.get(event.type) || [];
for (const listener of listeners) {
try {
await listener(event);
} catch (error) {
console.error(`Error handling event ${event.type}:`, error);
}
}
}
}
subscribe(eventType: string, listener: Function): void {
if (!this.listeners.has(eventType)) {
this.listeners.set(eventType, []);
}
this.listeners.get(eventType)?.push(listener);
}
unsubscribe(eventType: string, listener: Function): void {
if (this.listeners.has(eventType)) {
const listeners = this.listeners.get(eventType)?.filter(l => l !== listener);
this.listeners.set(eventType, listeners || []);
}
}
}
// 全局事件总线
export const eventBus = new EventBus();
```
### 6.2 事件处理器
```typescript
// 订单事件处理器
class OrderEventHandler {
constructor(private inventoryService: InventoryService, private notificationService: NotificationService) {
eventBus.subscribe('OrderCreated', this.handleOrderCreated.bind(this));
eventBus.subscribe('OrderCancelled', this.handleOrderCancelled.bind(this));
}
private async handleOrderCreated(event: Event): Promise<void> {
const order = event.data;
// 扣减库存
for (const item of order.items) {
await this.inventoryService.deductInventory(item.productId, item.quantity);
}
// 发送通知
await this.notificationService.sendOrderConfirmation(order);
}
private async handleOrderCancelled(event: Event): Promise<void> {
const order = event.data;
// 恢复库存
for (const item of order.items) {
await this.inventoryService.restoreInventory(item.productId, item.quantity);
}
// 发送通知
await this.notificationService.sendOrderCancellation(order);
}
}
// 库存事件处理器
class InventoryEventHandler {
constructor(private notificationService: NotificationService) {
eventBus.subscribe('InventoryLow', this.handleInventoryLow.bind(this));
}
private async handleInventoryLow(event: Event): Promise<void> {
const { productId, quantity, alertLevel } = event.data;
// 发送库存预警通知
await this.notificationService.sendInventoryAlert(productId, quantity, alertLevel);
}
}
```
---
## 7. 相关文档
- [Service_Design.md](./Service_Design.md)
- [Data_Consistency.md](./Data_Consistency.md)
- [Observability.md](./Observability.md)
---
*本文档基于服务设计文档,最后更新: 2026-03-18*

View File

@@ -0,0 +1,349 @@
# 可观测性文档 (Crawlful Hub)
> **定位**Crawlful Hub 可观测性设计文档 - 确保系统的可观测性,便于问题排查和系统优化。
> **更新日期**: 2026-03-18
> **最高优先级参考**: [Service_Design.md](./Service_Design.md)
---
## 1. 可观测性概述
### 1.1 定义
可观测性是指通过系统的外部输出(如日志、指标、追踪)来了解系统内部状态的能力。
### 1.2 重要性
良好的可观测性可以:
- 快速定位和解决问题
- 预测和预防系统故障
- 优化系统性能
- 提高系统可靠性
- 降低运维成本
### 1.3 核心组成
- **业务日志**:记录业务操作的详细信息
- **链路追踪**:追踪请求在系统中的完整路径
- **指标监控**:监控系统的各种指标
---
## 2. 业务日志
### 2.1 定义
业务日志是指记录业务操作的详细信息,包括操作人、操作时间、操作类型、操作对象、操作结果等。
### 2.2 实现方法
#### 2.2.1 日志级别
- **DEBUG**:详细的调试信息
- **INFO**:一般的信息
- **WARN**:警告信息
- **ERROR**:错误信息
- **FATAL**:致命错误信息
#### 2.2.2 日志格式
```json
{
"timestamp": "2026-03-18T10:00:00Z",
"level": "INFO",
"service": "ProductService",
"method": "updatePrice",
"traceId": "1234567890",
"tenantId": "tenant-001",
"shopId": "shop-001",
"businessType": "TOC",
"message": "Updating price for product 123 to 99.99",
"data": {
"productId": "123",
"oldPrice": 89.99,
"newPrice": 99.99,
"roi": 1.5
}
}
```
#### 2.2.3 日志框架
**推荐**
- Node.jswinston, bunyan
- Javalog4j, logback
- Pythonlogging, structlog
**示例**
```typescript
// Node.js/winston 示例
import winston from 'winston';
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.json(),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
// 使用
logger.info('Updating price for product', {
productId: '123',
oldPrice: 89.99,
newPrice: 99.99,
traceId: '1234567890',
tenantId: 'tenant-001',
shopId: 'shop-001',
businessType: 'TOC'
});
```
### 2.3 最佳实践
- **结构化日志**:使用 JSON 格式,便于分析和查询
- **统一日志格式**:所有服务使用相同的日志格式
- **包含必要字段**时间戳、级别、服务名、方法名、追踪ID、租户ID、店铺ID、业务类型等
- **适当的日志级别**:根据信息的重要性选择合适的级别
- **日志轮转**:定期轮转日志文件,防止日志文件过大
- **日志存储**:使用 ELK Stack、Splunk 等工具存储和分析日志
---
## 3. 链路追踪
### 3.1 定义
链路追踪是指追踪请求在系统中的完整路径,包括请求经过的所有服务和操作。
### 3.2 实现方法
#### 3.2.1 追踪ID
**定义**:一个唯一的标识符,用于关联同一个请求的所有操作
**实现**
- 生成唯一的 `traceId`
- 在请求开始时创建 `traceId`
- 在所有相关操作中传递 `traceId`
**示例**
```typescript
// 中间件生成 traceId
const traceMiddleware = (req, res, next) => {
const traceId = req.headers['x-trace-id'] || uuidv4();
req.traceId = traceId;
res.setHeader('x-trace-id', traceId);
next();
};
// 使用
app.use(traceMiddleware);
// 在服务中使用
async updatePrice(productId: string, price: number, traceId: string): Promise<Product> {
logger.info('Updating price', { traceId, productId, price });
// 业务逻辑
return product;
}
```
#### 3.2.2 分布式追踪系统
**推荐**
- Jaeger
- Zipkin
- OpenTelemetry
**示例**
```typescript
// 使用 OpenTelemetry
import { trace } from '@opentelemetry/api';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { JaegerExporter } from '@opentelemetry/exporter-jaeger';
// 初始化追踪器
const provider = new NodeTracerProvider();
const exporter = new JaegerExporter({
serviceName: 'product-service'
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();
// 创建 span
const tracer = trace.getTracer('product-service');
async updatePrice(productId: string, price: number): Promise<Product> {
const span = tracer.startSpan('updatePrice');
try {
// 业务逻辑
const product = await this.productRepository.findById(productId);
// 创建子 span
const calculateRoiSpan = tracer.startSpan('calculateROI', {
parent: span
});
const roi = await this.pricingService.calculateROI(product, price);
calculateRoiSpan.end();
product.price = price;
product.roi = roi;
const updatedProduct = await this.productRepository.save(product);
return updatedProduct;
} finally {
span.end();
}
}
```
### 3.3 最佳实践
- **统一的追踪ID**所有服务使用相同的追踪ID格式
- **完整的链路**:追踪请求的完整路径,包括所有服务和操作
- **适当的 span**:为重要操作创建 span
- **添加上下文信息**:在 span 中添加业务相关的上下文信息
- **集成监控系统**:将追踪数据与监控系统集成
---
## 4. 指标监控
### 4.1 定义
指标监控是指监控系统的各种指标,如响应时间、调用次数、错误率等。
### 4.2 实现方法
#### 4.2.1 核心指标
- **响应时间**:请求的处理时间
- **调用次数**:服务的调用次数
- **错误率**:错误请求的比例
- **资源使用**CPU、内存、磁盘、网络等资源的使用情况
- **业务指标**:订单量、销售额、利润率等
#### 4.2.2 监控系统
**推荐**
- Prometheus
- Grafana
- Datadog
- New Relic
**示例**
```typescript
// 使用 Prometheus
import prometheus from 'prom-client';
// 定义指标
const requestCounter = new prometheus.Counter({
name: 'http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'endpoint', 'status']
});
const requestDuration = new prometheus.Histogram({
name: 'http_request_duration_seconds',
help: 'HTTP request duration in seconds',
labelNames: ['method', 'endpoint'],
buckets: [0.1, 0.5, 1, 2, 5]
});
// 中间件
const metricsMiddleware = (req, res, next) => {
const start = process.hrtime();
res.on('finish', () => {
const duration = process.hrtime(start);
const seconds = duration[0] + duration[1] / 1e9;
requestCounter.inc({
method: req.method,
endpoint: req.path,
status: res.statusCode
});
requestDuration.observe({
method: req.method,
endpoint: req.path
}, seconds);
});
next();
};
// 使用
app.use(metricsMiddleware);
app.get('/metrics', (req, res) => {
res.set('Content-Type', prometheus.register.contentType);
res.end(prometheus.register.metrics());
});
```
### 4.3 最佳实践
- **定义关键指标**:根据业务需求定义关键指标
- **设置合理的告警**:为重要指标设置告警
- **可视化**:使用 Grafana 等工具可视化指标
- **定期分析**:定期分析指标数据,发现问题和优化机会
- **集成业务指标**:将业务指标与技术指标结合
---
## 5. 可观测性集成
### 5.1 日志、追踪和指标的关联
- **使用相同的 traceId**:将日志、追踪和指标关联起来
- **统一的上下文**:在所有可观测性数据中包含相同的上下文信息
- **集成平台**:使用 ELK Stack、Grafana 等平台集成所有可观测性数据
### 5.2 监控仪表盘
**推荐仪表盘**
- **系统健康仪表盘**:显示系统的整体健康状态
- **服务性能仪表盘**:显示各个服务的性能指标
- **业务指标仪表盘**:显示业务相关的指标
- **告警仪表盘**:显示当前的告警状态
### 5.3 告警策略
- **设置合理的阈值**:根据业务需求设置合理的告警阈值
- **分级告警**:根据问题的严重程度设置不同级别的告警
- **告警通知**通过邮件、短信、Slack 等渠道发送告警通知
- **告警抑制**:避免告警风暴
---
## 6. 最佳实践
### 6.1 设计原则
- **可观测性优先**:在系统设计阶段就考虑可观测性
- **统一标准**:所有服务使用相同的可观测性标准
- **适度采集**:采集足够的数据,但不过度采集
- **数据保留**:设置合理的数据保留策略
### 6.2 实现建议
- **使用开源工具**:如 ELK Stack、Prometheus、Grafana、Jaeger 等
- **自动化部署**:自动化可观测性工具的部署和配置
- **定期演练**:定期演练故障排查和恢复流程
- **持续优化**:根据实际情况持续优化可观测性方案
---
## 7. 相关文档
- [Service_Design.md](./Service_Design.md)
- [Data_Consistency.md](./Data_Consistency.md)
- [Architecture_Overview.md](./Architecture_Overview.md)
---
*本文档基于服务设计文档,最后更新: 2026-03-18*

View File

@@ -0,0 +1,383 @@
# 权限系统设计文档 (Crawlful Hub)
> **定位**Crawlful Hub 权限系统设计文档 - 定义基于角色的访问控制RBAC和数据级权限。
> **更新日期**: 2026-03-18
> **最高优先级参考**: [Service_Design.md](./Service_Design.md)
---
## 1. 权限系统概述
### 1.1 核心概念
- **角色Role**:一组权限的集合
- **权限Permission**:对资源的操作许可
- **用户User**:系统的使用者
- **资源Resource**:系统中的对象,如商品、订单、用户等
- **数据级权限**:基于数据属性的访问控制
### 1.2 重要性
良好的权限系统可以:
- 保护系统安全
- 确保数据隐私
- 实现职责分离
- 满足合规要求
- 提供可审计性
---
## 2. RBAC 模型
### 2.1 角色定义
| 角色 | 描述 | 权限范围 |
|------|------|----------|
| **ADMIN** | 系统管理员 | 所有资源的所有操作 |
| **MANAGER** | 运营主管 | 大部分资源的管理操作 |
| **OPERATOR** | 运营专员 | 基础运营操作 |
| **FINANCE** | 财务主管 | 财务相关操作 |
| **SOURCING** | 采购专家 | 采购相关操作 |
| **LOGISTICS** | 物流专家 | 物流相关操作 |
| **ANALYST** | 数据分析师 | 数据分析相关操作 |
### 2.2 权限定义
| 权限 | 描述 | 适用资源 |
|------|------|----------|
| **CREATE** | 创建资源 | 所有资源 |
| **READ** | 读取资源 | 所有资源 |
| **UPDATE** | 更新资源 | 所有资源 |
| **DELETE** | 删除资源 | 所有资源 |
| **APPROVE** | 审批操作 | 订单、结算等 |
| **EXPORT** | 导出数据 | 报表、数据等 |
| **IMPORT** | 导入数据 | 商品、用户等 |
### 2.3 权限分配
**示例**
```typescript
// 角色权限映射
const rolePermissions = {
ADMIN: ['*'], // 所有权限
MANAGER: [
'CREATE:product', 'READ:product', 'UPDATE:product', 'DELETE:product',
'CREATE:order', 'READ:order', 'UPDATE:order', 'APPROVE:order',
'READ:report', 'EXPORT:report'
],
OPERATOR: [
'READ:product', 'UPDATE:product',
'READ:order', 'UPDATE:order'
],
FINANCE: [
'READ:order', 'READ:settlement', 'APPROVE:settlement',
'READ:report', 'EXPORT:report'
],
SOURCING: [
'CREATE:product', 'READ:product', 'UPDATE:product',
'READ:supplier', 'CREATE:supplier', 'UPDATE:supplier'
],
LOGISTICS: [
'READ:order', 'UPDATE:order',
'READ:inventory', 'UPDATE:inventory'
],
ANALYST: [
'READ:report', 'EXPORT:report'
]
};
```
---
## 3. 数据级权限
### 3.1 定义
数据级权限是指基于数据属性的访问控制,确保用户只能访问和操作与自己相关的数据。
### 3.2 实现方法
#### 3.2.1 租户隔离
**定义**:不同租户的数据相互隔离
**实现**
- 在所有数据表中添加 `tenantId` 字段
- 在所有查询中默认带上 `tenantId` 过滤
- 确保跨租户操作的安全性
**示例**
```typescript
// 数据访问层
class ProductRepository {
async findAll(tenantId: string, params?: any): Promise<Product[]> {
return await Product.findAll({
where: {
tenantId,
...params
}
});
}
async findById(id: string, tenantId: string): Promise<Product | null> {
return await Product.findOne({
where: {
id,
tenantId
}
});
}
}
```
#### 3.2.2 店铺隔离
**定义**:同一租户下不同店铺的数据相互隔离
**实现**
- 在相关数据表中添加 `shopId` 字段
- 在查询中根据用户的店铺权限过滤
- 确保用户只能访问自己有权限的店铺数据
**示例**
```typescript
// 权限服务
class RBACService {
async checkShopAccess(userId: string, shopId: string): Promise<boolean> {
const user = await this.userRepository.findById(userId);
const userShops = await this.userShopRepository.findByUserId(userId);
return userShops.some(us => us.shopId === shopId) || user.role === 'ADMIN';
}
}
// 订单服务
class OrderService {
async getOrders(userId: string, params?: any): Promise<Order[]> {
const user = await this.userRepository.findById(userId);
if (user.role === 'ADMIN') {
return await this.orderRepository.findAll(params);
}
const userShops = await this.userShopRepository.findByUserId(userId);
const shopIds = userShops.map(us => us.shopId);
return await this.orderRepository.findAll({
...params,
shopId: shopIds
});
}
}
```
#### 3.2.3 字段级权限
**定义**:基于字段的访问控制
**实现**
- 定义字段级权限规则
- 在返回数据时过滤敏感字段
- 确保用户只能看到和修改自己有权限的字段
**示例**
```typescript
// 字段级权限
const fieldPermissions = {
ADMIN: {
product: ['*'], // 所有字段
user: ['*']
},
MANAGER: {
product: ['id', 'name', 'price', 'stock'],
user: ['id', 'name', 'email']
},
OPERATOR: {
product: ['id', 'name', 'price'],
user: ['id', 'name']
}
};
// 数据过滤
function filterFields(data: any, fields: string[]): any {
if (fields.includes('*')) {
return data;
}
const filtered: any = {};
fields.forEach(field => {
if (data[field] !== undefined) {
filtered[field] = data[field];
}
});
return filtered;
}
```
### 3.3 最佳实践
- **默认带租户ID**:所有查询默认带 `tenantId` 过滤
- **权限检查前置**:在业务逻辑开始前检查权限
- **统一权限服务**:使用统一的权限服务处理权限检查
- **缓存权限**:缓存用户权限,提高性能
- **审计日志**:记录权限相关操作的审计日志
---
## 4. 权限验证
### 4.1 实现方法
#### 4.1.1 中间件验证
**适用场景**API 路由权限验证
**实现**
- 创建权限验证中间件
- 在路由中应用中间件
- 验证用户是否有权限访问资源
**示例**
```typescript
// 权限中间件
const authorize = (requiredPermission: string) => {
return (req, res, next) => {
const user = req.user;
if (!user) {
return res.status(401).json({ error: 'Unauthorized' });
}
if (!user.permissions.includes(requiredPermission) && user.role !== 'ADMIN') {
return res.status(403).json({ error: 'Forbidden' });
}
next();
};
};
// 使用
app.get('/products', authorize('READ:product'), productController.getProducts);
app.post('/products', authorize('CREATE:product'), productController.createProduct);
```
#### 4.1.2 服务层验证
**适用场景**:业务逻辑权限验证
**实现**
- 在服务层检查权限
- 验证用户是否有权限操作资源
- 验证用户是否有权限访问数据
**示例**
```typescript
async updateProduct(productId: string, updates: Partial<Product>, userId: string): Promise<Product> {
// 检查操作权限
if (!this.rbacService.hasPermission(userId, 'UPDATE:product')) {
throw new ForbiddenException('You do not have permission to update products');
}
// 获取商品
const product = await this.productRepository.findById(productId);
if (!product) {
throw new NotFoundException('Product not found');
}
// 检查数据权限
if (!this.rbacService.hasDataAccess(userId, product.tenantId, product.shopId)) {
throw new ForbiddenException('You do not have access to this product');
}
// 更新商品
Object.assign(product, updates);
return await this.productRepository.save(product);
}
```
### 4.2 最佳实践
- **多层验证**:在中间件和服务层都进行权限验证
- **明确的错误信息**:返回清晰的权限错误信息
- **权限缓存**:缓存用户权限,提高验证性能
- **定期权限检查**:定期检查权限配置的正确性
---
## 5. 权限管理
### 5.1 角色管理
- **创建角色**:定义新角色
- **修改角色**:修改角色的权限
- **删除角色**:删除不需要的角色
- **分配角色**:为用户分配角色
### 5.2 权限管理
- **定义权限**:定义新的权限
- **分配权限**:为角色分配权限
- **回收权限**:从角色中回收权限
### 5.3 用户管理
- **创建用户**:创建新用户并分配角色
- **修改用户**:修改用户的角色和权限
- **删除用户**:删除用户
- **禁用用户**:暂时禁用用户
---
## 6. 安全考虑
### 6.1 防止权限提升
- **最小权限原则**:用户只获得必要的权限
- **权限审计**:定期审计权限配置
- **权限边界**:明确权限的边界
### 6.2 防止数据泄露
- **数据加密**:加密敏感数据
- **访问控制**:严格控制数据访问
- **审计日志**:记录数据访问日志
### 6.3 防止暴力破解
- **密码策略**:强密码要求
- **登录限制**:限制登录尝试次数
- **验证码**:使用验证码防止暴力破解
---
## 7. 测试策略
### 7.1 单元测试
- 测试权限验证逻辑
- 测试角色权限映射
- 测试数据级权限过滤
### 7.2 集成测试
- 测试完整的权限流程
- 测试不同角色的访问控制
- 测试数据级权限的有效性
### 7.3 安全测试
- 测试权限提升攻击
- 测试数据泄露风险
- 测试暴力破解防护
---
## 8. 相关文档
- [Service_Design.md](./Service_Design.md)
- [Data_Consistency.md](./Data_Consistency.md)
- [API_Specs](./API_Specs/)
---
*本文档基于服务设计文档,最后更新: 2026-03-18*

View File

@@ -0,0 +1,433 @@
# 服务设计文档 (Crawlful Hub)
> **定位**Crawlful Hub 后端服务设计文档 - 定义服务层架构、服务职责和实现规范。
> **更新日期**: 2026-03-18
> **最高优先级参考**: [Business_ClosedLoops.md](../00_Business/Business_ClosedLoops.md)
---
## 1. 服务层架构
### 1.1 核心原则
- **每个业务操作对应一个 Service**:前端的每个用户操作都必须有对应的后端 Service 处理
- **服务编排**:通过 Service 层串联多个模块,实现业务流程的完整执行
- **单一职责**:每个 Service 只负责一个核心业务领域
- **依赖注入**:通过依赖注入实现服务间的解耦
- **事务管理**:重要操作必须在事务中执行,确保数据一致性
### 1.2 服务层级结构
```
Controller → Service (核心编排) → Repository / External API → 数据库/外部系统
```
---
## 2. 核心服务列表
### 2.1 商品服务 (ProductService)
**职责**:管理商品全生命周期,包括创建、更新、查询、删除等操作
**核心方法**
- `createProduct()`: 创建商品
- `updateProduct()`: 更新商品信息
- `updatePrice()`: 更新商品价格,同时计算 ROI
- `getProductById()`: 根据 ID 获取商品详情
- `getProducts()`: 获取商品列表
- `deleteProduct()`: 删除商品
- `publishProduct()`: 发布商品到平台
- `unpublishProduct()`: 从平台下架商品
**依赖**
- `PricingService`: 计算价格和 ROI
- `InventoryService`: 管理商品库存
- `MediaService`: 管理商品媒体资源
### 2.2 订单服务 (OrderService)
**职责**:管理订单全生命周期,包括创建、更新、查询、处理等操作
**核心方法**
- `createOrder()`: 创建订单
- `updateOrderStatus()`: 更新订单状态
- `getOrderById()`: 根据 ID 获取订单详情
- `getOrders()`: 获取订单列表
- `processOrder()`: 处理订单(包括库存扣减、物流安排等)
- `splitOrder()`: 拆分订单
- `mergeOrders()`: 合并订单
- `handleExceptionOrder()`: 处理异常订单
**依赖**
- `InventoryService`: 管理库存
- `LogisticsService`: 安排物流
- `SettlementService`: 处理结算
### 2.3 定价服务 (PricingService)
**职责**:负责商品定价和利润计算
**核心方法**
- `calculatePrice()`: 计算商品价格
- `calculateROI()`: 计算投资回报率
- `calculateProfit()`: 计算利润
- `getPricingStrategy()`: 获取定价策略
- `updatePricingStrategy()`: 更新定价策略
**依赖**
- `CostService`: 计算成本
- `MarketService`: 分析市场价格
### 2.4 库存服务 (InventoryService)
**职责**:管理库存,包括库存查询、扣减、预警等
**核心方法**
- `getInventory()`: 获取库存信息
- `updateInventory()`: 更新库存
- `deductInventory()`: 扣减库存
- `reserveInventory()`: 预留库存
- `releaseInventory()`: 释放预留库存
- `getInventoryAlert()`: 获取库存预警
**依赖**
- `WarehouseService`: 管理仓库
### 2.5 物流服务 (LogisticsService)
**职责**:管理物流,包括物流选择、追踪、费用计算等
**核心方法**
- `selectLogisticsChannel()`: 选择物流渠道
- `calculateFreight()`: 计算运费
- `trackLogistics()`: 追踪物流状态
- `createShippingLabel()`: 创建 shipping label
**依赖**
- `ThirdPartyLogisticsAPI`: 对接第三方物流 API
### 2.6 结算服务 (SettlementService)
**职责**:管理结算,包括收入计算、佣金扣除、打款等
**核心方法**
- `calculateSettlement()`: 计算结算金额
- `processSettlement()`: 处理结算
- `createSettlementBill()`: 创建结算账单
- `processPayment()`: 处理付款
**依赖**
- `FinanceService`: 财务管理
- `PaymentService`: 支付处理
### 2.7 商户服务 (MerchantService)
**职责**:管理商户,包括商户注册、认证、管理等
**核心方法**
- `registerMerchant()`: 注册商户
- `verifyMerchant()`: 验证商户资质
- `getMerchantById()`: 获取商户详情
- `updateMerchant()`: 更新商户信息
- `suspendMerchant()`: 暂停商户
- `activateMerchant()`: 激活商户
**依赖**
- `VerificationService`: 资质验证
- `RBACService`: 权限管理
### 2.8 权限服务 (RBACService)
**职责**:管理权限,包括角色定义、权限分配等
**核心方法**
- `createRole()`: 创建角色
- `assignPermission()`: 分配权限
- `checkPermission()`: 检查权限
- `getUserRoles()`: 获取用户角色
**依赖**
- `UserService`: 用户管理
### 2.9 数据服务 (DataPipelineService)
**职责**:管理数据采集、清洗、处理等
**核心方法**
- `collectData()`: 采集数据
- `cleanData()`: 清洗数据
- `processData()`: 处理数据
- `analyzeData()`: 分析数据
**依赖**
- `PlatformApiService`: 对接平台 API
- `CrawlerService`: 网页爬虫
### 2.10 AI 服务 (AIService)
**职责**:提供 AI 相关功能,如智能定价、智能分析等
**核心方法**
- `predictPrice()`: 预测价格
- `analyzeMarket()`: 分析市场
- `optimizeStrategy()`: 优化策略
- `detectAnomaly()`: 检测异常
**依赖**
- `MachineLearningModel`: 机器学习模型
---
## 3. 服务间调用规范
### 3.1 同步调用
**适用场景**:需要立即获取结果的操作
**示例**
```typescript
// ProductService 调用 PricingService
async updatePrice(productId: string, price: number): Promise<Product> {
const product = await this.productRepository.findById(productId);
const roi = await this.pricingService.calculateROI(product, price);
product.price = price;
product.roi = roi;
return await this.productRepository.save(product);
}
```
### 3.2 异步调用
**适用场景**:不需要立即获取结果的操作,如发送通知、数据处理等
**示例**
```typescript
// OrderService 调用 NotificationService
async processOrder(orderId: string): Promise<void> {
const order = await this.orderRepository.findById(orderId);
// 处理订单
await this.orderRepository.save(order);
// 异步发送通知
this.notificationService.sendOrderConfirmation(order).catch(err => {
this.logger.error('Failed to send order confirmation', err);
});
}
```
---
## 4. 事务管理
### 4.1 事务边界
**定义**:一组操作要么全部成功,要么全部失败
**示例**
```typescript
@Transactional()
async createOrder(orderData: OrderCreateDto): Promise<Order> {
// 1. 创建订单
const order = await this.orderRepository.create(orderData);
// 2. 扣减库存
await this.inventoryService.deductInventory(
orderData.productId,
orderData.quantity
);
// 3. 记录交易
await this.transactionRepository.create({
orderId: order.id,
amount: order.totalAmount,
type: 'ORDER_CREATED'
});
return order;
}
```
### 4.2 幂等性
**定义**:同一个请求执行多次,结果应该相同
**实现**
- 使用唯一的 `requestId`
- 记录已处理的请求
- 检查重复请求
**示例**
```typescript
async processPayment(paymentData: PaymentDto): Promise<Payment> {
// 检查是否已处理
const existingPayment = await this.paymentRepository.findByRequestId(paymentData.requestId);
if (existingPayment) {
return existingPayment;
}
// 处理支付
const payment = await this.paymentRepository.create(paymentData);
return payment;
}
```
---
## 5. 错误处理
### 5.1 业务错误
**定义**:业务逻辑错误,如库存不足、权限不足等
**处理**
- 抛出业务异常
- 上层捕获并返回适当的错误信息
**示例**
```typescript
async deductInventory(productId: string, quantity: number): Promise<void> {
const inventory = await this.inventoryRepository.findByProductId(productId);
if (inventory.quantity < quantity) {
throw new BusinessException('Insufficient inventory');
}
inventory.quantity -= quantity;
await this.inventoryRepository.save(inventory);
}
```
### 5.2 系统错误
**定义**系统级错误如数据库连接失败、API 调用失败等
**处理**
- 捕获系统异常
- 记录错误日志
- 尝试重试或降级策略
- 向上层返回适当的错误信息
**示例**
```typescript
async callExternalApi(endpoint: string, data: any): Promise<any> {
try {
const response = await this.httpClient.post(endpoint, data);
return response.data;
} catch (error) {
this.logger.error(`Failed to call external API: ${endpoint}`, error);
throw new SystemException('External API error');
}
}
```
---
## 6. 日志和监控
### 6.1 业务日志
**定义**:记录业务操作的日志
**内容**
- 操作人
- 操作时间
- 操作类型
- 操作对象
- 操作结果
**示例**
```typescript
async updatePrice(productId: string, price: number): Promise<Product> {
this.logger.info(`Updating price for product ${productId} to ${price}`);
try {
const product = await this.productRepository.findById(productId);
const roi = await this.pricingService.calculateROI(product, price);
product.price = price;
product.roi = roi;
const updatedProduct = await this.productRepository.save(product);
this.logger.info(`Successfully updated price for product ${productId}`, {
oldPrice: product.oldPrice,
newPrice: price,
roi: roi
});
return updatedProduct;
} catch (error) {
this.logger.error(`Failed to update price for product ${productId}`, error);
throw error;
}
}
```
### 6.2 性能监控
**定义**:监控服务性能
**指标**
- 响应时间
- 调用次数
- 错误率
- 资源使用情况
**实现**
- 使用 Prometheus 等监控工具
- 定期分析性能数据
- 优化性能瓶颈
---
## 7. 服务版本管理
### 7.1 版本控制
**定义**:管理服务的版本
**策略**
- 使用语义化版本号
- 向后兼容
- 版本迁移计划
### 7.2 API 版本控制
**定义**:管理 API 的版本
**实现**
- 在 URL 中包含版本号
- 支持多个版本并存
- 逐步废弃旧版本
---
## 8. 部署和扩展性
### 8.1 部署策略
**定义**:服务的部署方式
**选项**
- 单体应用
- 微服务
- 容器化部署
### 8.2 扩展性
**定义**:服务的扩展能力
**实现**
- 水平扩展
- 负载均衡
- 缓存策略
- 异步处理
---
## 9. 相关文档
- [API_Specs](./API_Specs/)
- [Database_Design](./Database_Design.md)
- [Architecture_Overview](./Architecture_Overview.md)
---
*本文档基于业务闭环设计,最后更新: 2026-03-18*