自建 LLM API 网关:架构与运维
用 Docker 部署自建 LLM API 网关,配置多供应商通道、作用域密钥、使用日志与 OpenAI 兼容端点。
自建 LLM API 网关是你在自有网络或云账户中运行的软件:它接受 OpenAI 兼容请求,认证调用方,把流量路由到一个或多个上游模型供应商,并为运维与成本控制记录用量。与纯反向代理不同,它是控制面:密钥、模型别名、通道凭证、配额与请求历史都靠近请求路径。本文说明何时值得自建、可从本仓库这类 Go 网关期望何种架构,以及如何运维它,而不把模型访问变成无人负责的黑盒。
如果仍在薄转发层与控制面之间选择,请先阅读 LLM 代理与 AI 网关。本文假定你已经需要网关职责,并希望获得一个可部署的基线。
何时自建是正确默认
至少满足以下两条时,自建网关:
- 供应商 API Key 不能分发给每个应用环境
- 多个产品或团队在不同预算下共享模型访问
- 需要落在自有留存边界内的请求级日志
- 数据路径或采购规则更倾向你运维的基础设施
- 希望在不重写客户端的情况下做多供应商路由
- SaaS 网关约束(数据驻留、网络出口、变更控制)不合适
当单一原型只用一把密钥、一个模型且无审计要求时,自建是错误默认。那时直接调用供应商或使用薄代理,直到控制面需求出现。
参考架构
Clients (apps, agents, eval jobs)
|
| HTTPS + Bearer gateway key
v
Self-hosted AI gateway
- OpenAI-compatible API (/v1/chat/completions, /v1/responses, ...)
- Admin API for users, tokens, channels
- Usage logs, dashboard, pricing context
|
+--> Channel: OpenAI
+--> Channel: Anthropic / Claude (native Messages adaptation)
+--> Channel: Gemini
+--> Channel: Azure / Bedrock / others
|
v
Your datastore (SQLite / MySQL / PostgreSQL)
optional Redis for cache and rate limiting
客户端继续使用 OpenAI SDK 或原始 HTTP。上游多样性是配置,不是每个供应商一个新 SDK。这与 兼容 OpenAI 的 API 网关 的价值主张相同,额外要求是你拥有可用性与备份。
本仓库形态网关通常包含什么
本项目是可自建的 Go 网关与 AI 资产管理式系统。规划时重要的仓库可见能力:
- 聊天及相关表面的 OpenAI 兼容中继端点
- 多供应商通道配置
- 用于作用域访问的用户/令牌管理
- 使用日志与运维看板
- 与服务一起嵌入的 Web 管理 UI
- 简单部署用 SQLite;耐用多用户生产用 MySQL 或 PostgreSQL
- 使用已发布镜像
calciumion/new-api的 Docker 部署路径
不要编造合规认证或未声明的 SLA。在向干系人承诺前,对照你运行版本的 UI 与 API 验证确切功能集。
已验证的最小 Docker 路径
仓库提供真实的 docker-compose.yml,使用 PostgreSQL 和 Redis 运行网关。这是多用户预发环境的推荐起点。项目 README 中的快速路径:
docker pull calciumion/new-api:latest
# from a checkout that includes docker-compose.yml
docker compose up -d
# gateway listens on http://localhost:3000 by default
核心服务形态如下,内容从仓库 compose 文件中缩减;Redis/Postgres 服务、健康检查和注释仍应保留完整文件:
services:
new-api:
image: calciumion/new-api:latest
container_name: new-api
restart: always
command: --log-dir /app/logs
ports:
- "3000:3000"
volumes:
- ./data:/data
- ./logs:/app/logs
environment:
# Change passwords before any shared or production use.
- SQL_DSN=postgresql://root:123456@postgres:5432/new-api
- REDIS_CONN_STRING=redis://:123456@redis:6379
- TZ=Asia/Shanghai
- ERROR_LOG_ENABLED=true
- BATCH_UPDATE_ENABLED=true
- NODE_NAME=new-api-node-1
depends_on:
- redis
- postgres
以下运维说明使示例保持诚实:
- compose 的默认密码(
123456)只用于本地启动。进入任何共享环境前必须轮换。 - 受监管环境应固定镜像 digest,而不是使用文档中的浮动
:latest标签。 - 对于单节点 SQLite 实验,README 也记录了挂载
/data且不设置SQL_DSN的容器运行方式;应把它视为小规模路径,而不是多写入者生产环境。 - 在入口(nginx、Caddy、云负载均衡器、Traefik)终止 TLS。没有额外访问控制时,不要把管理 UI 路径暴露到公网。
- 首次登录后,供应商 API 密钥应进入通道配置或密钥管理器,不能进入 git。
如果由于隔离网络镜像仓库或自定义编排而无法原样使用 Docker Compose,请把该片段视为需要转换的已验证基线,而不是可选伪代码。上面的镜像名、端口、卷和 SQL_DSN 变量都与本仓库发布的部署文档一致。
第一周配置清单
1. 身份与密钥
- 用强认证创建管理员用户
- 为每个服务签发最小模型作用域令牌
- 分离预发与生产密钥
- 记录轮换负责人
2. 通道
在管理 UI 的通道配置中:
- 每个上游凭证边界一个通道
- 为 Azure/区域端点写明 base URL
- 凭证变化后运行健康检查或手动冒烟测试
- 绝不要让互不信任的租户共享一把不受限的上游密钥
3. 目录与价格上下文
- 发布应用依赖的稳定模型别名(
claude-sonnet、gemini-flash、gpt-...) - 把别名映射到当前上游 ID,例如切换时供应商列出的 Claude Sonnet 5 / Opus 4.8 与 Gemini 3.5 Flash 类模型
- 默认别名变化时复核定价上下文
4. 可观测性
- 为计费路由启用使用日志
- 确认日志留存和导出路径
- 对错误率和支出速度告警,而不只是 CPU
5. 备份
- 自动执行数据库备份(PostgreSQL/MySQL dump 或卷快照)
- 在第一次真实事故前,在空白主机上测试恢复
- 将备份加密密钥保存在网关容器之外
自建控制面的安全模型
需要防范的威胁
- 被盗的网关密钥耗尽供应商预算
- 管理 UI 暴露在公网
- 提示与工具日志包含客户机密
- 当运维人员可把通道指向内部元数据端点时,通道 base URL 引发 SSRF 类风险
- 集群中的
SESSION_SECRET保持默认值,导致多节点会话固定风险
真正有效的控制措施
- 在边缘终止 TLS;通过 VPN、SSO 或 IP 白名单限制管理访问
- 每个应用使用唯一密钥;批处理密钥设置模型白名单
- 供应商密钥只保存在网关
- 对任何可触发工具或长上下文的密钥设置配额
- 为使用日志导出制定脱敏策略
- 多节点部署设置
SESSION_SECRET(参见仓库内 compose 注释)
当 agent 能自动调用工具时,请复核 OWASP LLM 应用 Top 10。自建不会消除过度代理风险,只会改变你实施控制的位置。
将路由策略写成配置
把路由策略写成配置:
- 每产品默认模型别名
- 上游瞬时错误的备份别名
- 受监管或评估敏感流的固定别名
- 对密钥绝不可触达模型的显式拒绝
把路由与 LLM API 故障转移策略 结合,避免天真地重试中流失败。对于工具型 agent,按照跨供应商可移植工具调用中的方式保持 schema 可移植。
容量、数据库与 Redis
| 规模 | 数据库 | 说明 |
|---|---|---|
| 个人 / 小团队 | SQLite | 简单,挂载持久卷 |
| 多团队生产 | MySQL ≥ 5.7.8 或 PostgreSQL ≥ 9.6 | 更好并发与运维工具 |
| 热点限流/缓存路径 | 可选 Redis | 进程内限制不够时使用 |
按并发流而不是空闲管理 UI 用量估算 CPU/内存。流式响应会占用连接;若客户端流式,负载测试应包含 SSE 类流量。
升级与变更管理
- 阅读与通道、计费相关的发布说明。
- 用类生产通道配置部署到预发。
- 对
/v1/chat/completions与任何/v1/responses使用做 curl 冒烟。 - 用金丝雀密钥验证日志入库与钱包/配额行为。
- 带着已知上一镜像前滚以便回滚。
- 升级后对照上游更名复核模型别名。
切勿在同一无人值守窗口同时做数据库迁移、供应商凭证轮换与路由策略变更。
每次部署后的冒烟测试
curl -sS https://gateway.example.com/v1/models \
-H "Authorization: Bearer $GATEWAY_API_KEY" | head
curl -sS https://gateway.example.com/v1/chat/completions \
-H "Authorization: Bearer $GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4.1-mini",
"messages": [{"role": "user", "content": "ping"}],
"max_tokens": 16
}'
如果 Claude 和 Gemini 通道在范围内,分别添加一个 Claude 别名(例如 claude-sonnet → 当前 Claude ID)和一个 Gemini 别名(gemini-flash → gemini-3.5-flash 或后继模型)。在宣布部署健康前确认使用日志中有条目。
不放弃自建的前提下控制成本
自建不等于无限。配置:
- 按密钥与分组的配额
- 阻止批处理密钥使用旗舰模型的模型白名单
- 用日志导出或看板检查对花费速度告警
- 评估任务默认走更便宜模型
默认别名变化时复核公开的价格上下文。无法回答成本问题的自建网关会变成共享负债。
何时改选托管
在以下情况保持托管或混合:
- 缺乏对 tier-0 依赖的值班能力
- 无法满足备份/恢复义务
- 采购更倾向供应商运营的控制面
- 团队只需要单供应商密钥跳
无论哪种,应用客户端仍可保持 OpenAI 兼容。托管模式不应迫使客户端重写。
官方与项目资料
- 项目 README 的部署章节(
docker pull calciumion/new-api:latest、docker-compose.yml) - OWASP LLM 应用 Top 10
- OpenAI API 参考
- Docker 文档
最近核对:2026-07-15。请对照你实际部署的版本验证镜像标签、环境变量与 UI 路径。
常见问题
自建 LLM 网关等于自己托管模型吗?
不等于。多数自建网关仍调用托管供应商 API。你托管的是控制面——鉴权、路由、日志——不一定是权重。自托管开源权重是额外的 GPU 栈。
可以从 SQLite 起步再迁到 PostgreSQL 吗?
对许多部署可以,但要规划迁移,而不是在事故中才发现锁竞争。小规模用 SQLite,当并发写与备份工具需要时再迁移。
最小可行安全设置是什么?
边缘 TLS、私有管理访问、每应用唯一密钥、供应商密钥只在网关、启用使用日志,以及对任何可触发工具或长上下文的密钥设配额。
如何避免成为单点故障?
可用性重要时在负载均衡后至少跑两个应用实例,使用外部数据库,测试恢复,并文档化通道故障转移。网关应缩小供应商中断的爆炸半径,而不是制造更糟的一个。
新客户端应指向哪个端点?
优先网关的 OpenAI 兼容 /v1 根与 /v1/chat/completions 以获得广泛客户端支持。仅当你的产品有意依赖 /v1/responses 且网关版本支持所需工作流时再采用它。
预发切换
使用仓库 compose 文件(或等效镜像与 SQL_DSN)部署预发网关,向单个非关键服务签发作用域密钥,并在接入第二个供应商或生产流量前验证聊天补全、使用日志与备份恢复。第一个金丝雀验证通过后,把通道配置、模型目录与使用历史作为日常运维循环。