本服务面向非中国大陆地区 · ZetaAPI.AI 的网站与控制台主要面向非中国大陆市场,注册与开通功能在你当前地区不可用。
Назад в блог
Надёжность 2026-04-10 8 мин

Как двухканальная изоляция подняла доступность моделей с 97% до 99,8%

Где потолок доступности одного канала поставки? Мы разбираем 18 месяцев продакшен-данных и показываем реализацию и эффект двухканальной изоляции.

Проблема: потолок одного канала

В конце 2024 года наши основные модели (Claude Sonnet, GPT-4o) подключались к вышестоящим провайдерам через единственный канал. Месячная доступность колебалась между 96,5% и 97,2%. Звучит нормально?

Посчитайте — и нет. 97% доступности означает около 21 часа простоя в месяц. Для команд, которые используют нас как инфраструктуру, это неприемлемо.

Корень проблемы не в нашем коде — это волатильность самих вышестоящих провайдеров. Один канал падает — и страдает весь трафик. Единая точка зависимости — это проблема архитектуры, а не эксплуатации.

Проектирование: двухканальная изоляция

Идея проста: держать по два независимых канала поставки на модель (Channel A / Channel B), взаимно резервирующих друг друга.

Логика маршрутизации

Когда приходит запрос, маршрутизатор делает три вещи:

  1. Запрашивает реальные health-оценки обоих каналов (по ошибкам и задержке за последние 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 })
  }
}

Расчёт health-оценки

Health-оценка каждого канала — значение 0–100 на скользящем окне:

  • Доля ошибок, вес 70% — 5xx / всего запросов за последние 5 минут
  • Задержка, вес 30% — насколько P95 отклоняется от базовой линии

Канал ниже 50 автоматически понижается в весе; канал ниже 30 в течение 3 минут подряд временно выводится из пула маршрутизации, периодически прощупывается отдельным heartbeat-зондом и возвращается после восстановления.

Результат: 18 месяцев продакшен-данных

После запуска двухканальной изоляции доступность выросла до 99,81%, а время восстановления упало с p95 4 минуты до p95 8 секунд — подавляющее большинство пользователей вообще не заметили сбой на стороне провайдера.

МетрикаОдин канал (2024 Q4)Два канала (2025 Q3)
Доступность97,0%99,81%
Средний простой в месяц21ч1,4ч
failover p95—8с

Набитые шишки

  • Сначала не изолировали бюджет таймаута: у резервного канала timeout тоже был 30с, что удваивало ожидание при сбоях. После перехода на основной 30с / резервный 20с воспринимаемая задержка упала на 35%.
  • Запаздывание health-оценки: 5-минутное окно медленно реагирует на внезапные сбои, поэтому мы добавили быстрый 30-секундный сигнал «недавняя ошибка».
  • Шторм переключений: при кратковременном дрожании основного обе стороны опрашивали и перегружали резервный. Помогли клиентское ограничение частоты + backoff.

Что дальше

Двухканальность уже решает сбой одного вендора. Но мы по-прежнему зависим от единственного сетевого выхода, единственного биллинг-аккаунта, единственного региона. Следующий пункт плана — распространить изоляцию на эти уровни; напишем об этом, когда реализуем.

Похожие статьи