refactor(server): 重构服务层代码结构 feat(server): 添加基础设施、跨境电商、AI决策等核心服务 docs: 完善前端业务说明书和开发进度文档 style: 格式化代码和文档
8.9 KiB
8.9 KiB
可观测性文档 (Crawlful Hub)
定位:Crawlful Hub 可观测性设计文档 - 确保系统的可观测性,便于问题排查和系统优化。 更新日期: 2026-03-18 最高优先级参考: 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 日志格式
{
"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.js:winston, bunyan
- Java:log4j, logback
- Python:logging, structlog
示例:
// 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
示例:
// 中间件生成 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
示例:
// 使用 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
示例:
// 使用 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. 相关文档
本文档基于服务设计文档,最后更新: 2026-03-18