最佳实践

优化性能、安全性和可靠性的专业建议

API密钥安全

保护您的API密钥

  • 永远不要在客户端代码或公共代码库中暴露API密钥
  • 使用环境变量存储API密钥
  • 为不同环境(开发、测试、生产)使用不同的API密钥
  • 定期轮换API密钥
  • 如果密钥泄露,立即删除并创建新密钥

环境变量配置

# .env 文件
AOXSI_API_KEY=your_api_key_here
AOXSI_API_URL=https://api.aoxsi.com

# 不要将 .env 文件提交到版本控制
# 添加到 .gitignore
echo ".env" >> .gitignore

服务器端代理

对于Web应用,通过服务器端代理调用API:

// 客户端调用您的服务器
fetch('/api/translate', {
  method: 'POST',
  body: JSON.stringify({ text: 'Hello' })
});

// 服务器端代理到Aoxsi API
app.post('/api/translate', async (req, res) => {
  const response = await fetch('https://api.aoxsi.com/api/ai/translate', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.AOXSI_API_KEY}`
    },
    body: JSON.stringify(req.body)
  });
  res.json(await response.json());
});
错误处理

实现健壮的错误处理

async function callApiWithErrorHandling(endpoint, data) {
  try {
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    });

    if (!response.ok) {
      const error = await response.json();
      
      // 根据错误码处理
      switch (error.error.code) {
        case 'E1001':
          throw new Error('余额不足,请充值');
        case 'E1004':
          throw new Error('API密钥无效');
        case 'E5001':
          throw new Error('服务暂时不可用,请稍后重试');
        default:
          throw new Error(`API错误: ${error.error.message}`);
      }
    }

    return await response.json();
  } catch (error) {
    console.error('API调用失败:', error);
    throw error;
  }
}

重试策略

对于临时性错误,实现指数退避重试:

async function retryWithBackoff(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      // 不重试的错误类型
      if (error.code === 'E1004' || error.code === 'E1001') {
        throw error;
      }
      
      if (i === maxRetries - 1) {
        throw error;
      }
      
      // 指数退避: 1s, 2s, 4s
      const delay = Math.pow(2, i) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
性能优化

缓存策略

对于重复的请求,使用缓存可以显著提高性能并降低成本:

// 使用Redis缓存
const redis = require('redis');
const client = redis.createClient();

async function translateWithCache(text, sourceLang, targetLang) {
  const cacheKey = `translate:${sourceLang}:${targetLang}:${text}`;
  
  // 尝试从缓存获取
  const cached = await client.get(cacheKey);
  if (cached) {
    return JSON.parse(cached);
  }
  
  // 调用API
  const result = await translateText(text, sourceLang, targetLang);
  
  // 缓存结果(24小时)
  await client.setex(cacheKey, 86400, JSON.stringify(result));
  
  return result;
}

批量处理

合并多个请求以减少网络开销:

// 批量翻译
async function batchTranslate(texts, sourceLang, targetLang) {
  // 使用Promise.all并行处理
  const results = await Promise.all(
    texts.map(text => 
      translateText(text, sourceLang, targetLang)
    )
  );
  return results;
}

// 使用批处理队列
class BatchQueue {
  constructor(batchSize = 10, delay = 100) {
    this.queue = [];
    this.batchSize = batchSize;
    this.delay = delay;
  }

  async add(item) {
    this.queue.push(item);
    
    if (this.queue.length >= this.batchSize) {
      await this.flush();
    } else {
      this.scheduleFlush();
    }
  }

  scheduleFlush() {
    if (this.timer) return;
    this.timer = setTimeout(() => this.flush(), this.delay);
  }

  async flush() {
    if (this.timer) {
      clearTimeout(this.timer);
      this.timer = null;
    }
    
    const batch = this.queue.splice(0, this.batchSize);
    if (batch.length > 0) {
      await this.processBatch(batch);
    }
  }

  async processBatch(batch) {
    // 处理批量请求
    const results = await batchTranslate(
      batch.map(item => item.text),
      batch[0].sourceLang,
      batch[0].targetLang
    );
    
    // 返回结果给各个请求
    batch.forEach((item, index) => {
      item.resolve(results[index]);
    });
  }
}

连接池

复用HTTP连接以提高性能:

const http = require('http');
const https = require('https');

// 创建连接池
const agent = new https.Agent({
  keepAlive: true,
  maxSockets: 50,
  maxFreeSockets: 10,
  timeout: 60000
});

// 使用连接池
const response = await fetch(url, {
  agent: agent,
  // ... 其他选项
});
速率限制管理

实现客户端速率限制

class RateLimiter {
  constructor(maxRequests, timeWindow) {
    this.maxRequests = maxRequests; // 最大请求数
    this.timeWindow = timeWindow;   // 时间窗口(毫秒)
    this.requests = [];
  }

  async acquire() {
    const now = Date.now();
    
    // 清理过期的请求记录
    this.requests = this.requests.filter(
      time => now - time < this.timeWindow
    );
    
    // 检查是否超过限制
    if (this.requests.length >= this.maxRequests) {
      const oldestRequest = this.requests[0];
      const waitTime = this.timeWindow - (now - oldestRequest);
      await new Promise(resolve => setTimeout(resolve, waitTime));
      return this.acquire();
    }
    
    this.requests.push(now);
  }
}

// 使用示例
const limiter = new RateLimiter(60, 60000); // 每分钟60次

async function callApiWithRateLimit(data) {
  await limiter.acquire();
  return await callApi(data);
}

监控速率限制

async function callApiWithMonitoring(data) {
  const response = await fetch(url, options);
  
  // 检查速率限制头
  const limit = response.headers.get('X-RateLimit-Limit');
  const remaining = response.headers.get('X-RateLimit-Remaining');
  const reset = response.headers.get('X-RateLimit-Reset');
  
  console.log(`速率限制: ${remaining}/${limit}`);
  
  // 如果接近限制,减慢请求速度
  if (remaining < limit * 0.1) {
    console.warn('接近速率限制,减慢请求速度');
    await new Promise(resolve => setTimeout(resolve, 1000));
  }
  
  return await response.json();
}
监控和日志

结构化日志

const logger = {
  info: (message, meta = {}) => {
    console.log(JSON.stringify({
      level: 'info',
      timestamp: new Date().toISOString(),
      message,
      ...meta
    }));
  },
  error: (message, error, meta = {}) => {
    console.error(JSON.stringify({
      level: 'error',
      timestamp: new Date().toISOString(),
      message,
      error: {
        message: error.message,
        stack: error.stack
      },
      ...meta
    }));
  }
};

// 使用示例
async function translateWithLogging(text, sourceLang, targetLang) {
  const startTime = Date.now();
  
  try {
    logger.info('开始翻译', {
      textLength: text.length,
      sourceLang,
      targetLang
    });
    
    const result = await translateText(text, sourceLang, targetLang);
    
    logger.info('翻译成功', {
      duration: Date.now() - startTime,
      resultLength: result.length
    });
    
    return result;
  } catch (error) {
    logger.error('翻译失败', error, {
      duration: Date.now() - startTime,
      textLength: text.length
    });
    throw error;
  }
}

性能监控

class PerformanceMonitor {
  constructor() {
    this.metrics = {
      totalRequests: 0,
      successfulRequests: 0,
      failedRequests: 0,
      totalDuration: 0,
      errors: {}
    };
  }

  recordRequest(duration, success, errorCode = null) {
    this.metrics.totalRequests++;
    this.metrics.totalDuration += duration;
    
    if (success) {
      this.metrics.successfulRequests++;
    } else {
      this.metrics.failedRequests++;
      this.metrics.errors[errorCode] = 
        (this.metrics.errors[errorCode] || 0) + 1;
    }
  }

  getStats() {
    return {
      totalRequests: this.metrics.totalRequests,
      successRate: this.metrics.successfulRequests / 
                   this.metrics.totalRequests,
      averageDuration: this.metrics.totalDuration / 
                       this.metrics.totalRequests,
      errors: this.metrics.errors
    };
  }
}

const monitor = new PerformanceMonitor();

async function monitoredApiCall(fn) {
  const startTime = Date.now();
  try {
    const result = await fn();
    monitor.recordRequest(Date.now() - startTime, true);
    return result;
  } catch (error) {
    monitor.recordRequest(Date.now() - startTime, false, error.code);
    throw error;
  }
}
成本优化

优化建议

  • 使用缓存减少重复请求
  • 批量处理多个请求
  • 只请求需要的数据
  • 实现请求去重
  • 监控使用量,设置预算警报
  • 定期审查API调用模式

请求去重

class RequestDeduplicator {
  constructor() {
    this.pending = new Map();
  }

  async deduplicate(key, fn) {
    // 如果相同请求正在进行,等待结果
    if (this.pending.has(key)) {
      return await this.pending.get(key);
    }

    // 创建新请求
    const promise = fn().finally(() => {
      this.pending.delete(key);
    });

    this.pending.set(key, promise);
    return await promise;
  }
}

const deduplicator = new RequestDeduplicator();

async function translateWithDedup(text, sourceLang, targetLang) {
  const key = `${text}:${sourceLang}:${targetLang}`;
  return await deduplicator.deduplicate(
    key,
    () => translateText(text, sourceLang, targetLang)
  );
}
测试策略

单元测试

// 使用Jest进行单元测试
const { translateText } = require('./api');

// Mock API调用
jest.mock('./api', () => ({
  translateText: jest.fn()
}));

describe('Translation Service', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  test('should translate text successfully', async () => {
    translateText.mockResolvedValue('你好');
    
    const result = await translateText('Hello', 'english', 'chinese');
    
    expect(result).toBe('你好');
    expect(translateText).toHaveBeenCalledWith('Hello', 'english', 'chinese');
  });

  test('should handle errors', async () => {
    translateText.mockRejectedValue(new Error('API Error'));
    
    await expect(
      translateText('Hello', 'english', 'chinese')
    ).rejects.toThrow('API Error');
  });
});

集成测试

// 使用真实API进行集成测试
describe('API Integration Tests', () => {
  // 使用测试环境的API密钥
  const TEST_API_KEY = process.env.TEST_API_KEY;

  test('should call real API successfully', async () => {
    const result = await translateText(
      'Hello',
      'english',
      'chinese'
    );
    
    expect(result).toBeTruthy();
    expect(typeof result).toBe('string');
  }, 10000); // 增加超时时间
});
生产环境清单

在部署到生产环境之前,确保完成以下检查:

  • API密钥使用环境变量存储
  • 实现了错误处理和重试机制
  • 配置了适当的超时时间
  • 实现了速率限制管理
  • 添加了日志和监控
  • 使用缓存优化性能
  • 设置了使用量警报
  • 通过了集成测试
  • 准备了故障恢复计划
  • 文档化了API集成