跨境电商系统错误处理策略
在跨境电商系统中,错误处理是保障系统稳定性和用户体验的关键环节。本文将分享跨境电商系统中错误处理的最佳实践和策略。
错误分类与处理原则
跨境电商系统中的错误可以分为以下几类:
- API集成错误:与第三方平台API交互时的错误
- 系统内部错误:系统组件内部发生的异常
- 业务逻辑错误:业务规则验证失败产生的错误
- 网络与基础设施错误:网络连接、服务器故障等
针对不同类型的错误,我们需要采用不同的处理策略,但总体原则是:
- 优雅降级:核心功能不可用时提供备选方案
- 透明可见:错误应当被记录并可被监控系统捕获
- 用户友好:向最终用户展示有意义的错误信息
- 自动恢复:尽可能实现系统的自动恢复
API错误处理策略
1. 统一错误码映射
将各平台的错误码映射为统一的内部错误码:
// 错误码映射配置
const ERROR_CODE_MAPPING = {
// Amazon错误码映射
'amazon': {
'QuotaExceeded': 'API_RATE_LIMIT_EXCEEDED',
'Unauthorized': 'AUTHENTICATION_ERROR',
'ResourceNotFound': 'RESOURCE_NOT_FOUND',
// ...其他错误码
},
// eBay错误码映射
'ebay': {
'18000': 'API_RATE_LIMIT_EXCEEDED',
'931': 'AUTHENTICATION_ERROR',
'11001': 'RESOURCE_NOT_FOUND',
// ...其他错误码
},
// ...其他平台
};
// 错误码映射函数
function mapErrorCode(platform: string, originalCode: string): string {
const platformMapping = ERROR_CODE_MAPPING[platform.toLowerCase()];
if (!platformMapping) {
return 'UNKNOWN_ERROR';
}
return platformMapping[originalCode] || 'UNKNOWN_ERROR';
}
2. 智能重试策略
根据错误类型实施不同的重试策略:
class RetryStrategy {
// 根据错误类型确定是否应该重试
shouldRetry(error: ApiError): boolean {
// 这些错误类型可以重试
const retryableErrors = [
'API_RATE_LIMIT_EXCEEDED',
'TEMPORARY_ERROR',
'SERVICE_UNAVAILABLE',
'GATEWAY_ERROR',
'NETWORK_ERROR'
];
return retryableErrors.includes(error.code);
}
// 计算重试延迟时间
calculateDelay(attempt: number, error: ApiError): number {
// 基础延迟时间(毫秒)
const baseDelay = 1000;
// 指数退避策略
let delay = baseDelay * Math.pow(2, attempt);
// 添加随机抖动,避免多个请求同时重试
delay = delay * (0.5 + Math.random() * 0.5);
// 根据错误类型调整延迟
if (error.code === 'API_RATE_LIMIT_EXCEEDED') {
// 限流错误使用更长的延迟
delay = Math.max(delay, error.retryAfter || 5000);
}
// 设置最大延迟上限
return Math.min(delay, 60000);
}
// 执行带重试的操作
async executeWithRetry<T>(
operation: () => Promise<T>,
maxRetries: number = 3
): Promise<T> {
let attempt = 0;
let lastError: ApiError | null = null;
while (attempt <= maxRetries) {
try {
return await operation();
} catch (error) {
lastError = this.normalizeError(error);
// 检查是否应该重试
if (!this.shouldRetry(lastError) || attempt >= maxRetries) {
throw lastError;
}
// 计算延迟时间
const delay = this.calculateDelay(attempt, lastError);
// 记录重试信息
console.log(`Retrying operation after ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);
// 等待后重试
await this.sleep(delay);
attempt++;
}
}
throw lastError;
}
// 辅助方法
private normalizeError(error: any): ApiError {
// 将各种错误格式标准化为ApiError
// ...
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
3. 断路器模式
实现断路器模式,防止级联故障:
class CircuitBreaker {
private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED';
private failureCount: number = 0;
private lastFailureTime: number = 0;
private readonly failureThreshold: number;
private readonly resetTimeout: number;
constructor(failureThreshold: number = 5, resetTimeout: number = 30000) {
this.failureThreshold = failureThreshold;
this.resetTimeout = resetTimeout;
}
async execute<T>(operation: () => Promise<T>): Promise<T> {
// 检查断路器状态
if (this.state === 'OPEN') {
// 检查是否应该进入半开状态
if (Date.now() - this.lastFailureTime >= this.resetTimeout) {
this.state = 'HALF_OPEN';
} else {
throw new Error('Circuit breaker is open');
}
}
try {
const result = await operation();
// 操作成功,重置断路器
this.reset();
return result;
} catch (error) {
// 记录失败
this.recordFailure();
// 检查是否应该打开断路器
if (this.state === 'HALF_OPEN' || this.failureCount >= this.failureThreshold) {
this.state = 'OPEN';
this.lastFailureTime = Date.now();
}
throw error;
}
}
private reset(): void {
this.failureCount = 0;
this.state = 'CLOSED';
}
private recordFailure(): void {
this.failureCount++;
}
}
系统内部错误处理
1. 结构化错误日志
采用结构化日志格式,便于分析和监控:
interface ErrorLogEntry {
timestamp: string;
errorId: string;
level: 'ERROR' | 'WARNING' | 'CRITICAL';
service: string;
component: string;
message: string;
code: string;
stackTrace?: string;
context?: Record<string, any>;
userId?: string;
requestId?: string;
}
class ErrorLogger {
log(error: Error, context: Partial<ErrorLogEntry> = {}): void {
const entry: ErrorLogEntry = {
timestamp: new Date().toISOString(),
errorId: this.generateErrorId(),
level: context.level || 'ERROR',
service: context.service || 'unknown',
component: context.component || 'unknown',
message: error.message,
code: this.extractErrorCode(error),
stackTrace: error.stack,
...context
};
// 输出到日志系统
console.error(JSON.stringify(entry));
// 对于严重错误,触发告警
if (entry.level === 'CRITICAL') {
this.triggerAlert(entry);
}
}
// 辅助方法
private generateErrorId(): string {
return Math.random().toString(36).substring(2, 15);
}
private extractErrorCode(error: any): string {
return error.code || 'UNKNOWN_ERROR';
}
private triggerAlert(entry: ErrorLogEntry): void {
// 实现告警逻辑
// ...
}
}
2. 全局错误处理中间件
在API层实现全局错误处理中间件:
// Express错误处理中间件示例
function errorHandlerMiddleware(
err: any,
req: Request,
res: Response,
next: NextFunction
): void {
// 标准化错误
const normalizedError = normalizeError(err);
// 记录错误
errorLogger.log(normalizedError, {
service: 'api-gateway',
component: req.path,
requestId: req.headers['x-request-id'] as string,
userId: req.user?.id
});
// 构造错误响应
const errorResponse = {
error: {
code: normalizedError.code,
message: getClientErrorMessage(normalizedError),
requestId: req.headers['x-request-id']
}
};
// 设置HTTP状态码
const statusCode = getHttpStatusCode(normalizedError);
// 发送响应
res.status(statusCode).json(errorResponse);
}
// 获取适合展示给客户端的错误信息
function getClientErrorMessage(error: NormalizedError): string {
// 生产环境不暴露内部错误细节
if (process.env.NODE_ENV === 'production' && error.isInternal) {
return '系统处理请求时遇到问题,请稍后再试';
}
return error.clientMessage || error.message;
}
// 根据错误类型确定HTTP状态码
function getHttpStatusCode(error: NormalizedError): number {
const statusCodeMap: Record<string, number> = {
'VALIDATION_ERROR': 400,
'AUTHENTICATION_ERROR': 401,
'AUTHORIZATION_ERROR': 403,
'RESOURCE_NOT_FOUND': 404,
'RATE_LIMIT_EXCEEDED': 429,
'INTERNAL_ERROR': 500,
'SERVICE_UNAVAILABLE': 503
};
return statusCodeMap[error.code] || 500;
}
业务错误处理
1. 领域特定错误类型
定义领域特定的错误类型,提高代码可读性:
// 基础错误类
class DomainError extends Error {
constructor(message: string) {
super(message);
this.name = this.constructor.name;
}
}
// 订单领域错误
class OrderNotFoundError extends DomainError {
constructor(orderId: string) {
super(`Order with ID ${orderId} not found`);
}
}
class InsufficientInventoryError extends DomainError {
constructor(productId: string, requested: number, available: number) {
super(`Insufficient inventory for product ${productId}: requested ${requested}, available ${available}`);
}
}
// 支付领域错误
class PaymentFailedError extends DomainError {
constructor(reason: string) {
super(`Payment failed: ${reason}`);
}
}
// 使用示例
function processOrder(orderId: string): void {
const order = orderRepository.findById(orderId);
if (!order) {
throw new OrderNotFoundError(orderId);
}
// 处理订单...
}
2. 错误恢复策略
实现业务级错误恢复策略:
class OrderProcessor {
async processOrder(orderId: string): Promise<void> {
try {
// 尝试处理订单
await this.doProcessOrder(orderId);
} catch (error) {
// 根据错误类型执行恢复策略
if (error instanceof PaymentFailedError) {
await this.handlePaymentFailure(orderId, error);
} else if (error instanceof InventoryAllocationError) {
await this.handleInventoryFailure(orderId, error);
} else {
// 无法恢复的错误
await this.markOrderAsFailed(orderId, error);
throw error;
}
}
}
private async handlePaymentFailure(orderId: string, error: PaymentFailedError): Promise<void> {
// 记录支付失败
await this.logOrderEvent(orderId, 'PAYMENT_FAILED', error.message);
// 检查重试次数
const retryCount = await this.getPaymentRetryCount(orderId);
if (retryCount < 3) {
// 安排稍后重试支付
await this.schedulePaymentRetry(orderId, retryCount + 1);
} else {
// 超过重试次数,通知客户
await this.notifyCustomerAboutPaymentIssue(orderId);
await this.markOrderAsPaymentFailed(orderId);
}
}
private async handleInventoryFailure(orderId: string, error: InventoryAllocationError): Promise<void> {
// 记录库存分配失败
await this.logOrderEvent(orderId, 'INVENTORY_ALLOCATION_FAILED', error.message);
// 尝试从其他仓库分配库存
const allocated = await this.tryAlternativeInventoryAllocation(orderId);
if (!allocated) {
// 无法分配库存,通知客户
await this.notifyCustomerAboutInventoryIssue(orderId);
await this.markOrderAsBackordered(orderId);
}
}
// 其他辅助方法...
}
监控与告警
错误处理系统需要与监控系统集成:
class ErrorMonitor {
// 记录错误指标
recordErrorMetrics(error: NormalizedError): void {
const tags = {
service: error.service,
component: error.component,
code: error.code,
environment: process.env.NODE_ENV
};
// 增加错误计数
metrics.increment('errors.count', 1, tags);
// 记录错误响应时间
if (error.duration) {
metrics.histogram('errors.duration', error.duration, tags);
}
}
// 检查错误模式
detectErrorPatterns(): void {
// 实现错误模式检测算法
// 例如:短时间内同类错误突增
// ...
}
// 生成错误报告
generateErrorReport(timeRange: TimeRange): ErrorReport {
// 聚合错误数据,生成报告
// ...
}
}
案例分析:订单系统错误处理优化
我们对某跨境电商客户的订单系统错误处理进行了优化,取得了显著成效:
- 系统可用性从99.9%提升到99.99%
- 订单处理失败率从2%降至0.2%
- 错误恢复时间从平均30分钟降至5分钟
结论
完善的错误处理策略是构建稳定、可靠的跨境电商系统的关键。通过实施统一错误码映射、智能重试策略、断路器模式、结构化错误日志和业务级错误恢复策略,我们可以显著提升系统的稳定性和用户体验。
在未来的文章中,我们将深入探讨特定业务场景下的错误处理最佳实践,如订单处理、支付集成等。