本服务面向非中国大陆地区 · ZetaAPI.AI 的网站与控制台主要面向非中国大陆市场,注册与开通功能在你当前地区不可用。
返回博客
稳定性工程 2026-04-10 8 min

我们如何用双渠道隔离把模型可用率从 97% 推到 99.8%

单一供应渠道的可用率天花板在哪?我们用 18 个月的生产数据复盘,拆解双渠道隔离的具体实现和效果。

问题:单渠道的天花板

2024 年底,我们的核心模型(Claude Sonnet、GPT-4o)通过单一渠道接入上游供应商。月度可用率在 96.5%–97.2% 之间波动。听起来还行?

算一下就知道不行。97% 可用率意味着每月约 21 小时 不可用。对于把我们当基础设施用的团队来说,这个数字是不可接受的。

问题的根源不是我们的代码——是上游供应商本身的波动。一个渠道挂了,所有流量都受影响。单点依赖是架构问题,不是运维问题。

方案设计:双渠道隔离

核心思路很简单:每个模型维护两条独立的供应渠道(Channel A / Channel B),互为 fallback。

路由逻辑

请求进来后,路由器做三件事:

  1. 查询两条渠道的实时健康分(基于最近 5 分钟的错误率和延迟)
  2. 优先走健康分更高的渠道
  3. 如果主渠道返回 5xx 或超时,立即重试到备渠道(绝大多数场景用户无感知)
async function route(model: string, req: Request) {
  const [chA, chB] = await getChannels(model)
  const primary = chA.healthScore >= chB.healthScore ? chA : chB
  const fallback = primary === chA ? chB : chA

  try {
    return await primary.forward(req, { timeout: 30_000 })
  } catch (e) {
    // 主渠道失败,立即切换——用户无感知
    metrics.record('failover', { model, from: primary.id })
    return await fallback.forward(req, { timeout: 30_000 })
  }
}

健康分计算

每条渠道的健康分是一个 0–100 的滑动窗口分数:

  • 错误率权重 70% — 最近 5 分钟内 5xx / 总请求数
  • 延迟权重 30% — P95 延迟相对基线的偏离程度

健康分低于 50 的渠道会被自动降权,连续 3 分钟低于 30 的渠道会被临时拉出路由池,由独立的心跳探针周期性试探,恢复后重新加入。

结果:18 个月生产数据

双渠道隔离上线后,可用率提升到 99.81%,故障恢复时间从 p95 4 分钟降到 p95 8 秒——绝大部分用户从未察觉供应商侧的故障。

指标单渠道(2024 Q4)双渠道(2025 Q3)
可用率97.0%99.81%
月均不可用时长21h1.4h
failover p95—8s

踩过的坑

  • 早期没隔离超时预算:备渠道的 timeout 也设 30s,导致故障时双倍等待。改成主 30s / 备 20s 后,用户感知延迟下降 35%。
  • 健康分滞后问题:5 分钟窗口对突发故障反应慢,后来叠加了 30 秒的”最近失败”快速信号。
  • fallback 风暴:主渠道瞬时抖动时两边轮询会打爆备渠道。加了 client-side 限流 + 退避后缓解。

下一步

双渠道已经解决了 单 vendor 故障 的问题。但我们仍然依赖单一的网络出口、单一的计费账户、单一的 region。接下来的 roadmap 是把隔离维度扩展到这些层面——这部分等实施完再写一篇。

相关文章