Back to Prompt Optimizer

技术实现详解

docs/archives/122-docker-api-proxy/implementation.md

2.10.26.6 KB
Original Source

技术实现详解

🔧 架构设计

整体架构

前端应用 → nginx (80) → Node Proxy (3001) → 外部LLM API

设计理念

基于Docker受信环境假设,采用简化优先的设计原则:

  • 重点关注功能实现而非复杂安全防护
  • 避免nginx动态代理的复杂性
  • 零依赖实现,提高可维护性

架构优势

  • ✅ 避免nginx动态代理的DNS解析问题
  • ✅ 配置简单,易于维护
  • ✅ 适合Docker容器的受信环境
  • ✅ 职责清晰:nginx负责转发,Node.js负责代理逻辑

🐛 问题诊断与解决

核心技术挑战

1. nginx动态代理复杂性

问题:nginx动态代理需要复杂的DNS解析和变量处理 解决方案:采用nginx本地转发 + Node.js代理的简化架构

nginx
location /api/proxy {
    proxy_pass http://127.0.0.1:3001;
    proxy_http_version 1.1;
}

2. 流式响应透传

问题:SSE流式响应需要实时透传,不能缓冲 解决方案

  • nginx配置:proxy_buffering offX-Accel-Buffering no
  • Node.js实现:使用Readable.fromWeb()正确处理流

3. CORS头重复设置

问题:nginx和Node.js同时设置CORS头导致重复 解决方案:统一由Node.js处理CORS,nginx不设置

4. 超时策略优化

问题:LLM流式请求可能需要很长时间,统一超时不合理 解决方案:差异化超时策略

  • 流式请求:5分钟超时
  • 普通请求:2分钟超时
  • 支持环境变量配置

📝 实施步骤

阶段1:基础代理功能实现

  1. 创建Node.js代理服务

    • 零依赖实现,只使用内置模块
    • 支持所有HTTP方法
    • 基础错误处理
  2. 配置nginx转发

    • 添加/api/proxy/api/stream路径
    • 本地转发到127.0.0.1:3001
    • 基础CORS配置
  3. Docker集成

    • 修改supervisord.conf添加node-proxy进程
    • 环境变量配置支持

阶段2:流式代理和UI集成

  1. 流式响应优化

    • nginx流式配置优化
    • Node.js使用Readable.fromWeb()处理流
    • 流式超时策略
  2. 前端UI集成

    • 环境检测逻辑
    • ModelManager.vue添加Docker代理选项
    • 国际化文本支持
  3. 数据持久化

    • ModelConfig接口添加useDockerProxy
    • 配置保存和加载逻辑

阶段3:错误处理与体验优化

  1. 增强错误处理

    • 智能错误分类:超时504、连接错误502、格式错误400
    • 用户友好错误消息
    • 请求追踪系统
  2. LLM服务集成

    • OpenAI服务添加Docker代理支持
    • Gemini服务添加Docker代理支持
    • 类型定义完善
  3. 端到端验证

    • 功能测试:基础代理、错误处理、流式响应
    • 性能测试:响应时间、内存使用、并发处理
    • 集成测试:前端UI、LLM服务、构建系统

🔍 调试过程

调试工具组合

  • Nginx access_log:记录/api/*专用日志
  • Node Proxy日志:详细的请求处理日志
  • 浏览器网络面板:前端请求状态检查

关键调试点

  1. CORS问题:确保只有Node.js设置CORS头
  2. 流式响应:检查nginx缓冲配置和Node.js流处理
  3. 超时处理:验证不同类型请求的超时策略
  4. 错误分类:确保错误码和消息的正确性

🧪 测试验证

功能测试用例

javascript
// 基础代理测试
GET /api/proxy?url=https://httpbin.org/get
期望:200状态码,正确的JSON响应

// 错误处理测试
GET /api/proxy?url=https://nonexistent-domain.com
期望:502状态码,友好错误消息

// 流式响应测试
GET /api/stream?url=https://httpbin.org/stream/5
期望:实时流式数据,无缓冲延迟

性能测试指标

  • 响应时间:6-7秒(httpbin.org正常延迟)
  • 内存使用:稳定,无内存泄漏
  • 并发处理:支持多个同时请求
  • 资源清理:定时器正确清理

集成测试验证

  • 前端UI:代理选项正确显示和保存
  • LLM服务:Docker代理配置正确传递
  • 构建系统:Core和UI包构建成功
  • 类型检查:TypeScript检查通过

🔧 核心代码实现

Node.js代理服务核心逻辑

javascript
// 零依赖实现,只使用内置模块
const http = require('http');
const { Readable } = require('stream');

// 流式响应处理
if (upstreamRes.headers['content-type']?.includes('text/event-stream')) {
    const stream = Readable.fromWeb(upstreamRes.body);
    stream.pipe(res);
}

// 智能错误处理
const handleError = (error, res, requestId) => {
    if (error.code === 'ENOTFOUND') {
        return sendError(res, 502, 'DNS resolution failed', requestId);
    }
    if (error.code === 'ECONNREFUSED') {
        return sendError(res, 502, 'Connection refused', requestId);
    }
    return sendError(res, 500, 'Internal server error', requestId);
};

nginx配置核心部分

nginx
# 基础代理配置
location /api/proxy {
    proxy_pass http://127.0.0.1:3001;
    proxy_http_version 1.1;
}

# 流式响应配置
location /api/stream {
    proxy_pass http://127.0.0.1:3001;
    proxy_buffering off;
    proxy_request_buffering off;
    add_header X-Accel-Buffering no always;
}

前端环境检测

typescript
export const checkDockerApiAvailability = async (): Promise<boolean> => {
    try {
        const response = await fetch('/api/docker-status');
        return response.ok;
    } catch {
        return false;
    }
};

📊 性能优化

关键优化点

  1. 流式透传:nginx关闭缓冲,Node.js使用Readable.fromWeb()
  2. 超时策略:差异化超时,流式5分钟,普通2分钟
  3. 错误处理:快速失败,避免长时间等待
  4. 资源清理:及时清理定时器和连接

监控指标

  • 请求追踪:唯一请求ID
  • 性能日志:响应时间、状态码、错误率
  • 资源使用:内存、CPU、连接数

🔒 安全考虑

当前安全措施

  • 受信环境假设:基于Docker容器的受信环境
  • 基础CORS配置:允许跨域访问
  • 错误信息过滤:避免泄露敏感信息

可选安全增强

  • URL白名单:限制可访问的目标域名
  • 请求频率限制:防止滥用
  • 请求大小限制:防止大文件攻击

🎯 技术亮点

  1. 零依赖实现:提高安全性和可维护性
  2. 架构简洁:避免复杂的nginx动态代理配置
  3. 流式透传:正确处理SSE流式响应
  4. 智能错误处理:用户友好的错误分类和消息
  5. 完整集成:前端UI、LLM服务、类型定义全面支持

这个实现为Docker部署环境提供了完整、可靠、易维护的API代理解决方案。