Files
NexusAI/docs/02-软件设计文档-SDD.md
ericwyuan 8017f691a1 fix(部署): One-API 管理端口改为局域网直连,SSH 隧道方案不可行
- 发现 NAS sshd 关闭了 AllowTcpForwarding,SSH -L 隧道会报 administratively prohibited,此前文档里的隧道方案实际不可用
- one-api 端口绑定改为 192.168.50.64:3001(NAS 局域网 IP),不再绑定 127.0.0.1;仍不接入 frp、不暴露公网,只是访问方式从"SSH隧道转发"改为"同局域网直连"
- 已在 NAS 上应用并验证 http://192.168.50.64:3001 可正常访问(HTTP 200)
- 同步修正 README/PROGRESS/SDD 中的管理端口访问说明
2026-08-23 09:02:54 +08:00

18 KiB
Raw Permalink Blame History

软件设计说明书SDD

自建多模态 AI 网关系统AI Gateway System

项目 内容
文档版本 V1.0
编写日期 2026-08-23
对应需求文档 01-软件需求文档-SRS.md V1.0

1. 设计概述

1.1 设计目标

在满足 SRS 中全部功能需求与非功能需求的前提下,采用成熟开源组件 + 容器化编排的方式快速搭建系统,降低自研成本,优先保证 Failover 可靠性与部署可维护性。

1.2 设计原则

  • 不重复造轮子网关、前端均采用成熟开源方案One-API + LobeChat仅做配置层工作
  • 松耦合:前端、网关、各 AI 渠道之间通过标准 OpenAI 兼容接口通信,任一组件可替换
  • 配置驱动:渠道增删、优先级调整通过后台界面完成,不需改代码重新部署
  • 最小暴露面:仅前端端口对公网开放,管理端口和数据库端口仅内网可访问

2. 系统架构设计

2.1 总体架构图

┌───────────────────────────────────────────────────────────────┐
│                      公司内网(用户侧)                          │
│                    浏览器 / 移动端浏览器                         │
└──────────────────────────┬────────────────────────────────────┘
                            │ HTTPS (443)
                            ▼
┌───────────────────────────────────────────────────────────────┐
│           甲骨文服务器129.146.203.203,公网反代层)             │
│           frp / nginx 反向代理端口 → NAS对外统一入口          │
└──────────────────────────┬────────────────────────────────────┘
                            │ 反代 / 隧道frp
                            ▼
┌───────────────────────────────────────────────────────────────┐
│                    NAS 本机Docker 宿主机)                     │
│                                                                 │
│  ┌─────────────────────────────────────────────────────────┐  │
│  │  Nginx反向代理层                                        │  │
│  │  - HTTPS 终止 / 证书管理                                    │  │
│  │  - 请求转发至 LobeChat                                      │  │
│  │  - 流式响应透传proxy_buffering off                       │  │
│  └───────────────────────┬─────────────────────────────────┘  │
│                           ▼                                    │
│  ┌─────────────────────────────────────────────────────────┐  │
│  │  LobeChat前端应用层  端口 3210                           │  │
│  │  - 对话界面渲染                                             │  │
│  │  - 图片上传处理                                             │  │
│  │  - Access Code 鉴权                                        │  │
│  │  - 对话历史管理IndexedDB / PostgreSQL                    │  │
│  └───────────────────────┬─────────────────────────────────┘  │
│                           │ OpenAI 兼容协议                      │
│                           ▼                                    │
│  ┌─────────────────────────────────────────────────────────┐  │
│  │  One-API网关聚合层  端口 3000仅内网                    │  │
│  │  - 渠道管理 / 优先级路由                                     │  │
│  │  - 模型名映射                                               │  │
│  │  - 失败重试 / 自动禁用 / 冷却恢复                             │  │
│  │  - 调用日志 / 用量统计                                       │  │
│  └───────────────────────┬─────────────────────────────────┘  │
│                           │                                    │
│  ┌─────────────────────────────────────────────────────────┐  │
│  │  MySQL网关数据存储                                       │  │
│  │  - 渠道配置表 / Token 表 / 调用日志表                         │  │
│  └─────────────────────────────────────────────────────────┘  │
└──────────────────────────┬────────────────────────────────────┘
                            │ 各家官方 HTTPS API
        ┌───────────┬───────────┬───────────┬───────────┐
        ▼           ▼           ▼           ▼           ▼
     Gemini    NVIDIA NIM     Groq      OpenRouter    Mistral

2.2 分层说明

层级 组件 职责
反代层 甲骨文服务器 frp/nginx 反向代理端口,对外统一访问入口
接入层 Nginx HTTPS 终止、反向代理、访问入口统一NAS 本机)
表现层 LobeChat 用户交互、对话渲染、多模态输入采集
网关层 One-API 协议转换、渠道路由、故障转移、用量统计
数据层 MySQL 网关配置与日志持久化
外部服务层 5 家 AI API 实际推理能力提供方

2.3 部署视图

单机 Docker Compose 部署于 NAS 本机,各服务以容器形式运行在同一 Docker 网络(ai-network)内,服务间通过容器名互相寻址,仅 Nginx 的 80/443 端口对局域网暴露;对外由**甲骨文服务器129.146.203.203**通过 frp/nginx 反向代理该端口,供公司内网公网访问。


3. 模块设计

3.1 Nginx 反向代理模块

职责

  • 在 NAS 本机暴露 443HTTPS与 80HTTP 跳转 443公网访问由甲骨文服务器反向代理到本机 443 端口
  • 将请求转发至 lobe-chat:3210
  • 关闭代理缓冲以支持流式输出SSE

关键配置片段

server {
    listen 443 ssl;
    server_name <domain-or-ip>;

    ssl_certificate     /etc/nginx/certs/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/privkey.pem;

    location / {
        proxy_pass http://lobe-chat:3210;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
        proxy_cache off;
    }
}

server {
    listen 80;
    server_name <domain-or-ip>;
    return 301 https://$host$request_uri;
}

3.2 LobeChat 前端模块

职责

  • 渲染对话界面、处理用户输入(含图片)
  • 通过 OPENAI_PROXY_URL 将请求发送至 One-API而非直连任一具体厂商
  • 校验 ACCESS_CODE 完成访问控制

关键环境变量设计

变量名 说明 示例值
OPENAI_API_KEY 填 One-API 生成的聚合 Token非各厂商原始 Key sk-xxxxx
OPENAI_PROXY_URL 指向 One-API 的 v1 路径 http://one-api:3000/v1
ACCESS_CODE 前端访问密码 自定义
DEFAULT_LANG 默认语言 zh-CN
OPENAI_MODEL_LIST 控制模型下拉菜单显示项 见 3.3 模型映射设计

数据存储:本期采用 Client-SideIndexedDB后续如需多端同步再切换 Server-SidePostgreSQL

3.3 One-API 网关模块

职责

  • 维护渠道Channel配置表Base URL、Key、支持模型、优先级、权重
  • 维护 Token 表:对外暴露给 LobeChat 使用的聚合密钥
  • 请求路由:按优先级+权重选择渠道,失败时按策略重试下一渠道
  • 日志记录:每次请求实际路由渠道、耗时、成功/失败状态

渠道设计表

渠道名 类型 Base URL 优先级 支持视觉
nvidia-nim 自定义(OpenAI兼容) integrate.api.nvidia.com/v1 1 部分模型
gemini Google Gemini generativelanguage.googleapis.com/v1beta 1
openrouter 自定义(OpenAI兼容) openrouter.ai/api/v1 2 部分模型(:free)
groq 自定义(OpenAI兼容) api.groq.com/openai/v1 2 有限
mistral 自定义(OpenAI兼容) api.mistral.ai/v1 3 Pixtral系列

优先级数字越小越优先;同优先级内按权重轮询分摊负载。

模型映射设计

对外统一暴露两个聚合模型名,前端只需感知这两个名字:

对外模型名 用途 关联渠道
auto-vision 图文混合问答 Gemini、NVIDIA(视觉模型)、OpenRouter(视觉模型)、Mistral(Pixtral)
auto-text 纯文本问答 上述全部 + Groq

故障转移策略

  1. 请求到达 One-APIauto-visionauto-text 匹配渠道池
  2. 按优先级从高到低尝试,同优先级内按权重随机/轮询选择
  3. 若渠道返回 429限流/5xx服务错误/超时,标记该渠道本次失败,自动尝试下一渠道
  4. 连续失败次数超过阈值(如 5 次/5 分钟),该渠道进入"冷却禁用"状态,冷却期(如 10 分钟)后自动恢复参与路由
  5. 全部渠道均失败时,向前端返回明确错误提示(而非静默失败)

3.4 MySQL 数据模块

职责:持久化 One-API 的渠道配置、Token、调用日志

核心表设计(概念级,实际以 One-API 内建 schema 为准)

关键字段 说明
channels id, name, base_url, key, priority, weight, models, status 渠道配置
tokens id, key, name, quota, status 对外令牌
logs id, channel_id, model, status_code, latency, created_at 调用日志

4. 接口设计

4.1 前端 ↔ 网关接口

遵循 OpenAI /v1/chat/completions 协议,支持多模态 content 数组格式:

{
  "model": "auto-vision",
  "messages": [
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "这张图片里有什么?" },
        { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,..." } }
      ]
    }
  ],
  "stream": true
}

4.2 网关 ↔ 各 AI 渠道接口

渠道 协议特点 转换要点
Gemini 原生协议与 OpenAI 不同(contents/parts结构) One-API 内建适配器自动转换
NVIDIA NIM OpenAI 兼容 直接透传,仅替换 Base URL 和 Key
Groq OpenAI 兼容 直接透传
OpenRouter OpenAI 兼容 直接透传,模型名需带 :free 后缀
Mistral OpenAI 兼容 直接透传,视觉模型指定 pixtral-*

5. 安全设计

风险点 设计对策
后台管理端口暴露 One-API 的 3000 端口不映射到公网仅容器内网可访问Oracle 反代仅转发前端端口,管理端口走 SSH 隧道或 VPN
API Key 泄露 所有 Key 通过 .env 文件注入容器环境变量,.env 加入 .gitignore,不提交版本库
未授权访问前端 LobeChat ACCESS_CODE 强制校验
传输层安全 Nginx 强制 HTTPSHTTP 请求 301 跳转
公网入口暴露 对外仅暴露甲骨文服务器反代端口NAS 本机不直接暴露公网
密钥被盗用后的止损 One-API 后台可随时吊销/轮换 Token不影响各渠道原始 Key

6. 部署设计

6.1 目录结构

~/ai-gateway/
├── docker-compose.yml
├── .env                    # 敏感变量,不提交版本库
├── nginx.conf
├── certs/                  # HTTPS 证书
├── one-api-data/           # One-API 持久化数据
└── mysql-data/             # MySQL 持久化数据

6.2 Docker Compose 设计

version: '3.8'

services:
  one-api:
    image: justsong/one-api:latest
    container_name: one-api
    restart: always
    ports:
      - "3000:3000"   # 建议后续改为仅内网映射
    volumes:
      - ./one-api-data:/data
    environment:
      - SQL_DSN=root:${MYSQL_ROOT_PASSWORD}@tcp(mysql:3306)/oneapi
      - TZ=Asia/Shanghai
    depends_on:
      - mysql
    networks:
      - ai-network

  mysql:
    image: mysql:8.0
    container_name: one-api-mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=oneapi
    volumes:
      - ./mysql-data:/var/lib/mysql
    networks:
      - ai-network

  lobe-chat:
    image: lobehub/lobe-chat:latest
    container_name: lobe-chat
    restart: always
    ports:
      - "3210:3210"
    environment:
      - OPENAI_API_KEY=${ONE_API_TOKEN}
      - OPENAI_PROXY_URL=http://one-api:3000/v1
      - ACCESS_CODE=${LOBE_ACCESS_CODE}
      - DEFAULT_LANG=zh-CN
    depends_on:
      - one-api
    networks:
      - ai-network

  nginx:
    image: nginx:alpine
    container_name: nginx-proxy
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      - lobe-chat
    networks:
      - ai-network

networks:
  ai-network:
    driver: bridge

6.3 部署步骤

  1. NAS 安装 Docker + Docker ComposeContainerManager
  2. 按 6.1 结构创建目录,放置 docker-compose.yml.envnginx.conf
  3. 申请 HTTPS 证书Let's Encrypt/certbot放入 certs/
  4. 执行 docker-compose up -d 启动全部服务
  5. 访问 http://<NAS-IP>:3000 完成 One-API 初始化(设置管理员密码)
  6. 后台按 3.3 节渠道设计表逐个添加渠道,设置优先级
  7. 创建对外 Token写入 .envONE_API_TOKEN
  8. docker-compose restart lobe-chat 使配置生效
  9. 在甲骨文服务器配置 frp或 nginx 反代)将公网端口转发至 NAS 的 Nginx 443 端口
  10. 访问 https://<域名>(经甲骨文反代)验证前端可正常对话、上传图片、触发 Failover

6.4 运维监控设计

监控项 方式
渠道可用性 One-API 后台"渠道"页面查看状态与最近调用日志
免费额度消耗 各厂商官方控制台 + One-API 用量统计页面双重核对
容器健康状态 docker-compose ps / 可选接入 Prometheus+Grafana后续扩展
证书到期提醒 certbot 自动续期 + 到期前邮件提醒(后续扩展)

7. 设计与需求追溯表

SRS 需求编号 对应设计章节
FR-1 统一对话界面 3.2 LobeChat 前端模块
FR-2 多渠道聚合与路由 3.3 One-API 网关模块
FR-3 多模态能力 3.3 模型映射设计
FR-4 渠道管理 3.3 / 3.4
FR-5 安全与访问控制 第 5 章 安全设计
非功能-可用性 3.3 故障转移策略
非功能-可维护性 6.4 运维监控设计

8. 待确认事项2026-08-23 更新:已实际部署,多数事项已给出默认结论)

  1. 是否需要 Server-Side 模式支持多端对话同步 默认结论:本期保持 Client-SideIndexedDB不额外部署 PostgreSQL仅单用户/单浏览器使用,暂无多端同步需求。如后续需要,再单独排期
  2. 后台管理端口是否需要通过 VPN/SSH 隧道访问 已实施2026-08-23 修正)NAS sshd 关闭了 AllowTcpForwardingSSH 隧道方案实测不可行;改为 One-API 绑定 NAS 局域网 IP 192.168.50.64:3001,不接入 frp 隧道、不映射公网,同局域网内浏览器直接访问 http://192.168.50.64:3001
  3. 是否需要接入 Prometheus/Grafana 默认结论:本期不接入,沿用 SDD 6.4 既定的轻量监控(docker compose ps + One-API 后台渠道页面);用量不大,暂不需要额外可视化监控栈
  4. 域名与证书:尚未有正式域名,当前用临时自签名证书certs/fullchain.pem/privkey.pemCN=nexusai.local跑通链路浏览器会提示"不安全"但功能不受影响;若紫川后续购买/已有域名,替换证书为 Let's Encrypt 即可,无需改动其他组件——此项仍待紫川决定是否购买域名
  5. NAS 到各海外 API 官方域名的直连稳定性验证 已完成2026-08-23:五渠道 TCP/TLS 握手均 2 秒内完成NAS 出站直连稳定,无需额外代理
  6. 甲骨文反代方式确认 已完成2026-08-23:采用 frp 隧道(与 FAM 项目一致),复用 Oracle 上已运行的 frpsNAS frpc.toml 新增 nexusai 代理remotePort 3210(专属端口,非默认 443与 gitea:3000/wordpress:8500/fam-core:8000 同一约定)→ NAS 8443对外访问地址为 https://129.146.203.203:3210