28 нояб. 2025 г.·7 мин чтения

Штормы повторов в продуктах ИИ: остановите умножение сбоев

Узнайте, как штормы повторов в продуктах ИИ превращают краткие простои моделей в взрыв расходов и как ограничить повторы, настроить backoff и fallback‑сценарии, чтобы защитить пользователей и бюджет.

Штормы повторов в продуктах ИИ: остановите умножение сбоев

Как выглядит шторм повторов

Шторм повторов начинается с небольшой ошибки. Модель подтормаживает на несколько минут или возвращает таймауты и ошибки 5xx. По отдельности это может выглядеть управляемо.

Проблема появляется, когда приложение срабатывает неправильно. Вместо ожидания оно тут же повторяет каждый неудачный вызов. Второй запрос попадает на ту же перегруженную модель и тоже падает. Одна проблема быстро превращается в несколько.

В продуктах ИИ это быстро становится грязным делом, потому что одно действие пользователя часто запускает несколько обращений к модели. Один тап на кнопку может попросить модель прочитать сообщение, составить ответ, оценить намерение и написать краткое резюме. Если на каждом этапе при ошибке сразу идут повторы, одно действие создаёт кучу дополнительных запросов.

Краткий простой часто разрастается так:

  • Пользователи отправляют обычные запросы.
  • Модель замедляется или начинает возвращать ошибки.
  • Приложение сразу же шлёт повторы.
  • Очереди растут, и пользователи ждут дольше.
  • Некоторые пользователи кликают ещё раз, добавляя трафик.

Объём запросов растёт, а полезной работы становится меньше. Время ответа ухудшается. Частота ошибок остаётся высокой. Расходы растут, потому что система продолжает делать платные вызовы API, хотя пользователи всё ещё не получают ответов.

Графики сначала могут выглядеть обманчиво «здоровыми». Объём запросов взлетает. Воркеры остаются активны. Логи наполняются активностью. Но большая часть этой активности — пустая трата.

Вы обычно замечаете шаблон, когда вместе скачут несколько показателей: число запросов, время ожидания, потребление токенов и упавшие задания. Если ваша обычная нагрузка — 1 000 вызовов модели в минуту, и каждая ошибка даёт по два быстрых повтора, краткий простой может почти мгновенно поднять это до 3 000 вызовов в минуту. Если пользователи обновляют страницу или повторно отправляют запрос, число снова вырастет.

Именно поэтому простои моделей кажутся дороже, чем должны быть. Простой причиняет ущерб, но плохие правила повторов умножают этот ущерб. Пятиминутное замедление может оставить гораздо большую головную боль в приложении, очередях и в счёте.

Почему плохие правила повторов усугубляют простои

Простой модели редко остаётся малым, когда приложение слишком быстро отправляет повторы. Первый запрос падает, затем то же приложение посылает другой через секунду, потом ещё один. Если так делают тысячи пользователей одновременно, восстановление становится сложнее, а не легче. Вы просто добавляете трафик на ту же перегруженную модель.

Ущерб распространяется, потому что одно действие пользователя часто порождает несколько вызовов. Веб-запрос может повторяться в браузере, затем ваш API-сервер повторит его, затем фоновая задача — ещё раз. Каждый уровень думает, что помогает. Вместе они могут превратить один упавший промпт в три, шесть или десять запросов.

Долгие таймауты усугубляют ситуацию. Когда запрос висит 30 или 60 секунд, сервер занят — заняты память, воркеры и открытые соединения. Новые запросы ждут дольше, больше пользователей смотрят на крутилку, и больше повторов начинается до того, как старые завершатся.

Пользователи добавляют своё давление. Если приложение кажется зависшим, многие кликают снова. Они обновляют страницу. Они повторно отправляют то же сообщение. Теперь система борется и с простоем, и со второй волной реального трафика от людей, которые думают, что ничего не произошло.

Обычный паттерн падения прост и понятен:

  • Неудачные вызовы возвращаются до восстановления модели.
  • Разные части стека повторяют одну и ту же работу.
  • Длинные таймауты забивают воркеры и очереди.
  • Пользователи создают дубликаты, пытаясь снова.

Это порождает неприятную петлю обратной связи. Больше повторов — больше нагрузки. Больше нагрузки — более медленная система. Более медленная система даёт больше таймаутов, больше кликов и ещё больше повторов. Счёт может вырасти особенно сильно, если провайдер берёт плату за частичную работу, повторные запросы или токены, обработанные до ошибки.

Хорошее практическое правило — считать повторы ограниченным запасным планом, а не автоматическим рефлексом. Если модель перегружена, немедленное повторение того же вызова редко помогает — в основном вы просто увеличиваете трафик в самый неподходящий момент.

Как задать правила повторов, которые безопасны

Краткий простой должен оставаться кратким. Проблемы распространяются, когда каждый слой повторяет самостоятельно, одновременно и продолжает, даже когда шансы на успех уже упали.

Начните с жёсткого лимита по числу повторов. Для большинства пользовательских вызовов ИИ одной–двух повторных попыток достаточно. После этого вы обычно добавляете задержку, нагрузку и расходы без заметного улучшения для пользователя.

Интервал между попытками должен расти. Простая схема 1 секунда, затем 2, затем 4 работает гораздо лучше, чем повторы каждые несколько сотен миллисекунд. Быстрые циклы кажутся harmless в тестах, но они нагружают провайдера, который уже и так в беде.

Случайная задержка важна тоже. Если 5 000 запросов повторяются ровно через 2 секунды, они ударяют как единый пик. Добавьте небольшой джиттер, например 10–20% дополнительного ожидания, чтобы трафик распределялся, а не падал волной.

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

Безопасный набор по умолчанию обычно выглядит так:

  • Повторять только в одном слое, а не в клиенте и во всех воркерах.
  • Останавливать после 2 повторов.
  • Использовать экспоненциальный backoff с небольшим случайным джиттером.
  • Немедленно фейлить на ошибках 400 уровня (плохой ввод), проблемах с авторизацией и на исчерпании квоты.

Установите единый дедлайн для всего пользовательского действия, а не новый таймаут для каждого повтора. Если ответ чата должен уложиться в 10 секунд, каждая попытка должна вместиться в этот бюджет. Иначе запрос может висеть 30 секунд, всё равно падать и запускать лишнюю работу в фоне.

Здесь встречаются обработка простоев, backoff повторов и контроль затрат. Ограничение числа повторов, растущие задержки и единый дедлайн могут выглядеть консервативно на бумаге, но в инциденте они спасут вас от гораздо большей счёта.

Как ограничить трафик, прежде чем расходы выйдут из-под контроля

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

Начните с жёсткого потолка вызовов модели в минуту. Сделайте его достаточно низким, чтобы одна сломавшаяся функция не захлестнула ваш аккаунт, но достаточно высоким для нормального спроса. Размещайте лимит ближе к вызывающему коду, а не только у провайдера, чтобы все сервисы видели один и тот же знак «стоп».

Второй лимит должен учитывать деньги, а не только количество запросов. Дайте каждой функции, уровню подписки или арендаторам собственный бюджет на временное окно. Если внутренний суммаризатор сожрёт свой бюджет, он не должен красть средства у проверок платежей, фрод-ревью или ответов в поддержку, которые сейчас нужны пользователям.

Что делать, когда лимит срабатывает

Не продолжайте бить по модели в надежде на счастливый ответ. Ставьте низкоприоритетную работу в очередь, откладывайте её или отбрасывайте, если можно позже восстановить. Фоновые теги, большие резюме и массовый экспорт могут подождать. Сброс пароля, проверки платежей и передача живому агенту обычно не могут.

Вам также нужна зарезервированная полоса для критичных потоков. Разделите ёмкость заранее, а не в разгар инцидента. Например:

  • Зарезервируйте часть мощности для входа, платежей или передачи на поддержку.
  • Ограничьте фоновые задачи оставшейся ёмкостью.
  • Останавливайте трафик бесплатного уровня или пакетные задания раньше, чем трафик платных пользователей.
  • Истекайте устаревшие задания в очереди, чтобы старые задачи позже не затопили систему.

Пользователи переносят плохие новости лучше, чем молчание. Если лимит блокирует запрос, верните простое сообщение вроде «Ответы ИИ сейчас загружены. Мы сохранили ваш запрос и попробуем снова» или «Задача приостановлена из‑за перегрузки сервиса.» Это лучше, чем вечный спиннер, который повторяет попытки.

Ограничения кажутся строгими, но они дают пространство для восстановления. Они защищают ваш бюджет, сохраняют самые важные пути и не дают одному простою превратиться во вторую неисправность внутри вашей системы.

Простой пример на примере чат‑бота поддержки

Исправьте затратные правила fallback
Проверьте, соответствуют ли модели-заменители, бюджеты и интервалы повторов текущим требованиям.

В 9:05 утра 1 000 клиентов открыли чат поддержки, чтобы спросить, где их заказ. Бот отправил каждый вопрос провайдеру ИИ. Провайдер замедлился на две минуты. Ответы начали таймаутиться через 8 секунд, хотя некоторые запросы могли бы получиться, если бы приложение просто подождало немного дольше.

Чат‑бот использует распространённое правило: повторять каждый упавший запрос до трёх раз почти сразу. Это кажется безопасным при низком трафике. Во время замедления это превращает одну проблему в несколько.

Первые 1 000 запросов уходят. Многие падают. Приложение посылает 1 000 повторов. Они тоже падают, так что отправляется ещё 1 000, затем ещё 1 000. Краткий простой породил 4 000 платных вызовов вместо 1 000.

Математика простая:

  • 1 000 пользователей по одному вопросу.
  • 1 оригинальный вызов + 3 повтора = 4 вызова на пользователя.
  • 1 000 × 4 = 4 000 вызовов всего.

Пользователи всё ещё ждут. Служба поддержки всё ещё получает жалобы. Счёт в 4 раза выше, и дополнительный трафик делает провайдера медленнее для всех.

Более безопасная схема меняет форму всплеска. Поместите упавшие запросы в очередь вместо немедленных повторов. Используйте backoff, чтобы вторая попытка подождала 10 секунд, затем 30, потом, например, 60. Добавьте случайную задержку, чтобы повторы не обрушились одновременно.

Потом добавьте жёсткий лимит. Например, разрешите только 100 активных вызовов ИИ одновременно и не более 300 повторов в очереди. Если очередь заполнена, перестаньте повторять и отправьте простое сообщение: «Мы видим задержки. Пожалуйста, попробуйте снова через минуту.» Это сообщение намного дешевле, чем тысячи лишних вызовов модели.

В том же простое чат‑бот всё ещё испытывает трудности, но всплеск остаётся в рамках. Вы можете обработать 1 000 оригинальных запросов, повторить только ту небольшую долю, которая действительно важна, и не дать двум минутам замедления превратиться в тридцатиминутную катастрофу. Хорошие правила повторов не только защищают доступность. Они берегут ваш бюджет, когда что‑то идёт не так.

Ошибки, которые команды делают под давлением

Под давлением команды тянутся к простым решениям, и простые решения часто усугубляют простой. Паника плюс автоматизация причиняют большую часть ущерба.

Обычная ошибка — повторять в двух местах одновременно. Браузер повторяет из‑за спиннера, сервер повторяет из‑за ошибки у апстрима. Одно действие пользователя превращается в четыре, восемь или больше вызовов модели, прежде чем кто‑то заметит. Это быстро сжигает квоту и делает простой сильнее, чем он есть.

Команды также ставят один таймаут повсюду. Звучит аккуратно, но терпит неудачу в реальном трафике. Быстрый вызов классификации и длинное резюме не должны ждать одинаково. Если таймаут слишком короткий, здоровые запросы прерываются и повторяются зря. Если он слишком длинный, застрявшие запросы накапливаются и блокируют соединения.

Fallback‑сценарии тоже приносят проблемы. Переход на другую модель кажется безопасным, но может тихо удвоить расходы. В инциденте команды часто переходят с дешёвой модели на большую без суточного или поминутного лимита. Приложение может продолжать отвечать, но счёт взлетает за минуты.

Логи могут создать ещё одну неприятность, если переусердствовать. Если каждая ошибка сохраняет полные промпты, ответы и длинные трассировки стека, обработка ошибок сама по себе становится источником больших объёмов данных. Логи должны помогать дебагу. Они не должны становиться вторым источником расходов.

Ещё одна распространённая ошибка — трактовать 429 и 500 одинаково. Это разные проблемы. 429 означает, что провайдер просит снизить трафик прямо сейчас, поэтому агрессивные повторы только усугубят ситуацию. 500 может пройти при следующей попытке, но даже здесь нужны интервалы, лимиты и жёсткая остановка.

Когда команды сохраняют спокойствие, правила обычно упрощаются:

  • Повторять в одном слое, а не в двух.
  • Устанавливать таймауты по задачам.
  • Поставить бюджет на каждый путь fallback.
  • Логировать достаточно для дебага, затем сэмплировать или урезать остальное.
  • Сильно замедляться на 429, а повторы на 500 держать редкими.

Простые правила экономят деньги. Они также делают графики инцидентов проще для чтения, когда команда устала и догадывается.

Быстрые проверки перед релизом

Урезать лишние вызовы ИИ
Сфокусируйте расходы на действительно важных запросах во время замедлений провайдера.

Большинство команд тестируют «счастливые сценарии» и на этом останавливаются. Так штормы повторов и попадают в продакшен.

Перед запуском посчитайте, какое максимальное число вызовов может породить одно действие пользователя. Один клик в чате может задеть модель, фильтр безопасности, шаг поиска, сервис логирования и вторую модель для форматирования. Если каждый слой повторяет три раза, один упавший ответ может превратиться в десятки платных запросов.

Запишите худший сценарий, а не средний. Повтор в фронтенде плюс повтор в API плюс повтор фоновой задачи — именно там команды обычно обгорают.

Короткая предполётная проверка помогает:

  • Проследите одно действие пользователя от клика до финального ответа и посчитайте максимальные API‑вызовы.
  • Выделите ошибки, которые никогда не должны повторяться: плохой ввод, проблемы авторизации, исчерпание квоты и строгие проверки валидации.
  • Тестируйте медленный отказ, а не только поломку. Добавьте задержку провайдера в 10 секунд и посмотрите, что делает ваше приложение.
  • Настройте алерты по скорости запросов, частоте ошибок, латентности и сигналам расходов, чтобы команда узнала о проблеме до того, как счёт подскочит.
  • Дайте продукту и поддержке простое сообщение‑заглушку, чтобы пользователи получали ясный ответ, когда модель недоступна.

Тест с задержкой ловит больше багов, чем многие команды ожидают. Провайдеру не нужно полностью падать, чтобы нанести ущерб. Если ответы застревают на 10 секунд, нетерпеливые пользователи кликают снова, таймауты накапливаются, воркеры заняты, и логика повторов может начать срабатывать, пока первый запрос ещё жив.

Сообщение‑fallback тоже важно. Если поддержка говорит «попробуйте позже», а приложение в фоне повторяет запросы, пользователи могут удвоить нагрузку, не понимая этого. Лучше прямо: сервис сейчас медленный, ваш запрос может занять больше времени, повторные попытки не ускорят его.

Проводите эту проверку перед каждым релизом, который трогает вызовы моделей, очереди или правила таймаутов. Это займёт меньше часа и может сберечь неделю уборки инцидентов и неприятный счёт.

За чем следить во время инцидента

Проверить инфраструктуру ИИ
Помощь с наблюдаемостью, деплоем и оптимизацией облачных затрат для продакшен-систем ИИ.

Когда шторм повторов начинается, основная проблема — скорость. Небольшая ошибка модели может превратиться в всплеск трафика за несколько минут, и обычные дашборды могут это скрывать, если показывают только часовые или суточные тренды.

Смотрите на повторы как на отдельный сигнал, а не просто на общий объём запросов. Разбивайте их по фиче, модели и сегменту клиентов. Если один рабочий процесс, один провайдер модели или одна группа клиентов даёт большую часть повторов, вы можете быстро снять нагрузку, не замедляя всё остальное.

Полезное представление инцидента должно отвечать на пять вопросов:

  • Как быстро растёт скорость повторов по каждой фиче и модели?
  • Растут ли очереди, таймаутятся ли задачи или сбрасывается работа?
  • Каковы текущие расходы в минуту?
  • Возвращает ли fallback больше запросов, чем повторы?
  • Сколько времени системе требуется, чтобы успокоиться после включения лимитов?

Глубина очереди важна, потому что показывает давление ещё до жалоб пользователей. Если очередь растёт 10 минут подряд, воркеры уже отстают. Процент таймаутов показывает, висят ли вызовы достаточно долго, чтобы создавать дополнительные повторы. Сброшенная работа важна не меньше. Если система начинает отбрасывать задания, нужно понимать, какие и кто пострадал.

График расходов в минуту часто отсутствует. Суточные траты выглядят спокойно, пока счёт жжёт в реальном времени. Во время простоя плохое правило повторов может превратить час за 20 долларов в час за 200. Команды, которые отслеживают живые расходы, могут принимать более точечные решения, например отключить одну дорогую функцию вместо всего продукта.

Сравните успешность после fallback и после повтора. Это один из самых ясных способов понять, помогают ли ещё повторы. Если повторы удачны в 3% случаев, а fallback — в 40%, дополнительные повторы лишь увеличивают нагрузку и расходы.

Время восстановления говорит, работают ли ваши контролы. После ограничения трафика, ограничения клиентов или сокращения очередей измерьте, сколько времени нужно, чтобы таймауты, бэклог и расходы вернулись в норму. Если восстановление затягивается, лимит может быть слишком мягким или зависшие задания всё ещё давят на систему.

Во время реального инцидента простое лучше сложного. Пять понятных графиков на одном экране помогут больше, чем двадцать трудночитаемых при стрессе.

Что делать дальше

Начните с карты, а не с заплаты. Большинство команд знают основной вызов модели, но пропускают побочные треки: фоновые суммаризаторы, проверки модерации, embeddings, проигрывание упавших задач и инструменты поддержки staff. Поместите все вызовы модели на одну страницу с тремя пометками рядом: кто их вызывает, как часто они выполняются и что происходит при ошибке.

Эта карта обычно показывает, где начинается беда. Небольшой простой редко остаётся небольшим, когда один и тот же запрос может отскакивать через код приложения, воркеры очереди, cron‑задачи и SDK провайдера.

Затем исправьте самый загруженный путь сначала. Если один чат‑запрос может породить три повтора в разных слоях, урежьте эту цепочку сейчас. Выберите одно место, которое отвечает за повторы, задайте жёсткий лимит повторов и добавьте лимит расходов для пути с наибольшим трафиком. Простой жёсткий лимит лучше хитрого правила, безудержно срабатывающего в 2:00 ночи.

Короткое упражнение по простоям расскажет вам больше, чем длинный документ. Смоделируйте фальшивые 429 и таймауты в тестовой среде и посмотрите, что происходит. Проверьте, накапливаются ли запросы, кликают ли пользователи повторно, остаются ли fallback‑решения дешёвыми и срабатывают ли оповещения достаточно рано.

Держите чеклист коротким:

  • Перечислите все вызовы модели и все автоматические повторы.
  • Поставьте строгие лимиты для самого загруженного пользовательского потока.
  • Добавьте лимиты расходов, капы очередей и kill‑switch.
  • Проведите одно упражнение с фальшивыми 429 и таймаутами на этой неделе.

Если у вашей команды логика повторов уже разбросана по SDK, воркерам и внутренним сервисам, внешний аудит может сэкономить время. Oleg Sotnikov через oleg.is работает как fractional CTO и консультант стартапов и помогает компаниям ужесточить правила повторов ИИ, запасные пути, инфраструктуру и контроль затрат до того, как следующий инцидент превратится в большой счёт.