AI API - внешняя зависимость с необычными режимами отказа
Интеграция может получить timeout, 429, 5xx, отказ по безопасности, обрезанный ответ, несовместимый JSON или семантически слабый результат. HTTP 200 не означает, что пользовательская задача выполнена.
Отказоустойчивость - способность сохранить безопасный и объяснимый результат при частичном сбое, а затем восстановиться без дублей и скрытого ухудшения.
Карта отказов: сначала классификация, потом retry
| Сбой | Обычно временный? | Действие |
|---|---|---|
| Сеть, 408, часть 5xx | Возможно | Ограниченный retry |
| 429 rate limit | Возможно | Retry-After, pacing, queue |
| Quota или billing | Нет без изменения | Alert, fallback или остановка |
| Invalid request | Нет | Исправить запрос |
| Safety refusal | Не transport error | Обработать как отдельный outcome |
| Schema mismatch | Иногда | Validator и один controlled retry |
| Низкое качество | Не определяется HTTP | Eval, fallback, human review |
Failure-mode analysis для каждого workflow
- Какая зависимость может отказать.
- Как сбой обнаруживается.
- Затрагивает ли один запрос, tenant или всех.
- Можно ли повторить операцию безопасно.
- Каков общий deadline пользователя.
- Есть ли совместимый fallback.
- Как выглядит graceful degradation.
- Может ли произойти побочный эффект.
- Как восстановить pending работу.
- Какие alert и playbook нужны.
Timeout и deadline - разные ограничения
Timeout ограничивает отдельный вызов. Deadline ограничивает весь workflow с retrieval, несколькими генерациями, tools и retries. Если каждый шаг получает полный timeout заново, пользователь ждёт гораздо дольше обещанного.
Передавайте оставшийся budget вниз по цепочке. Не начинайте fallback, если он уже не успеет дать полезный ответ. Отдельно измеряйте connect timeout, time to first token и полное время.
Retry только для временной и повторяемой операции
Повтор запроса на генерацию может быть безопасен, но повтор tool call способен создать второе письмо, заказ или платёж. Разделите получение предложения модели и исполнение действия.
Составь retry policy для AI-workflow. Операции: [список]. Коды и типы ошибок: [список]. Побочные эффекты: [список]. Для каждой операции укажи: retryable true/false, максимум попыток как параметр, общий deadline, backoff, jitter, Retry-After, idempotency requirement, fallback и финальный error_code. Учти встроенные retries официального SDK, чтобы не создавать вложенные циклы.
Exponential backoff и jitter защищают от retry storm
Если тысячи клиентов повторят запрос через одинаковый интервал, они снова ударят по восстанавливающемуся сервису одновременно. Exponential backoff увеличивает задержку, jitter добавляет случайный разброс.
OpenAI рекомендует для временного 429 соблюдать Retry-After, а при его отсутствии использовать exponential backoff с jitter и ограничивать число попыток и суммарное время. Неудачные запросы тоже могут учитываться в rate limits. Проверьте, какие retries уже выполняет SDK.
Rate limits: управляйте потоком до ошибки
Лимиты могут считаться по requests, tokens, project, organization и model family. Средняя нагрузка ниже минутного лимита не исключает короткий burst. Используйте централизованный limiter, оценивайте размер запроса и оставляйте headroom.
Circuit breaker прекращает бессмысленные вызовы
В состоянии closed запросы проходят, а ошибки считаются в окне. После порога breaker переходит в open и быстро возвращает контролируемый fallback. Позже half-open пропускает ограниченные probe requests. Успех закрывает circuit, новый сбой снова открывает.
Microsoft подчёркивает, что retry ожидает скорое восстановление, а circuit breaker предотвращает повтор операции, которая, вероятно, продолжит падать. Breaker создавайте по независимому ресурсу: один provider, region, model или endpoint не должен блокировать здоровые.
Bulkhead изолирует tenants и типы работы
Один тяжёлый batch способен занять все connections и токенный лимит, оставив без ответа интерактивный чат. Разделите concurrency pools, queues и budgets по критичности, tenant и workload.
- Отдельная очередь для online и batch.
- Per-tenant concurrency и spend limit.
- Резерв capacity для критических сценариев.
- Ограничение размера prompt и output.
- Dead-letter queue после исчерпания попыток.
Fallback - не просто второе имя модели
- Поддерживаются нужные языки и модальности.
- Достаточен context window.
- Совместимы structured outputs и schema.
- Есть нужные tools и их семантика.
- Safety policy не ломает разрешённый сценарий.
- Регион и обработка данных допустимы.
- Prompt адаптирован к провайдеру.
- Fallback прошёл regression evals.
- Latency и стоимость укладываются в budget.
- Версия и причина маршрутизации логируются.
Multi-provider не гарантирует независимость
Два API могут зависеть от одного cloud region, DNS, identity provider, network egress или вашего общего gateway. Модели также могут использовать несовместимые schemas, tool calling и safety behavior.
Постройте dependency map и проверьте common-mode failures. Храните ключи и лимиты раздельно, но не дублируйте чувствительные данные в новый регион без разрешения.
Router принимает решение по policy, а не по случайной ошибке
| Сигнал | Маршрут |
|---|---|
| Primary здоров и в budget | Primary |
| Временный 429, есть deadline | Queue/retry или совместимый fallback |
| Primary circuit open | Fallback либо degradation |
| Чувствительные данные | Только разрешённый provider/region |
| Fallback не прошёл eval | Не использовать; human/manual path |
| Высокий риск | Draft или human approval |
Решение, provider, модель и policy version сохраняются в trace.
Graceful degradation: сохраняйте ценность, не притворяясь
Если полный режим недоступен, продукт может сократить функцию: вернуть cached справку с датой, отключить персонализацию, создать draft, принять задачу в очередь или передать человеку. Пользователь должен видеть ограничение.
Спроектируй degradation ladder для функции [описание]. Полный результат: [результат]. Критические ограничения: [список]. Доступные fallback-компоненты: [список]. Предложи уровни от полного режима до безопасного отказа. Для каждого укажи сохранённую ценность, отключённые возможности, сообщение пользователю, допустимые данные, SLO и условие восстановления. Не маскируй cached или неполный ответ под актуальный.
Idempotency и side effects в агентных workflow
Каждому внешнему действию назначьте idempotency key, сохраняйте состояние planned → approved → executing → succeeded/failed/unknown и проверяйте результат перед повтором. Timeout после отправки не доказывает, что действие не произошло.
Для unknown сначала выполните reconciliation по внешней системе. Не просите модель «попробовать ещё раз» без проверки.
Очереди, checkpoint и dead-letter
Фоновую работу помещайте в durable queue с ограниченными attempts и visibility timeout. Workflow сохраняет checkpoint между стадиями, чтобы после сбоя не повторять уже завершённую генерацию или tool.
После исчерпания попыток сообщение попадает в dead-letter queue с причиной, trace ID, версиями и безопасным payload reference. Нужны владелец, SLA разбора и controlled replay.
Наблюдаемость устойчивости
| Метрика | Что показывает |
|---|---|
| Attempts per task | Скрытую retry-нагрузку |
| Fallback rate | Зависимость от резервного пути |
| Circuit state/time open | Длительность отказа ресурса |
| Queue age/depth | Накопление работы |
| Degraded success | Часть запросов с урезанной функцией |
| Duplicate side effects | Проблемы idempotency |
| Quality by route | Регрессии fallback-модели |
Chaos-тесты до настоящего outage
- Connection timeout и потеря DNS.
- 429 с Retry-After и без него.
- Последовательность 500/503.
- Медленный streaming и обрыв ответа.
- Invalid JSON и schema mismatch.
- Refusal вместо ожидаемого объекта.
- Недоступная модель или регион.
- Исчерпанная quota и billing limit.
- Падение tool после успешной генерации.
- Timeout с неизвестным side effect.
- Переполненная очередь.
- Fallback с несовместимым feature.
Тест выполняют в staging или контролируемом production experiment без реальных опасных действий.
Runbook аварии AI-провайдера
- Подтвердить provider/model/region и масштаб.
- Проверить circuit, retries и очередь.
- Остановить retry storm и некритичный batch.
- Включить утверждённый degradation или fallback.
- Проверить data policy и качество резервного маршрута.
- Сообщить пользователям о затронутой функции.
- Контролировать backlog и side effects.
- Восстанавливать primary через limited probes.
- Вернуть трафик постепенно и сравнить метрики.
- Добавить regression и обновить capacity plan.
Финальный чек-лист отказоустойчивой AI-интеграции
- Failure modes классифицированы.
- Есть общий deadline и timeouts шагов.
- Retry разрешён только для transient faults.
- Учитываются встроенные retries SDK.
- Соблюдается Retry-After, backoff и jitter.
- Attempts и суммарное время ограничены.
- Circuit breakers разделены по ресурсам.
- Bulkheads защищают tenants и online traffic.
- Queue имеет DLQ и controlled replay.
- Tool calls идемпотентны.
- Unknown side effects проходят reconciliation.
- Fallback совместим по функциям и данным.
- Fallback прошёл те же evals.
- Degradation честно показан пользователю.
- Route и версии видны в traces.
- Есть alert, runbook и manual override.
- Chaos-сценарии регулярно прогоняются.
Цель устойчивости - не любой ценой вернуть текст. Система должна сохранить корректность контракта, безопасность данных и контроль действий даже тогда, когда основная модель недоступна.
Какие ошибки AI API нужно повторять?
Как правильно обрабатывать ошибку 429?
Что такое circuit breaker?
Чем circuit breaker отличается от retry?
Как выбрать fallback-модель?
Что такое graceful degradation для ИИ?
Как избежать двойного действия ИИ-агента?
Как тестировать отказоустойчивость AI API?
- OpenAI Help Center: Troubleshooting API rate limits and 429 errors
- OpenAI API: Request IDs and rate-limit headers
- Microsoft Azure Architecture Center: Circuit Breaker pattern
- Microsoft Azure Architecture Center: Transient fault handling
- Microsoft Azure Architecture Center: Retry Storm antipattern
- AWS Builders' Library: Timeouts, retries, and backoff with jitter