API集成最佳实践:专业的接入之道

正确的API集成方式不仅能提升应用性能,还能降低成本、提高可靠性。 本指南将分享经过实践验证的集成模式和技巧。

集成架构设计

分层架构模式

// 1. API抽象层
interface LLMProvider {
  chat(messages: Message[]): Promise<Response>;
  complete(prompt: string): Promise<string>;
  embed(text: string): Promise<number[]>;
}

// 2. 提供商实现
class OpenAIProvider implements LLMProvider {
  private client: OpenAI;
  private config: ProviderConfig;
  
  constructor(config: ProviderConfig) {
    this.config = config;
    this.client = new OpenAI({
      apiKey: config.apiKey,
      maxRetries: config.maxRetries || 3,
    });
  }
  
  async chat(messages: Message[]): Promise<Response> {
    try {
      const response = await this.client.chat.completions.create({
        model: this.config.model || 'gpt-3.5-turbo',
        messages: messages,
        temperature: this.config.temperature || 0.7,
        stream: this.config.stream || false,
      });
      
      return this.formatResponse(response);
    } catch (error) {
      throw this.handleError(error);
    }
  }
  
  private handleError(error: any): Error {
    if (error.status === 429) {
      return new RateLimitError('Rate limit exceeded', error);
    }
    if (error.status === 401) {
      return new AuthenticationError('Invalid API key', error);
    }
    return new APIError('API request failed', error);
  }
}

// 3. 服务层
class LLMService {
  private providers: Map<string, LLMProvider>;
  private cache: CacheManager;
  private metrics: MetricsCollector;
  
  constructor() {
    this.providers = new Map();
    this.cache = new CacheManager();
    this.metrics = new MetricsCollector();
  }
  
  addProvider(name: string, provider: LLMProvider) {
    this.providers.set(name, provider);
  }
  
  async chat(
    providerName: string, 
    messages: Message[], 
    options?: ChatOptions
  ): Promise<Response> {
    const provider = this.providers.get(providerName);
    if (!provider) {
      throw new Error(`Provider ${providerName} not found`);
    }
    
    // 缓存检查
    const cacheKey = this.generateCacheKey(messages);
    const cached = await this.cache.get(cacheKey);
    if (cached && options?.useCache) {
      this.metrics.recordCacheHit();
      return cached;
    }
    
    // 调用API
    const startTime = Date.now();
    try {
      const response = await provider.chat(messages);
      
      // 记录指标
      this.metrics.recordLatency(Date.now() - startTime);
      this.metrics.recordTokenUsage(response.usage);
      
      // 缓存结果
      if (options?.useCache) {
        await this.cache.set(cacheKey, response, options.cacheTTL);
      }
      
      return response;
    } catch (error) {
      this.metrics.recordError(error);
      throw error;
    }
  }
}

错误处理策略

健壮的错误处理

错误分类处理

class ErrorHandler {
  static handle(error: any): ErrorResponse {
    // 1. API错误
    if (error.response) {
      switch (error.response.status) {
        case 429:
          return {
            retry: true,
            delay: this.getRetryDelay(error),
            message: 'Rate limited'
          };
        case 401:
          return {
            retry: false,
            message: 'Authentication failed'
          };
        case 500:
        case 502:
        case 503:
          return {
            retry: true,
            delay: 1000,
            message: 'Server error'
          };
      }
    }
    
    // 2. 网络错误
    if (error.code === 'ECONNREFUSED') {
      return {
        retry: true,
        delay: 5000,
        message: 'Connection failed'
      };
    }
    
    // 3. 超时错误
    if (error.code === 'ETIMEDOUT') {
      return {
        retry: true,
        delay: 2000,
        message: 'Request timeout'
      };
    }
    
    // 默认处理
    return {
      retry: false,
      message: error.message
    };
  }
  
  static getRetryDelay(error: any): number {
    // 从响应头获取重试时间
    const retryAfter = 
      error.response?.headers['retry-after'];
    
    if (retryAfter) {
      return parseInt(retryAfter) * 1000;
    }
    
    // 指数退避
    const attempt = error.attempt || 1;
    return Math.min(
      Math.pow(2, attempt) * 1000,
      30000
    );
  }
}

智能重试机制

class RetryManager {
  async execute<T>(
    operation: () => Promise<T>,
    options: RetryOptions = {}
  ): Promise<T> {
    const {
      maxAttempts = 3,
      initialDelay = 1000,
      maxDelay = 30000,
      factor = 2,
      jitter = true
    } = options;
    
    let lastError: any;
    
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        return await operation();
      } catch (error: any) {
        lastError = error;
        error.attempt = attempt;
        
        const errorResponse = 
          ErrorHandler.handle(error);
        
        if (!errorResponse.retry || 
            attempt === maxAttempts) {
          throw error;
        }
        
        // 计算延迟
        let delay = errorResponse.delay || 
          Math.min(
            initialDelay * Math.pow(factor, attempt - 1),
            maxDelay
          );
        
        // 添加抖动
        if (jitter) {
          delay *= 0.5 + Math.random();
        }
        
        console.log(
          `Retry ${attempt}/${maxAttempts} after ${delay}ms`
        );
        
        await this.sleep(delay);
      }
    }
    
    throw lastError;
  }
  
  private sleep(ms: number): Promise<void> {
    return new Promise(resolve => 
      setTimeout(resolve, ms)
    );
  }
}

流式响应处理

高效的流处理

// 流式响应处理器
class StreamHandler {
  async *handleStream(
    stream: ReadableStream,
    options: StreamOptions = {}
  ): AsyncGenerator<StreamChunk> {
    const reader = stream.getReader();
    const decoder = new TextDecoder();
    let buffer = '';
    
    try {
      while (true) {
        const { done, value } = await reader.read();
        
        if (done) {
          // 处理剩余数据
          if (buffer) {
            yield this.parseChunk(buffer);
          }
          break;
        }
        
        // 解码数据
        buffer += decoder.decode(value, { stream: true });
        
        // 按行分割
        const lines = buffer.split('\n');
        buffer = lines.pop() || '';
        
        for (const line of lines) {
          if (line.trim() === '') continue;
          
          if (line.startsWith('data: ')) {
            const data = line.slice(6);
            
            if (data === '[DONE]') {
              return;
            }
            
            try {
              const chunk = JSON.parse(data);
              
              // 处理数据
              const processed = await this.processChunk(chunk);
              
              // 发送处理后的数据
              yield processed;
              
              // 回调处理
              if (options.onChunk) {
                options.onChunk(processed);
              }
            } catch (error) {
              console.error('Failed to parse chunk:', error);
              
              if (options.onError) {
                options.onError(error);
              }
            }
          }
        }
      }
    } finally {
      reader.releaseLock();
    }
  }
  
  private processChunk(chunk: any): StreamChunk {
    return {
      id: chunk.id,
      content: chunk.choices?.[0]?.delta?.content || '',
      role: chunk.choices?.[0]?.delta?.role,
      finishReason: chunk.choices?.[0]?.finish_reason,
      usage: chunk.usage
    };
  }
  
  // 流聚合器
  async aggregateStream(
    stream: AsyncGenerator<StreamChunk>
  ): Promise<CompleteResponse> {
    let content = '';
    let role = '';
    let usage = null;
    
    for await (const chunk of stream) {
      if (chunk.content) {
        content += chunk.content;
      }
      if (chunk.role) {
        role = chunk.role;
      }
      if (chunk.usage) {
        usage = chunk.usage;
      }
    }
    
    return {
      content,
      role,
      usage
    };
  }
}

// 使用示例
const streamHandler = new StreamHandler();

// React组件中使用
function ChatComponent() {
  const [response, setResponse] = useState('');
  
  const handleStream = async (prompt: string) => {
    const stream = await api.createChatStream(prompt);
    
    for await (const chunk of streamHandler.handleStream(stream, {
      onChunk: (chunk) => {
        setResponse(prev => prev + chunk.content);
      },
      onError: (error) => {
        console.error('Stream error:', error);
      }
    })) {
      // 可以在这里做额外处理
    }
  };
}

性能优化技巧

提升API调用性能

🚀 连接池优化

// HTTP Agent配置
const https = require('https');
const http = require('http');

const httpsAgent = new https.Agent({
  keepAlive: true,
  keepAliveMsecs: 1000,
  maxSockets: 50,
  maxFreeSockets: 10,
  timeout: 60000,
  scheduling: 'lifo'
});

const httpAgent = new http.Agent({
  keepAlive: true,
  keepAliveMsecs: 1000,
  maxSockets: 50,
  maxFreeSockets: 10,
  timeout: 60000
});

// Axios配置
const apiClient = axios.create({
  httpsAgent,
  httpAgent,
  timeout: 30000,
  maxRedirects: 0,
  decompress: true,
  responseType: 'stream'
});

// 请求拦截器
apiClient.interceptors.request.use(
  config => {
    config.headers['Connection'] = 'keep-alive';
    config.headers['Accept-Encoding'] = 'gzip, deflate';
    return config;
  }
);

💾 智能缓存策略

class SmartCache {
  private cache: Map<string, CacheEntry>;
  private lru: string[];
  private maxSize: number;
  
  constructor(maxSize = 1000) {
    this.cache = new Map();
    this.lru = [];
    this.maxSize = maxSize;
  }
  
  async get(
    key: string,
    factory: () => Promise<any>,
    options: CacheOptions = {}
  ): Promise<any> {
    // 检查缓存
    const entry = this.cache.get(key);
    
    if (entry && !this.isExpired(entry)) {
      this.updateLRU(key);
      return entry.value;
    }
    
    // 生成新值
    const value = await factory();
    
    // 存储到缓存
    this.set(key, value, options.ttl || 3600000);
    
    return value;
  }
  
  private set(key: string, value: any, ttl: number) {
    // 检查容量
    if (this.cache.size >= this.maxSize) {
      this.evict();
    }
    
    this.cache.set(key, {
      value,
      expiry: Date.now() + ttl
    });
    
    this.updateLRU(key);
  }
  
  private evict() {
    // LRU淘汰
    const leastUsed = this.lru.shift();
    if (leastUsed) {
      this.cache.delete(leastUsed);
    }
  }
  
  private updateLRU(key: string) {
    const index = this.lru.indexOf(key);
    if (index > -1) {
      this.lru.splice(index, 1);
    }
    this.lru.push(key);
  }
  
  private isExpired(entry: CacheEntry): boolean {
    return Date.now() > entry.expiry;
  }
}

成本控制策略

精细化成本管理

Token优化

class TokenOptimizer {
  // 压缩Prompt
  compressPrompt(text: string): string {
    return text
      // 移除多余空白
      .replace(/\s+/g, ' ')
      // 移除重复标点
      .replace(/([.!?])\1+/g, '$1')
      // 精简格式
      .trim();
  }
  
  // 智能截断
  truncateToLimit(
    text: string, 
    maxTokens: number,
    model: string = 'gpt-3.5-turbo'
  ): string {
    const encoder = this.getEncoder(model);
    const tokens = encoder.encode(text);
    
    if (tokens.length <= maxTokens) {
      return text;
    }
    
    // 保留重要部分
    const importance = this.calculateImportance(text);
    const truncated = this.smartTruncate(
      text, 
      maxTokens, 
      importance
    );
    
    return truncated;
  }
  
  // 批量优化
  optimizeBatch(messages: Message[]): Message[] {
    // 去重
    const unique = this.deduplicateMessages(messages);
    
    // 合并相似
    const merged = this.mergeSimilar(unique);
    
    // 压缩内容
    return merged.map(msg => ({
      ...msg,
      content: this.compressPrompt(msg.content)
    }));
  }
}

使用量监控

class UsageMonitor {
  private usage: Map<string, UserUsage>;
  private limits: Map<string, UsageLimit>;
  
  async trackUsage(
    userId: string,
    tokens: number,
    cost: number
  ): Promise<void> {
    const usage = this.getOrCreateUsage(userId);
    
    // 更新使用量
    usage.tokens += tokens;
    usage.cost += cost;
    usage.requests += 1;
    
    // 检查限制
    await this.checkLimits(userId, usage);
    
    // 发送告警
    if (usage.cost > usage.budget * 0.8) {
      await this.sendBudgetAlert(userId, usage);
    }
  }
  
  async checkLimits(
    userId: string, 
    usage: UserUsage
  ): Promise<void> {
    const limits = this.limits.get(userId);
    if (!limits) return;
    
    if (usage.tokens > limits.maxTokens) {
      throw new Error('Token limit exceeded');
    }
    
    if (usage.cost > limits.maxCost) {
      throw new Error('Cost limit exceeded');
    }
    
    if (usage.requests > limits.maxRequests) {
      throw new Error('Request limit exceeded');
    }
  }
  
  generateReport(userId: string): UsageReport {
    const usage = this.usage.get(userId);
    if (!usage) return null;
    
    return {
      period: this.getCurrentPeriod(),
      totalTokens: usage.tokens,
      totalCost: usage.cost,
      totalRequests: usage.requests,
      avgTokensPerRequest: usage.tokens / usage.requests,
      avgCostPerRequest: usage.cost / usage.requests,
      topModels: this.getTopModels(usage),
      recommendations: this.getRecommendations(usage)
    };
  }
}

安全最佳实践

API安全防护

🔐 密钥管理

// 安全的密钥管理
class SecureKeyManager {
  private keys: Map<string, EncryptedKey>;
  private vault: KeyVault;
  
  constructor() {
    this.keys = new Map();
    this.vault = new KeyVault(process.env.VAULT_URL);
  }
  
  async getKey(keyName: string): Promise<string> {
    // 1. 检查内存缓存
    const cached = this.keys.get(keyName);
    if (cached && !this.isExpired(cached)) {
      return this.decrypt(cached);
    }
    
    // 2. 从密钥库获取
    const key = await this.vault.getSecret(keyName);
    
    // 3. 缓存加密的密钥
    this.keys.set(keyName, {
      value: this.encrypt(key),
      expiry: Date.now() + 3600000 // 1小时
    });
    
    return key;
  }
  
  // 密钥轮换
  async rotateKey(keyName: string): Promise<void> {
    // 生成新密钥
    const newKey = this.generateKey();
    
    // 更新密钥库
    await this.vault.updateSecret(keyName, newKey);
    
    // 清除缓存
    this.keys.delete(keyName);
    
    // 通知相关服务
    await this.notifyKeyRotation(keyName);
  }
  
  // 审计日志
  async logKeyAccess(keyName: string, userId: string) {
    await this.vault.audit({
      action: 'KEY_ACCESS',
      keyName,
      userId,
      timestamp: new Date(),
      ip: this.getClientIP()
    });
  }
}

🛡️ 输入验证

class InputValidator {
  static validateChatInput(input: ChatInput): void {
    // 1. 长度检查
    if (input.message.length > 4000) {
      throw new ValidationError('Message too long');
    }
    
    // 2. 内容过滤
    if (this.containsMalicious(input.message)) {
      throw new ValidationError('Malicious content detected');
    }
    
    // 3. 注入检测
    if (this.detectInjection(input.message)) {
      throw new ValidationError('Injection attempt detected');
    }
    
    // 4. 编码检查
    if (!this.isValidUTF8(input.message)) {
      throw new ValidationError('Invalid encoding');
    }
  }
  
  private static containsMalicious(text: string): boolean {
    const patterns = [
      /system\s*:/i,
      /ignore\s+previous/i,
      /<script[^>]*>/i,
      /\x00/
    ];
    
    return patterns.some(pattern => pattern.test(text));
  }
  
  private static detectInjection(text: string): boolean {
    // Prompt注入检测
    const injectionPatterns = [
      'forget all previous',
      'disregard instructions',
      'new system prompt'
    ];
    
    const lowercased = text.toLowerCase();
    return injectionPatterns.some(pattern => 
      lowercased.includes(pattern)
    );
  }
}

监控与可观测性

全方位监控体系

// 集成监控系统
class ObservabilitySystem {
  private metrics: MetricsClient;
  private traces: TracingClient;
  private logs: LoggingClient;
  
  constructor() {
    this.metrics = new PrometheusClient();
    this.traces = new JaegerClient();
    this.logs = new ElasticsearchClient();
  }
  
  // 请求追踪
  async traceRequest(
    operation: string,
    fn: () => Promise<any>
  ): Promise<any> {
    const span = this.traces.startSpan(operation);
    const requestId = generateRequestId();
    
    try {
      // 设置追踪上下文
      span.setTag('request.id', requestId);
      span.setTag('user.id', getCurrentUserId());
      
      // 记录开始
      this.logs.info('Request started', {
        requestId,
        operation,
        timestamp: new Date()
      });
      
      // 执行操作
      const startTime = Date.now();
      const result = await fn();
      const duration = Date.now() - startTime;
      
      // 记录指标
      this.metrics.histogram('api_request_duration', duration, {
        operation,
        status: 'success'
      });
      
      // 记录成功
      span.setTag('response.status', 'success');
      span.finish();
      
      return result;
    } catch (error) {
      // 记录错误
      span.setTag('error', true);
      span.log({
        event: 'error',
        message: error.message,
        stack: error.stack
      });
      
      // 错误指标
      this.metrics.increment('api_request_errors', {
        operation,
        error_type: error.constructor.name
      });
      
      // 错误日志
      this.logs.error('Request failed', {
        requestId,
        operation,
        error: {
          message: error.message,
          stack: error.stack
        }
      });
      
      span.finish();
      throw error;
    }
  }
  
  // 自定义指标
  recordCustomMetric(name: string, value: number, tags?: any) {
    this.metrics.gauge(name, value, tags);
  }
  
  // 健康检查
  async healthCheck(): Promise<HealthStatus> {
    const checks = await Promise.all([
      this.checkAPIHealth(),
      this.checkDatabaseHealth(),
      this.checkCacheHealth()
    ]);
    
    const allHealthy = checks.every(c => c.healthy);
    
    return {
      status: allHealthy ? 'healthy' : 'unhealthy',
      checks,
      timestamp: new Date()
    };
  }
}

打造专业的API集成

遵循最佳实践,构建高效、可靠、安全的大模型应用。

开始集成