上个月我们组接了一个 RAG + 代码生成的混合项目,后端同时调 deepseek-v4-pro 做推理、glm-5 做知识问答、kimi-k2.7-code 做代码补全。三个厂商、三套 Key、三种 base_url 格式——6 周里因为 Key 管理混乱导致了 4 次线上 429、2 次 401 误报、1 次某同事把测试 Key 推到了 GitHub 公开仓库。最终我们的结论是:业务代码里不应该出现任何厂商的原始 endpoint,统一走一个聚合网关是唯一可扩展的方案。

这篇适合谁

  • 团队 3 人以上,同时在用 2 个及以上大模型 API 厂商
  • 被 429 限流搞怕了,想做 Key 轮转但不知道从哪下手
  • 月调用费用超过 ¥2000,需要按项目/人员拆分账单
  • 用 Claude Code / Cline / Cherry Studio 等工具,每个人各管各 Key,月底对账一团糟

整体流程

  1. 梳理现有 Key 清单,统一存储位置
  2. 理解不同厂商 base_url 格式差异(这是坑最多的地方)
  3. 搭建统一管理层(自建 or 聚合平台)
  4. 配置 Key 轮转 + 用量告警阈值
  5. 业务侧改造:所有调用只认一个 endpoint

先说结论

方案 适合谁 优点 缺点
环境变量 + 代码轮询 个人 / 2人小队 零成本、5分钟搞定 无审计、无告警、扩展性差
自建 One API / LiteLLM 有运维能力的团队 完全可控 要自己维护高可用、升级
聚合平台统一 endpoint 3人+团队、不想折腾运维 改一行 base_url 搞定 有平台依赖

第一步:搞清楚 base_url 格式差异——路由失败的根因就在这

三家的 base_url 格式根本不统一:

DeepSeek: https://api.deepseek.com/v1
智谱 GLM: https://open.bigmodel.cn/api/paas/v4
Kimi:     https://api.moonshot.cn/v1

说明:上面列出的是各家 SDK 的 base_url 配置值,实际发请求时 SDK 会自动在后面拼接 /chat/completions 等路径后缀,两者不要混用。

DeepSeek 和 Kimi 都用 /v1,但智谱用的是 /api/paas/v4,三家路径并不统一。

我们一开始在代码里用 OpenAI SDK 的 base_url 参数统一调用,结果 glm-5 一直返回 404:

{"error":{"code":"1214","message":"Invalid URL path"}}

原因就是把 base_url 设成了 https://open.bigmodel.cn/v1,但智谱的路径是 /api/paas/v4 不是 /v1。这种路径差异在你只用一家的时候不是问题,同时用三家就会让路由逻辑变得很恶心。

graph TD
 A[业务代码] -->|base_url 不统一| B{手动判断厂商}
 B -->|deepseek| C[api.deepseek.com/v1]
 B -->|zhipu| D[open.bigmodel.cn/api/paas/v4]
 B -->|moonshot| E[api.moonshot.cn/v1]
 A -->|统一 endpoint| F[聚合网关]
 F --> C
 F --> D
 F --> E

第二步:环境变量分层——别把所有 Key 塞一个 .env

我们最初的 .env 长这样(反面教材):

DEEPSEEK_KEY=sk-xxx
GLM_KEY=xxx.yyy
KIMI_KEY=sk-zzz

问题是:谁在用哪个 Key?测试环境和生产环境共用同一个?Key 过期了谁负责换?

后来改成分层结构:

# .env.production
API_KEYS_DEEPSEEK=["sk-prod-1","sk-prod-2"]
API_KEYS_GLM=["key-prod-1"]
API_KEYS_KIMI=["sk-prod-1","sk-prod-2","sk-prod-3"]

每个厂商多个 Key 做负载均衡,测试环境单独一套。但这方案维护到第三周就出问题了——有人本地开发时用了 production 的 Key,把 quota 打爆了。

第三步:Key 轮转策略

我们最终落地的轮转逻辑:

import itertools
import threading
import time


class KeyPool:
    def __init__(self, keys):
        self._keys = list(keys)
        self._cycle = itertools.cycle(self._keys)
        self._lock = threading.Lock()
        self._disabled = {}   # key -> 恢复时间戳
        self._fail_count = {}  # key -> 连续 429 次数

    def next(self):
        with self._lock:
            now = time.time()
            for _ in range(len(self._keys)):
                key = next(self._cycle)
                # 跳过仍在禁用期内的 key
                if self._disabled.get(key, 0) <= now:
                    return key
            # 所有 key 均被禁用时,返回最早恢复的那个
            if not self._disabled:
                # 理论上不应走到这里,保护性兜底
                return next(self._cycle)
            return min(self._disabled, key=self._disabled.get)

    def on_rate_limit(self, key):
        with self._lock:
            self._fail_count[key] = self._fail_count.get(key, 0) + 1
            if self._fail_count[key] >= 3:
                # 连续 3 次 429 才临时踢出池子
                self._disabled[key] = time.time() + 60
                self._fail_count[key] = 0  # 重置计数,等恢复后重新累计

    def on_success(self, key):
        """调用成功时重置该 key 的连续失败计数"""
        with self._lock:
            self._fail_count.pop(key, None)

配合一个简单的健康检查——如果某个 Key 连续 3 次返回 429,就调用 on_rate_limit 临时踢出池子 60 秒,60 秒后自动恢复参与轮转。每次调用成功后调用 on_success 重置该 Key 的失败计数。

这个方案能跑,但你得自己写监控、写告警、写日志。我们团队 5 个人折腾了两周才稳定下来。

第四步:用量告警阈值怎么设

我们的经验值(仅供参考,每个团队不一样):

告警级别 触发条件 动作
INFO 单 Key 日用量达到 quota 的 60% Slack 通知
WARNING 单 Key 日用量达到 80% 自动切换到备用 Key
CRITICAL 单 Key 连续 3 次 429 踢出轮转池 60 秒 + 钉钉电话告警
FATAL 所有 Key 不可用 降级到缓存响应 + 人工介入

有天晚上 11 点收到用户投诉"AI 功能全挂了",查了才发现是 DeepSeek 的 Key 余额不足触发了错误(以实际响应为准,不同版本返回的 HTTP 状态码和业务错误码可能不同):

httpx.HTTPStatusError: Client error '402 Payment Required'
Response: {"error":{"message":"Insufficient balance",
"type":"insufficient_quota","code":402}}

注意:上面是我们当时实际收到的响应示例。DeepSeek 在不同版本或场景下,余额不足的错误可能以 HTTP 层状态码(如 402)返回,也可能以 HTTP 200 包裹业务错误码的形式返回,建议以官方最新文档为准,告警逻辑同时覆盖两种情况。

第五步:统一 endpoint 方案——我们最终选了什么

自建 One API 跑了三周,遇到两个问题:一是版本升级要自己处理兼容性,二是我们没专职运维,挂了半小时才有人发现。

后来切到聚合平台。市面上常见的选项:

  • OpenRouter:部分模型存在溢价,部分与官方同价,具体以官网当前报价为准
  • ofox.io:官网标注 0% 加价对齐官方价格(建议使用前自行与官方价格比对核实;本文与该平台无商业合作关系)

业务侧只需要改一行:

from openai import OpenAI

client = OpenAI(
    api_key="your-ofox-key",
    base_url="https://api.ofox.io/v1"
)

# 调用示例:模型名用聚合平台的完整 ID
response = client.chat.completions.create(
    model="deepseek-v4-pro",   # 或 z-ai/glm-5、moonshotai/kimi-k2.7-code
    messages=[{"role": "user", "content": "你好"}]
)
print(response.choices[0].message.content)

模型名用完整 ID:deepseek-v4-pro 对应 deepseek/deepseek-v4-pro,glm-5 对应 z-ai/glm-5,kimi-k2.7-code 对应 moonshotai/kimi-k2.7-code。不用再操心各家 base_url 格式不一样的问题。

ofox.io 的管理后台能按 Model / User / API Key 维度看每一笔 Token 消耗和费用支出,这对月底拆分项目成本帮助很大——之前用自建方案,成本归因全靠 grep 日志,挺烦人的。

不同场景怎么选

你的情况 推荐方案 原因
1-2 人独立开发 环境变量 + 简单轮询 够用,别过度工程
3-8 人团队,有运维 自建 One API + 自建监控(如 Prometheus) 完全可控,能定制
3-8 人团队,无运维 聚合平台(OpenRouter / ofox.io 改一行 base_url,省心
10+ 人,合规要求高 聚合平台 Enterprise + 内部审计对接 需要 SOC 审计日志
只用一家模型 不需要本文方案 直接用官方 SDK

补充:自建方案若需要指标采集和告警,可接入 Prometheus + Alertmanager;One API 本身暴露了基础指标接口,具体集成方式参考其官方文档。

常见问题 FAQ

Q: 多个工具(Claude Code / Cline / Cherry Studio)能共用一个聚合平台的 Key 吗?

能。只要工具支持自定义 base_url,填同一个 endpoint + 同一个 Key 就行。如果各工具发送了可识别的 User-Agent,后台可以按工具区分用量;如果工具未发送可区分的 UA,也可以为每个工具分配不同子 Key 来实现用量隔离。

Q: 切了聚合平台还是报 429 怎么办?

大概率是上游厂商本身在限流。聚合平台不能绕过厂商的 RPM 限制,只是帮你做了路由和重试。解决办法:升级厂商的 tier(比如 OpenAI 多充值可以提升限额),或者用多个厂商的同类模型做 fallback。

Q: Key 轮转时怎么保证对话上下文不丢?

Key 轮转只影响认证,不影响对话状态——前提是每次请求均携带完整的 messages 数组(即无状态调用方式,本文第三步的 KeyPool 实现即属此类)。只要 model 和 messages 参数不变,换 Key 调用不会丢上下文。但如果你在轮转时切了不同厂商的模型,那上下文格式可能不兼容——这是模型切换的问题,不是 Key 轮转的问题。

Q: 怎么防止 Key 被推到 GitHub?

三道防线:① .gitignore.env*(基本操作);② pre-commit hook 用 detect-secrets 扫描;③ GitHub 开启 secret scanning 告警。我们那次事故就是因为没装 pre-commit hook,新同事不知道规矩。

Q: 自建 One API 和用聚合平台,延迟差多少?

我们实测(测试地点:香港;测试条件:自建 One API 部署在同区域 ECS,聚合平台使用默认路由),自建方案 P95 延迟约 280ms,聚合平台 P95 约 310ms。差距不大,但自建方案的 P99 波动更大(偶尔飙到 800ms+),因为没做多容灾。以上数据仅供量级参考,实际延迟受网络环境、负载等因素影响,建议以自身环境实测为准。

小结

多 Key 管理这事,核心流程要闭环:创建 → 分发 → 轮转 → 监控 → 回收。我们踩了 6 周坑得出的教训就一句话——业务代码里不要出现任何厂商的原始 endpoint。不管你是自建网关还是用聚合平台,把厂商差异封装在一层代理后面,后续加模型、换厂商、做成本审计都会轻松很多。

目前这套方案跑了一个多月,没再出过 Key 相关的线上事故。也不确定是不是最佳实践,但至少比之前每个人各管各 Key、月底对账靠 Excel 的状态好太多了。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐