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

Почему фоновые задания начинают отставать
Большинство команд следят за задержкой модели и пропускают очередь перед воркерами. Один вызов модели может выглядеть достаточно быстрым сам по себе, но задания всё равно накапливаются, потому что работы приходит больше, чем пул успевает обрабатывать.
Это несоответствие может оставаться скрытым какое‑то время. Система продолжает принимать задания, пользователи продолжают нажимать, а очередь тихо растёт в фоне. К тому моменту, когда кто‑то замечает проблему, это уже не один медленный запрос. Это накопление, измеряемое в минутах или часах.
Повторы делают ситуацию хуже. Один неудачный вызов модели редко остаётся единственным. Тайм‑ауты, ограничения по частоте, некорректный вывод и вторичная валидация могут превратить одну задачу в две или три попытки. Каждая дополнительная попытка отнимает у воркеров время, которое могло бы пойти на новые задачи.
Небольшие задержки накапливаются лавинообразно. Если задания приходят каждую секунду и каждый воркер отстаёт всего немного, очередь не остаётся чуть‑чуть запоздавшей. Она растёт. Десять лишних секунд ожидания могут превратиться в сотни отложенных задач к следующему всплеску трафика.
Представьте пакетную задачу, которая создаёт резюме по тикетам поддержки. Обычно модель отвечает за 4 секунды, и команда думает, что у них запас по времени. Но полная обработка одного задания занимает 8 секунд, если учитывать сбор подсказки, парсинг, сохранение результатов и случайные повторы. Когда объём тикетов растёт в течение 20 минут, воркеры не успевают нагонять. Тикеты, которые должны были обработаться быстро, теперь стоят в очереди.
Команды часто замечают проблему только когда начинают срываться дедлайны. Отчёт пропускает окно отправки. Экспорт клиента завершается после рабочего времени. Рабочий процесс поддержки, который казался почти в реальном времени, внезапно застревает.
Именно поэтому планирование пула воркеров начинается с времени ожидания в очереди, а не с панели мониторинга модели. Если время ожидания очереди для фоновых задач продолжает расти, пул уже слишком мал для реальной нагрузки, даже если средняя задержка модели всё ещё выглядит приемлемо.
Числа, которые нужны перед подбором количества воркеров
Хорошее планирование ёмкости начинается с нескольких измерений, а не с догадки о том, сколько воркеров «кажется» правильным. Пропустите одно из них, и пул может выглядеть здоровым в тестировании, но отстать, как только трафик станет неравномерным.
Начните с времени в очереди. Измерьте разницу между созданием задания и его началом обработки для каждого типа задач. Это число показывает, когда спрос уже превышает предложение, даже если модель всё ещё отвечает в обычное время.
Затем замерьте полное время задачи, а не только вызов модели. Модель может занимать 8 секунд, но задача действительно может занимать 13, если включить сбор подсказки, парсинг, сохранение результатов, обновление состояния и отправку callback'а другому сервису. Воркеры заняты все эти 13 секунд, поэтому расчёты ёмкости должны опираться на полное время задачи.
Измеряйте время выполнения в спокойные и пиковые периоды. Задержка модели часто меняется под нагрузкой, и небольшие замедления быстро накапливаются. Задача, которая занимает 10 секунд в полдень и 16 секунд в пик, требует другого количества воркеров.
Повторы требуют отдельного учёта. Считайте, как часто задачи повторяются, и отслеживайте среднее число повторных попыток для тех, кто ретраится. Рейтинг повторов в 5% может добавить заметный объём дополнительной работы, когда очередь уже находится под давлением.
Соберите эти числа в одном месте:
- время ожидания в очереди от создания до начала обработки
- полное время выполнения задачи, включая работу вне модели
- время выполнения при нормальной и при пиковой нагрузке
- частота повторных попыток и среднее число попыток
- фиксированные накладные расходы, такие как записи в хранилище или callbacks
Простой пример показывает, почему это важно. Если одна задача тратит 7 секунд на модель, 2 секунды на парсинг и валидацию, 1 секунду на запись в базу, а повторы добавляют в среднем ещё 10% работы, реальная нагрузка ближе к 11 секундам на задачу, а не к 7.
Именно этот разрыв обычно ломает планы. Команды рассчитывают воркеров по задержке модели в одиночку, а затем удивляются, почему фоновые задания начинают отставать через неделю после запуска.
Измерьте, как приходят задачи
Большинство команд ошибаются здесь, потому что смотрят на среднее за день. Это число скрывает моменты, которые действительно вам вредят. Если за день приходит 20 000 задач, это не говорит о том, пришли ли они равномерно или скопились в один тяжёлый час.
Используйте самый загруженный час как базу, затем приглядитесь к числу задач в минуту внутри этого часа. Именно это число покажет, когда очередь начнёт расти.
Трафик обычно приходит из нескольких источников. Пользовательские действия создают постоянный поток, но всплески часто приходят откуда‑то ещё: плановой синхронизации, импорта CSV или ручного перезапуска задач после простоя.
Полезно разнести поступления по нескольким простым группам: постоянный пользовательский трафик, короткие всплески после действий в продукте, запланированные cron‑задачи, импорты и бэкиллы, и ручные перезапуски после сбоев. Считайте каждую группу в самый загруженный период, а не по всему дню.
Если приложение обычно получает 6 задач в минуту, но каждый час cron добавляет 120 задач за 10 минут, реальная скорость поступления в этот интервал намного выше. Подбирайте пул под эту нагрузку, а не под спокойные периоды.
Небольшая диаграмма помогает лучше большинства дашбордов. Логируйте время создания каждой задачи в течение недели, группируйте задачи по минутам и помечайте, откуда каждая пришла. Шаблоны появляются быстро: утренний пик, ежечасная партия или волна перезапусков после проблемы у провайдера.
Средние по дню делают нездоровые системы безопаснее, чем они есть. Минутные счёты в самый загруженный час показывают, успевают ли воркеры или начнёт накапливаться бэклог до того, как кто‑то заметит.
Замеряйте полное время задачи, а не только вызов модели
Вызов модели часто — лишь часть работы. Воркеры могут тратить время на скачивание входных данных, очистку текста, изменение размера изображений, вызов модели, проверку вывода и сохранение результатов. Если рассчитывать пул по латентности модели в одиночку, вы почти всегда окажетесь в дефиците.
Поставьте таймстемпы по полному пути задачи: получить вход, подготовить его, отправить запрос к модели и зафиксировать каждую повторную попытку, затем валидировать, пост‑обработать и сохранить результат. Это даст реальное сервисное время вместо оптимистичного варианта.
Не полагайтесь на среднее. Средние выглядят спокойно, даже когда очередь начинает дрейфовать. Отслеживайте p50 и p95 для каждого шага и для полной задачи. Если модель обычно возвращает ответ за 3 секунды, но p95 = 12 секунд, ваш пул воркеров должен выдерживать и 12‑секундный мир.
Небольшой пример проясняет это. Предположим, задача тратит 400 мс на скачивание файла, 700 мс на извлечение текста, 4 секунды на модель, 900 мс на исправление ответа и 200 мс на запись в базу. Вызов модели выглядит нормально сам по себе, но воркер занят больше 6 секунд, если весь поток обрабатывается блокирующе.
Каждому шагу дайте простую метку: делает ли он воркер занятым, или воркер в основном ждёт? CPU‑интенсивные шаги — парсинг, токенизация, OCR или очистка JSON — обычно полностью удерживают воркер. Внешние вызовы различаются. Если воркер отправляет запрос и блокируется до ответа — воркер занят. Если запрос передаётся дальше, а система опрашивает результат позже — воркер может быть свободен для других задач.
Эта разница важнее, чем кажется. Десять воркеров могут справиться с очень разной нагрузкой в зависимости от того, куда уходит время. Десять воркеров, занятых локальной CPU‑работой, не равны десяти воркерам, которые проводят половину времени в ожидании внешних API.
Как только вы знаете полное время задачи, p95‑хвост и какие части действительно держат воркер, ваши расчёты по размеру пула начнут соответствовать продакшену, а не желаемому сценарию.
Подбирайте размер пула шаг за шагом
Начните с одного обещания бизнесу: сколько времени задача может сидеть в очереди до начала обработки. Ночной отчёт может подождать дольше. Задача, видимая пользователю, обычно не может. Выберите этот лимит первым, потому что все последующие числа зависят от него.
Затем используйте самый загруженный час, а не среднее за день. Если задания приходят волнами в 9:00, рассчитывайте под эту волну. Команда, которая получает 600 задач за час, нуждается в совсем другом пуле, чем команда, у которой те же 600 разбросаны по дню.
Далее — полное время на задачу. Считайте сбор подсказки, чтение из БД, вызов модели, проверку результатов, записи и уборку. Если одна задача занимает 18 секунд от начала до конца и вы получаете 3 задания в секунду в пике, вам нужно около 54 активных воркеров одновременно.
Простейший метод размера работает хорошо:
- Установите целевое время ожидания в очереди.
- Измерьте пиковую скорость поступления.
- Умножьте скорость поступления на полное время задачи.
- Округлите в большую сторону.
- Добавьте запас мощности.
Этот запас важен. Если расчёт дал 54 воркера, не останавливайтесь на 54. Начните ближе к 65–70, если всплески часты. Небольшие пики, шумный трафик и разная длина задач быстро заполняют пул.
Повторы тоже требуют пространства. Если 8% задач повторяются один раз, нагрузка воркеров не остаётся постоянной. Периоды медленной модели усугубляют ситуацию, потому что пул тратит больше времени на каждую попытку, а в очередь поступают дополнительные повторы. Даже скромная частота повторов может перевести стабильную систему в состояние накопления.
Практическое правило простое: добавьте около 20% запасных воркеров для бурстового трафика, затем добавляйте больше, если повторы часты или задержка модели сильно колеблется.
Протестируйте число до запуска. Проведите нагрузочный тест, имитирующий реальный пик в течение нескольких минут. Наблюдайте за временем ожидания, загрузкой воркеров и числом повторов вместе. Если время ожидания продолжает расти, пул всё ещё слишком мал или оценка полного времени задачи была слишком оптимистичной.
Простой пример
Это становится понятнее, когда вы сведёте задачу к нескольким числам.
Предположим, команда импортирует 300 тикетов поддержки за 10 минут. Это означает 30 задач в минуту, или одна новая задача каждые 2 секунды.
Теперь разберите одну задачу по частям. Каждый тикет требует 12 секунд на подготовку и 18 секунд на вызов модели. Если остановиться на этом, полное время задачи — 30 секунд.
Здесь команды себя обманывают. Они часто рассчитывают воркеров по времени модели. При 10 воркерах и 18‑секундной модели математика выглядит нормально: каждый воркер может обработать около 3.3 задач в минуту, значит пул может примерно очистить 33 задачи в минуту.
Но модель — не вся задача. Реальное сервисное время — 30 секунд до учёта повторов. Это снижает способность 10 воркеров до примерно 20 задач в минуту.
Повторы опускают это ещё ниже. Если 8% задач попадают под лимит по частоте и повторяются один раз, средняя задача получает ещё 0.08 x 18 = 1.44 секунды модельного времени. Теперь средняя задача занимает около 31.44 секунды.
С таким реальным временем 10 воркеров могут завершать только примерно:
- 10 / 31.44 = 0.318 задач в секунду
- около 19.1 задач в минуту
- около 191 задачи за 10 минут
Очередь не появляется сама по себе. Она быстро растёт. Если приходит 300 задач, а завершается только 191, после окна импорта в очереди остаётся около 109 задач.
Теперь попробуйте 16 воркеров. С тем же средним временем задачи пул обрабатывает примерно 16 / 31.44 = 0.509 задач в секунду, или около 30.5 задач в минуту. За 10 минут это примерно 305 задач.
Это небольшое изменение имеет значение. 10 воркеров выглядят безопасно, если игнорировать подготовку и повторы. 16 воркеров успевают за поступлениями и держат время ожидания близко к цели, вместо того чтобы позволять накапливаться бэклогу.
Планируйте повторы и замедления
Повторы быстро меняют вашу математику. Если приходит 10 000 задач и у 8% из них есть одна повторная попытка, а у 2% — две, ваш пул не обрабатывает 10 000 прогонов. Он обрабатывает 11 200. Эти дополнительные 12% нагрузки могут превратить здоровую очередь в растущий бэклог.
Здесь многие команды ошибаются. Они считают только первые попытки, а затем удивляются, когда время ожидания растёт в час пик.
Причины обычно очевидны: лимиты по частоте у провайдера модели, тайм‑ауты, плохие входные данные, которые никогда не смогут успешно выполниться, или короткие провайдерские замедления, растягивающие задержку.
Обращайтесь с каждой причиной по‑разному. Повторяйте лимиты и тайм‑ауты. Не продолжайте ретраить плохие входы, если валидация может отсеять их до запуска задачи.
Backoff помогает, но только если вы ставите предел. Пул воркеров, который повторяет слишком быстро, может создать собственный всплеск трафика и снова попасть под тот же лимит. Используйте небольшой предел повторов, распределяйте попытки с backoff и небольшой долей случайности, а после достижения предела переводите неудачные задачи в dead‑letter или очередь на ручной разбор.
Пиковые медленные периоды тоже нужно учитывать в плане. Если обычное сквозное время задачи 20 секунд, а оно растёт до 35 секунд на полчаса, воркеры заняты намного дольше. Ёмкость падает, даже если скорость поступления остаётся прежней. Оставлять 20–30% запаса обычно дешевле, чем убирать бэклог потом.
Полезный тест — посчитать пул для нормального дня, затем прогнать его через плохой. Добавьте большую латентность, добавьте повторы и посмотрите, как долго время ожидания остаётся в пределах цели. Если ответ — «недолго», пул слишком тесный.
Пересматривайте план при каждом изменении подсказок, моделей или шагов рабочего процесса. Длиннее подсказка, новый вызов инструмента или дополнительная проверка могут добавить секунды к каждой задаче. Это изменение может показаться незначительным в тестах, но в масштабе съесть буфер, который вы считали имеющимся.
Ошибки, которые ломают план
Большинство команд делают расчёты по одному аккуратному среднему, а затем удивляются, почему очередь растёт. Средняя задержка модели скрывает медленный хвост. Если большинство запросов заканчиваются за 8 секунд, но небольшая часть занимает 40 или 60, эти медленные задачи держат воркеров намного дольше, чем предполагалось.
Проблема усугубляется, когда в дело вступают повторы. Тайм‑аут, 429 или некорректный ответ могут превратить одну задачу в две или три попытки. Если вы рассчитываете пул по среднему первому прогона, вы останетесь без ресурсов, как только провайдер замедлится.
Ещё одна распространённая ошибка — измерять только вызов модели. Реальные задачи также получают данные, собирают подсказку, валидируют вход, записывают результаты, обновляют базу и иногда зовут другие сервисы. Десять секунд на модель легко превращаются в двадцать секунд для полной задачи. Эта разница велика настолько, чтобы сломать расчёт количества воркеров.
Форма трафика тоже создаёт проблемы. Суммарное число за день может выглядеть спокойно, тогда как реальный паттерн поступления — всплескообразный. 20 000 задач в день звучит управляемо. Если половина из них приходит в 30‑минутный всплеск после события в продукте или плановой синхронизации, дневное среднее почти ничего не скажет.
Смешивание мелких задач с длинными в одной очереди — ещё один простой способ вызвать задержки. Короткая классификация не должна ждать за большой партией длинных сводок. Разделение очередей или хотя бы отдельных лимитов воркеров удержит мелкие задачи от застревания за тяжёлыми.
Несколько ранних признаков подскажут о проблеме:
- время ожидания в очереди растёт, даже если загрузка CPU воркеров низкая
- воркеры много времени тратят на повторы из‑за 429 или тайм‑аутов
- короткие задачи ждут за длинными пакетными задачами
- минутные счёты трафика выглядят резкими, а дневной — ровным
Ещё одна ошибка — добавлять воркеров, не проверив лимиты API. Больше воркеров не всегда означает большую пропускную способность. Если у провайдера модели есть ограничения на число запросов или токенов в минуту, дополнительные воркеры просто создают больше неудачных попыток и больше ожидания.
Лучше использовать p95 или p99 полного времени задачи, пиковый трафик, частоту повторов и лимиты провайдера вместе. Это число обычно менее приятное, чем среднее. Но именно оно не даст заданиям проскакивать.
Быстрая проверка перед запуском
У надёжного плана есть один простой тест: система остаётся спокойной в самый загруженный час. Средний трафик может скрыть плохую конфигурацию. Посмотрите очередь в самый ожидаемый пиковый час и проверьте, стартуют ли задачи в пределах целевого времени.
Не останавливайтесь на первом чистом прогоне. Добавьте ожидаемую в продакшене частоту повторов и проведите тот же тест нагрузки. Если воркеры теряют весь запас как только появляются повторы, пул слишком мал, даже если обычный трафик выглядит нормально.
Медленные периоды модели требуют отдельного теста. Короткий интервал повышенной латентности должен немного разрастить очередь, а затем очередь должна восстановиться. Если увеличение латентности на 30–50% удваивает бэклог и он остаётся высоким, вы слишком близко к краю.
Короткий предзапусковой чек‑лист:
- проверьте время ожидания очереди в самый загруженный час, а не только дневное среднее
- смоделируйте всплеск повторов и убедитесь, что у воркеров остаётся свободная ёмкость
- симулируйте более медленные ответы модели и измерьте время восстановления
- настройте оповещения по глубине очереди, возрасту старейшей задачи и частоте повторов
- решите, кто может приостановить новые задачи и когда это делать
Оповещения важнее, чем кажется. Если первое оповещение срабатывает только после того, как клиенты замечают задержки, оно опоздало. Установите раннее предупреждение о растущей глубине очереди и отдельное — для задач, которые слишком долго не начали обработку.
Ваша команда также должна иметь простое правило для отбрасывания нагрузки. Это может быть приостановка низкоприоритетных задач, уменьшение размера пакетной обработки или ограничение новых отправлений на несколько минут. Решите это до запуска, а не во время накопления бэклога.
Небольшим командам стоит держать правила простыми. Один дашборд, несколько порогов оповещений и таблица решений лучше сложной системы, которой ночью никто не доверяет. Если вы можете ответить на три вопроса — укладываемся ли мы в целевое время в очереди, есть ли у нас запас мощности, и кто приостанавливает новые задания при скольжении — вы почти готовы.
Что делать дальше
Рассматривайте планирование пула воркеров как операционную практику, а не разовую таблицу. Пул, который работал в прошлом месяце, может начать пропускать дедлайны после обновления модели, изменения подсказки или появления новой пакетной задачи.
Начните с одного дашборда, который показывает те несколько чисел, которые вам действительно нужны. Если время ожидания растёт, загрузка воркеров держится около 100%, и одновременно растут повторы — долгие дебаты не нужны. Пул слишком мал, задачи стали медленнее или и то, и другое.
Отслеживайте перцентильные времена ожидания в очереди, загрузку воркеров в пиках, частоту повторов по типу задачи и модели, а также общее время от постановки в очередь до окончательного результата. Просматривайте этот дашборд всякий раз, когда меняете модель, подсказку, рабочий процесс или правила повторов. Небольшие правки могут изменить пропускную способность сильнее, чем ожидают.
Перед каждой крупной партией или запуском проводите короткий нагрузочный тест. Не нужен огромный стенд — подайте реалистичный всплеск, наблюдайте время ожидания и убедитесь, что воркеры восстанавливаются после пика, а не остаются отстающими. Если очередь продолжает расти после окончания пика, исправьте план до прихода реальных задач.
Полезная практика: зафиксируйте текущие допущения. Запишите ожидаемую скорость поступления, обычную латентность модели, латентность в худшем случае, частоту повторов и число воркеров, которое должно держать линию. Это ускорит будущие проверки и сделает их менее эмоциональными.
Если хотите получить второе мнение по размеру пула воркеров или по окружению вокруг него, Oleg Sotnikov at oleg.is работает как Fractional CTO и консультант стартапов. Это помогает, когда реальная проблема распределена между дизайном очереди, политикой повторов, инфраструктурой и затратами в облаке, а не только числом воркеров.