客户端配置防呆:让 key 出问题时整个应用不跟着挂
本文从工程韧性角度讲解如何为 LLM API 客户端做防呆设计:通过多 key 池、健康检查、熔断与优雅降级,让单个 key 失效只影响一条链路,而不是拖垮整个应用。
为什么单个 key 失效会拖垮整个应用
很多项目最初只有一个 API key,所有请求都走同一条路径。一旦这个 key 被限流、欠费、封禁或上游临时故障,整条生产流量会同时失败。
问题不在于「key 会失效」——这是必然事件;而在于应用没有为「失效后怎么办」预留结构。韧性设计的目标不是消除失败,而是把失败的爆炸半径限制在一条链路上。
多 key 池:把单点变成可替换资源
最直接的做法是维护一个 key 池,而不是把 key 写死在配置里。
- 池中每个条目至少包含:key 标识、所属渠道或模型分组、当前状态、最近一次成功时间。
- 请求时按策略挑选一个可用 key,而不是永远用第一个。
- 某个 key 连续失败后,把它临时移出可用集合,过一段时间再探测恢复。
如果你使用的是聚合站,一个 key 本身就能调用多个模型。这种情况下 key 池的意义在于:同一模型可以通过多个 key 或不同渠道分流,避免单一凭证成为瓶颈。
健康检查:区分「暂时失败」和「已经不可用」
不是每一次报错都意味着 key 坏了。网络抖动、上游偶发 5xx、单次超时都会产生失败信号。直接据此禁用 key,会造成不必要的抖动。
一个实用的区分方式是分层判断:
- 认证类错误:key 无效或权限不足,通常应直接标记为不可用。
- 配额类错误:key 可用但额度耗尽,应暂停使用但不销毁状态。
- 超时与上游错误:先重试或换 key,连续多次再降权。
健康检查可以是主动的(定时发一个轻量请求探测)也可以是被动的(根据真实请求的成败更新状态)。被动方式成本更低,主动方式恢复更快,通常两者结合。
熔断:让故障 key 快速退出,而不是拖慢每个请求
熔断器的核心是状态机:关闭、打开、半开。
- 关闭状态:请求正常走该 key。
- 打开状态:连续失败超过阈值后,直接跳过该 key,不再尝试。
- 半开状态:经过冷却时间后,放少量请求试探,成功则恢复,失败则继续打开。
关键参数是失败阈值和冷却时间。阈值太低会频繁误伤,太高则失去保护意义。冷却时间要给上游留出恢复窗口。
熔断的价值在于:当某个 key 已经明显不可用时,后续请求不再为它付出等待成本。
优雅降级:失败时给用户一个可接受的回应
降级不是「什么都不返回」,而是在能力受限时仍然提供价值。常见层次:
- 换 key 重试:同一模型用池中另一个 key 再试一次。
- 换模型:如果聚合站支持多个模型,可降级到另一个可用模型完成同类任务。
- 降质量:减少上下文长度、降低输出长度要求,先保证有结果。
- 明确失败:以上都不可行时,返回清晰的错误信息,而不是让请求挂起。
降级策略应当是可配置的,因为不同业务对「质量」和「可用性」的容忍度不同。
把设计落到客户端代码里
不需要一开始就做全套。可以从最小可用版本开始:
- 第一步:把 key 从单值改成列表,请求时轮询或随机选择。
- 第二步:记录每个 key 的连续失败次数,超过阈值就跳过。
- 第三步:加入冷却时间,让跳过的 key 有机会恢复。
- 第四步:为关键链路配置降级模型或降级参数。
每一步都能独立降低爆炸半径,不必等整套系统完成。
计费与用量视角
在聚合站上,用户按官方价乘以固定系数扣费,贡献 key 按另一系数返还。这种结构下,多 key 池和健康检查不仅影响可用性,也影响成本分布:被熔断的 key 不再产生扣费,而健康 key 承担流量。
因此客户端侧的状态管理应当是可观测的——记录每个 key 的成功率、失败类型和恢复时间,才能判断池子是否健康。
小结
让单个 key 失效只影响一条链路,靠的不是运气,而是结构:多 key 池提供可替换性,健康检查提供判断依据,熔断提供快速退出,优雅降级提供兜底。这四者叠加,才是客户端防呆设计的完整形态。