怎么给项目配置多家 API 互备
单点依赖是生产环境最不该有的东西。本文给出一个不复杂的多通道互备方案:配置结构、切换时机、以及切换时必须注意的三个细节。
目标不是「永不出错」
先明确目标:不是让 API 永不故障(做不到),而是让故障的影响从「业务中断」降为「一次重试」。
配置互备后,一家站挂了,你的代码自动切到另一家,用户察觉不到。
最小可行的架构
class Channel:
def __init__(self, name, base_url, api_key, priority):
self.name, self.base_url = name, base_url
self.api_key, self.priority = api_key, priority
CHANNELS = [
Channel("主站", "https://站A/v1", key_a, 1),
Channel("备站", "https://站B/v1", key_b, 2),
Channel("兜底", "https://官方/v1", key_official, 3),
]
调用时按优先级依次尝试:
async def call_with_failover(payload):
errors = []
for ch in sorted(CHANNELS, key=lambda c: c.priority):
try:
return await call(ch, payload), ch.name
except RetryableError as e:
errors.append(f"{ch.name}: {e}")
continue
raise AllChannelsFailed(errors)
关键细节一:什么错误才该切换
| 错误类型 | 是否切换 | 原因 |
|---|---|---|
| 401 / 403 | ❌ | Key 的问题,换站也没用 |
| 400 | ❌ | 请求的问题 |
| 402(余额不足) | ✅ | 该通道熄火了 |
| 429(限流) | ✅ | 换通道能绕过 |
| 500 / 502 / 504 | ✅ | 服务端问题 |
| 模型不存在 | ❌ | 换站可能也没有 |
超时要单独注意:如果请求已经发出去了,切换意味着可能产生两次计费。至少要区分「连接超时」(未发出,可安全切换)和「响应超时」(可能已产生费用)。
关键细节二:别把故障转移写成无限重试
# 危险:每家都重试 3 次,3 家就是 9 次
for ch in CHANNELS:
for attempt in range(3):
try: ...
# 更合理:每家试 1 次,快速轮换
for ch in CHANNELS:
try:
return await call(ch, payload)
except RetryableError:
continue
理由:全部故障时(比如上游整体挂了),重试再多也没用,只是浪费时间并放大账单。快速失败 → 快速轮换 更有效。
关键细节三:记录实际使用的通道
result, channel_used = await call_with_failover(payload)
logger.info("请求完成", extra={"channel": channel_used})
为什么重要:出问题时你需要知道「当时走的是哪家」。没有这个日志,故障分析会变成猜谜。
另外,这个日志还能告诉你备用通道的切换频率。如果频繁切换,说明主站有问题,该处理了。
进阶:按模型路由
ROUTES = {
"claude-*": ["站A", "站C"],
"gpt-*": ["站B", "站C"],
"*": ["站A", "站B", "站C"],
}
每个模型都有它自己的主备顺序,整体可用性更高。
别忘了这些配套
一、模型名要统一映射。 各站命名不同,路由层要维护映射表。
二、定期演练切换。 配置好不等于能用。每隔一段时间手动断开主站,确认备用通道真的能接上。
三、备用通道也要有余额。 这是最容易忽略的 —— 备用站长期不用,余额可能不够,真需要时才发现。
四、监控切换率。 切换率突然上升是故障信号,应该触发告警。
相关阅读
- 选型之后:怎么持续监控你的 API 供应商
- 常见报错对照表:401/403/404/429/500 分别意味着什么
- 客服与对话场景:稳定性与并发怎么权衡
这篇文章对你有帮助吗?如果你在实际使用中发现了文中没提到的情况,欢迎 提交纠错或补充,我们会核验后更新到正文里。
相关文章
顺着看下去:本站收录的部分中转站
本文没有指向特定模型系列,下面是本站收录站点中综合评分靠前的几家,供你顺着看下去。排序依据是评分与可用率,不构成推荐。