← 返回资讯

多模型网关怎么选:按要解决的问题选,别按功能清单选

2026-08-07

我见过一个五个人的小团队,产品刚上线两周,日调用量三千出头,只接了一家上游。他们花了整整一个周末把一套开源网关搭起来,接了外置数据库和 Redis,然后第三周的一次线上故障,排查了两小时,最后发现是网关那台机器的磁盘满了——上游其实一直好好的。

这就是典型的「为不存在的问题上网关」。网关本身没错,错的是上它的时机。它是一层额外的进程、一份额外的配置、一个额外的故障点,你得先有值得用这些代价去换的东西。

这篇不做产品功能对比。市面上开源网关的功能清单看起来都差不多,照着清单打勾选出来的结果往往是「谁的 README 写得长选谁」。我更愿意反过来:先明确你要解决的是哪个问题,再看哪种形态能解决它,最后才看具体项目。

什么信号出现时才该上网关

网关的价值几乎全部来自「多」和「共享」。只有一家上游、一个应用、一个人管,它提供不了任何你自己写十行代码拿不到的东西。下面这些信号出现一个以上,才值得认真考虑:

第一,你有了第二个上游。 不是「打算接」,是真的在同时用两家。这时候你要处理模型名映射、鉴权方式差异、错误码语义不一致,这些逻辑散落在业务代码里会很难受。

第二,出现了分账需求。 财务开始问「这个月这笔钱是哪个业务花的」,或者你要给某个内部团队开一条额度受限的通道。这是网关最硬的价值点——单靠上游账单通常只能看到一个总数。

第三,你需要统一限流和审计。 比如要防止某个新上线的功能失控刷爆预算,或者合规要求所有对外模型调用都要留痕。这类横切能力放在应用里做,每接一个新应用就得重做一遍。

第四,你要做故障回退。 一家上游抽风时自动切到另一家,并且在切换过程中不把「内容策略拒绝」和「超时」当成同一种失败处理。

第五,调用方多于一个团队。 两个团队各自持有上游 key,轮换的时候要同时通知两边,出了泄漏你也不知道是哪边漏的。

如果一条都不占,先别上。把这个判断写下来,过三个月再回头看,比现在硬上要划算得多。关于网关这层到底在做什么,可以先读 网关到底解决什么问题 打个底。

三种形态:应用内封装、自部署、托管

「上网关」不是一个二选一的开关,它至少有三档。很多团队的痛苦来自直接从第一档跳到第三档,或者从零直接跳到自部署。

应用内 SDK 封装

在你的代码里做一层薄薄的通道抽象:定义一个 chat(model, messages) 之类的接口,内部按配置分发到不同上游,把 key 从环境变量读进来,把重试和超时包在里面。

  • 适用规模:一到两个应用、一到两家上游、单团队。
  • 要承担的运维:零。它就是你应用的一部分,跟着应用一起部署、一起监控。
  • 切换成本:低。因为你已经有了抽象层,日后换成真网关时只需要改这一层的实现——把分发逻辑换成「调网关」,业务代码一行不动。

这一档被严重低估。它能解决「多接一家上游」这个最常见的诉求,而且是唯一一档不增加故障点的做法。我的建议是:任何团队在上真网关之前,都应该先有这层抽象,哪怕只有五十行。它的真正作用不是省事,是把未来的迁移成本提前锁死。

自部署开源网关

把一个独立的网关服务跑在你自己的机器上,所有应用改成调它。

  • 适用规模:多上游、多团队、有分账和限流诉求,并且有人愿意为这台服务的可用性负责
  • 要承担的运维:一台(或多台)常驻服务、一个数据库、一个缓存、备份、升级、监控、告警、值班。后面单开一节讲。
  • 切换成本:中等。调用方从「调上游」改成「调网关」,如果上游接口本身是 OpenAI 兼容格式,通常只需要改 base URL 和 key;如果不是,改动会大一些。

托管服务

直接用别人跑好的聚合服务,你只拿一个 key。

  • 适用规模:不想碰运维、或者团队里确实没有能扛住半夜告警的人。
  • 要承担的运维:几乎为零,但换来两件事——你的所有调用要经过第三方,以及你的可用性上限被对方锁死。
  • 切换成本:取决于它是不是标准兼容格式。如果是,换回自建或换一家的成本不高;如果它有自己独有的接口约定,那就是长期绑定。

这三档的取舍在 自建聚合 vs 托管服务怎么选 里有更细的成本对比,这里不重复。

选型六维度:每个维度怎么判断

下面是这篇的主体。不要看功能清单,看这六个问题你能不能答出来。

一、计费与归属:能不能按团队 / 项目 / 环境分账

这是最容易被忽略、又最容易在半年后咬人的维度。判断标准很简单:问自己「下个月财务问某个业务花了多少钱,我要花多久才能答出来」。如果答案是「导账单然后手工按时间段猜」,那你需要这个能力。

具体要看三点:

  1. 能不能给每个调用方发独立凭证,而不是所有人共用一个 key。
  2. 每张凭证能不能带约束:限定模型范围、限定花费上限、限定速率。
  3. 花费能不能自动聚合到组织结构上,而不是只能看到一堆扁平的 key。

LiteLLM Proxy 的虚拟 key 是这类能力的一个具体实例,可以拿它当参照系看看「完整的分账能力长什么样」。它用 POST /key/generate 签发 key,鉴权用 master key 的 Bearer token,官方示例里的地址是 http://0.0.0.0:4000/key/generate

curl 'http://0.0.0.0:4000/key/generate' \
  --header 'Authorization: Bearer <master-key>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "models": ["gpt-3.5-turbo", "gpt-4"],
    "metadata": {"user": "email@example.com"}
  }'

签发时可以带的字段有:models(数组,该 key 允许调用的模型白名单)、user_idteam_id(关联到用户 / 团队)、metadata(自定义元数据)、duration(有效期,官方示例值是 "30min""30d")、max_budget(花费上限,单位 USD)、tpm_limitrpm_limit(每分钟 token 数 / 请求数上限)、aliases(模型名映射)。签发之后还有 /key/info 查花费、/key/update 改配置、/key/block/key/unblock 停用启用。官方说明是:花费追踪通过数据库在 key / user / team 三个层级自动进行

三层这件事比参数清单本身重要。它意味着你可以给同一个团队下的开发环境、预发、生产各签一张 key,既能单看某个环境烧了多少,也能直接看到团队总数,不用自己在外面写聚合逻辑。你评估任何一个候选网关时,就拿这个当尺子量:它的花费数据是扁平的还是有层级的。虚拟 key 的更多用法在 LiteLLM 虚拟 key 怎么用 里。

顺带一个实践判断:duration 这类有效期字段,日常发给临时项目、外部合作方、演示环境的 key 一定要带上。忘记回收的长期 key 是泄漏事故里占比最高的一类。

二、可靠性:回退不是一个开关,是三类不同的失败

很多人评估回退能力时只问一句「支不支持 failover」,得到「支持」就打勾了。这个勾打得太便宜。

真正要问的是:它区分不区分失败的种类。至少有三类失败在语义上完全不同:

  • 上游超时、5xx、连接断——换任何一家健康的上游都行。
  • 上游因为内容策略拒绝了这次请求——换一家风控策略同样严格的上游,大概率还是被拒,白白多花一次钱和一次延迟。
  • 请求超出了模型的上下文长度——这时候必须换到窗口更大的模型,换一个同样装不下的模型是纯粹的浪费。

LiteLLM Proxy 的配置里这三类是分开的字段:fallbacks(普通失败回退)、content_policy_fallbacks(内容策略拒绝回退)、context_window_fallbacks(超上下文回退),另外还有 default_fallbacks 做兜底。熔断相关的是 allowed_fails(触发冷却的失败次数阈值)和 cooldown_time(冷却时长,之后该模型重新启用),重试是 num_retries,单次调用最长时间是 request_timeout,还有 enable_pre_call_checks 做发送前校验。

官方文档里这些字段的示例值分别是 num_retries: 3request_timeout: 10allowed_fails: 3cooldown_time: 30这些是官方示例值,不是推荐值也不是默认值,你自己的数字要按业务的超时容忍度和上游实际表现定,具体取值和默认行为以官方文档当次为准。

评估其他网关时,把这套语义当检查表用就行:能不能区分三类失败、有没有熔断(失败阈值 + 冷却时长)、重试次数和单次超时能不能分开配。只有笼统一个「失败就换下一家」的,回退能力是打折的。

三、可观测性:用量和成本能不能采出来

判断方法:假设明天有人问你「上周三下午三点到四点,A 业务在 B 模型上的 token 消耗和失败率是多少」,你能不能查到。

要拆成三个小问题:

  1. 数据存在哪。落在网关自己的库里,还是能吐到你已有的监控系统里?前者意味着你要额外维护一套查询入口。
  2. 维度够不够细。只有总量和按 key 的分组,跟能按模型、时间、调用方、成功失败交叉,是两个量级的东西。
  3. 能不能导出。能导出就能进你自己的报表和预算模型;不能导出,你就永远只能在它自带的页面里看。

这里有个很实际的坑:成本数字是网关按自己维护的价格表算出来的,它跟上游真实账单之间几乎一定有差。差的来源可能是价格表没更新、缓存命中部分的计费口径、也可能是免费额度抵扣。别把网关里的成本数字当账单用,把它当趋势和分账依据用,月底还是要跟上游账单对一次。对不上的差额有多大、稳不稳定,是判断这个网关成本模块靠不靠谱的最好指标。

四、部署与运维成本:最简形态和生产形态差着一个数量级

选型时最容易低估的就是这个维度,因为大多数项目的 README 都会给一条一行就能跑起来的命令,看起来轻得不行。

拿 New API 举例。它是一个自部署的多模型网关,官方定位强调组织级鉴权、多模型管理、用量分析与私有化部署。最简形态确实很轻——Docker 单机、默认端口 3000、数据落 SQLite:

docker run -p 3000:3000 -v ./data:/data calciumion/new-api:latest

注意这里 -v ./data:/data 不是可选项,本地 SQLite 需要挂载 /data 目录,不挂载容器一重建数据就没了。

但这只是玩具形态。生产形态要多做三件事:

  1. 外置数据库:用 SQL_DSN 指定连接串,比如追加 -e SQL_DSN="root:password@tcp(host:3306)/db"。官方给的数据库要求是远程 MySQL ≥ 5.7.8 或 PostgreSQL ≥ 9.6。
  2. 接 Redis 缓存:环境变量是 REDIS_CONN_STRING
  3. 多节点必须统一 SESSION_SECRET:这是硬约束,多节点部署必须设置且所有节点取值一致,否则会话会在节点之间失效。另外还有一个 CRYPTO_SECRET 用作缓存键的 HMAC secret,默认取 SESSION_SECRET 的值。

官方推荐的部署方式是 Docker Compose:克隆仓库后 docker-compose up -d;也提供了宝塔面板应用商店一键安装。具体的 compose 文件内容、镜像 tag、各项默认值以仓库 README 当次为准——这类项目迭代快,我不建议你照抄任何二手教程里的配置。

从第一条命令到第三条约束,中间隔着一个数据库、一个缓存、一套备份策略和一次多节点验证。评估任何自部署网关,都要按第三条的形态去估工作量,不要按第一条。 New API 的部署细节在 New API 部署实操 里。

还有一件事:首次启动后的初始账号,按页面提示创建或查阅官方文档,别从任何教程里复制账号密码。这是安全底线。

五、安全边界:网关后台等同于密码库

这条我想单独强调,因为它经常被当成运维细节,其实是选型维度。

网关的数据库里存着你所有上游的 key。 一个人拿到网关后台的管理员权限,等于同时拿到了你在每一家上游的账户。它的安全等级不是「一个内部工具」,是「密码库」。

由此推出几条硬要求,评估时逐条对照:

  • 管理后台绝对不能暴露在公网上没有额外保护。至少要在内网、VPN 后面,或者加一层独立的访问控制。
  • 管理员权限要能拆开。至少要区分「能看用量」和「能看/改上游 key」这两类人。
  • 上游 key 在库里是不是加密存储,泄漏一份数据库备份等于泄漏什么。
  • 操作要留痕。谁改了哪条通道、谁签发了哪张 key,事后要查得到。
  • 备份文件本身也是密钥材料,扔在对象存储的公开桶里跟没加密没区别。

顺着这条还有一个正面收益:一旦所有上游 key 都收在网关里,轮换就从「通知五个团队改配置」变成「在一个地方改一次」。这是自部署网关最实在的价值之一,也是评估时该问的问题——它的通道配置改完是否即时生效、要不要重启。

六、迁移成本:换网关要动多少调用方

选型的时候没人想换,但换的那天成本全部一次性爆发。提前判断的方法只有一个:看它对调用方暴露的接口是不是标准的

  • 如果网关对外是 OpenAI 兼容格式,调用方只需要改 base URL 和 key,换掉它的成本接近零。
  • 如果它有自己一套接口约定、自己的 SDK、自己的模型命名体系,那么每个调用方都要改代码,改动量随应用数量线性增长。

同样的逻辑适用于模型名。如果你在业务代码里直接写死了某家上游的模型标识,换网关时这些字符串全都要改。在应用侧用自己的语义名(比如「主力模型」「便宜模型」「长文模型」),把语义名到真实模型的映射放在网关配置里,是成本最低的做法。前面提到的 aliases 之类的模型名映射能力,价值就在这里。

还有一条容易漏的:日志和成本数据也是迁移成本的一部分。换网关意味着历史用量数据留在旧系统里,如果你的预算模型依赖这份数据,提前想好怎么导出。

别为不存在的问题上网关

回到开头那个团队。他们的情况是:单上游、单应用、没有分账需求、没人专职运维。这四条同时成立时,上网关的净收益是负的。

理由很直白:

  • 网关是一个新增的常驻进程,它挂了你的全部调用都挂,而它挂的概率不会低于上游挂的概率——上游是专业团队七乘二十四小时运维的,你的网关是周末搭的。
  • 它引入了新的排障维度。原来出问题只有「我的代码」和「上游」两个嫌疑人,现在有三个,而且中间那个是你最不熟的。
  • 它的配置是新的状态。配置漂移、忘了改的通道、过期的 key,都是未来事故的种子。
  • 分账、限流、审计这些收益,在只有一个调用方的时候等于零。

一个简单的判断口径:把「上网关能省下的人工」和「维护网关要花的人工」放在同一张纸上估。前者包括手工对账时间、多上游适配的开发时间、key 轮换的沟通时间;后者包括搭建、备份、升级、故障排查、值班。前者明显大于后者才动手。多数团队第一次算这笔账时会发现差得很远,这就对了——那说明现在的正确答案是应用内封装。

还有一种常见的自我说服值得警惕:「先搭起来,以后总用得上」。网关不是搭起来放着不动的东西,它从上线那天起就开始产生维护成本——上游变了要改配置,安全补丁要跟,数据库要备份。为一个还没发生的需求提前付这份月供,通常撑不过三个月就会变成一台没人敢碰也没人敢关的机器。

自部署的真实成本:上生产前必须完成的清单

决定自部署之后,那条 docker run 只是第一步。下面这些没做完,不要把生产流量切过去:

项目具体要做什么不做的后果
数据库外置SQL_DSN 指向独立数据库实例,满足 MySQL ≥ 5.7.8 或 PostgreSQL ≥ 9.6容器一重建,所有通道配置和用量数据归零
备份数据库定时备份 + 至少做一次恢复演练备份文件存在但恢复不了,这种情况比没备份还常见
缓存REDIS_CONN_STRING,并想清楚 Redis 挂了网关是降级还是不可用缓存层成为隐性单点
多节点一致性所有节点 SESSION_SECRET 取值一致会话在节点间失效,用户随机掉登录
健康检查网关进程、数据库连接、每条上游通道各自有探活上游早挂了,你从用户投诉里得知
监控告警至少监控错误率、延迟、余额或预算消耗预算烧穿了才发现
访问控制管理后台不在公网裸奔,权限分级一次泄漏等于所有上游账户失守
升级流程明确谁负责跟进版本、怎么灰度、怎么回滚要么长期不升级带着已知问题跑,要么升级当天出事
值班明确半夜告警响了谁接「大家都以为别人在看」
容量与限流给网关本身设并发上限,防止被单个失控客户端打垮一个死循环的调用方拖垮所有业务

这张表里最容易被跳过的是恢复演练值班。前者是因为看起来备份脚本跑成功了就万事大吉,后者是因为它不产生代码。这两条恰恰是自部署和「玩票」的真正分界线。

如果这张表里有超过三条你现在答不上来「谁负责」,那就是自部署时机未到的信号。

一条渐进路线,以及每一步的触发条件

不要一步到位。按下面这条走,每一步都有明确的进入条件,没到条件就停在原地。

第一步:应用内薄封装(通道抽象)

  • 做什么:定义统一的调用接口,把上游选择、key 读取、重试、超时收到一处。模型用语义名,映射写在配置里。
  • 触发条件:你开始写第一行调用大模型的代码。是的,第一天就该做。
  • 停留标志:只要还是单上游 + 单团队,就一直停在这里。

第二步:上自部署网关

  • 触发条件(两条同时成立):有了第二个真实在用的上游,并且有了第二个需要独立分账或独立限流的调用方。只满足一条时,第一步的封装还能扛。
  • 前置条件:上一节那张清单里的责任人都能落实到具体的人。
  • 迁移动作:因为第一步已经有抽象层,业务代码不动,只把抽象层的实现从「直连上游」换成「调网关」。这是第一步最大的回报兑现的时刻。

第三步:考虑托管

  • 触发条件:调用规模继续上升,但你发现团队在网关运维上的投入(值班、升级、扩容)已经明显超过它带来的收益;或者出现了跨地域、多机房这类你不想自己搞的需求。
  • 判断依据:把第二步实际花掉的运维人时折算成钱,跟托管的报价放一起比。注意这时候你已经有真实数据了,不用拍脑袋。
  • 前提:确认托管方对外是标准兼容接口,否则你是在用运维成本换绑定风险。

这条路线的关键不是每一步做什么,而是每一步都是可逆的。第一步的抽象层让第二步几乎零成本,第二步坚持用标准接口让第三步和第三步的回退都保持开放。反过来,一开始就把某家网关的独有约定写进业务代码,后面每一步都会很贵。

自查清单

动手前,把下面几条逐条答一遍。有答不上来的,说明你还没到该做决定的时候。

  1. 信号核对:多上游、多团队分账、统一限流审计、故障回退、多调用方——这五条我占了几条?一条都不占就停手。
  2. 形态选择:我要的这几条能力,应用内封装能不能解决?能解决就先别上独立网关。
  3. 分账尺子:候选方案的花费数据是扁平的还是有层级的?能不能按调用方签发带模型白名单、预算上限和速率上限的独立凭证?
  4. 回退语义:它区分「普通失败 / 内容策略拒绝 / 超上下文」三类失败吗?有没有失败阈值加冷却时长的熔断机制?
  5. 可观测性:用量和成本数据能不能导出?月底能不能跟上游账单对上,差多少?
  6. 运维账:上一节那张生产清单,我能给每一行填上责任人吗?备份做过恢复演练没有?
  7. 安全等级:我是不是已经把这套系统当密码库对待——后台不裸奔、权限分级、操作留痕、备份加密?
  8. 退路:换掉它要改多少个调用方?模型名是写死在业务代码里,还是走的语义名映射?

最后提醒一句:本文提到的所有环境变量名、接口字段和参数,都以对应项目的官方文档与仓库 README 当次为准。这类项目迭代很快,任何二手教程(包括这篇)里的配置细节都可能过时,但上面那套判断方法不会。

相关阅读