В системе с очередью CPU воркеров низок, но очередь растёт: какой сигнал масштабирования лучше отражает дефицит обработки?
Лучшим сигналом будет не загрузка CPU, а длина очереди, возраст самого старого сообщения или производная от них — например, требуемое число воркеров для удержания заданного времени ожидания. Низкий CPU не означает отсутствие дефицита: обработчики могут ждать внешнюю зависимость, ограничение параллелизма или медленно подтверждать сообщения.
Такое масштабирование связывает решение с пользовательским последствием — временем ожидания в очереди, а не с косвенным потреблением ресурса.
Ранние схемы автоматического масштабирования часто ориентировались на загрузку CPU или памяти, потому что эти метрики доступны почти для любого процесса и удобны для сравнения экземпляров. Такой подход хорошо работает для CPU-связанных вычислений, где рост нагрузки прямо увеличивает занятость процессора.
В системах с очередями пропускная способность определяется не только CPU. На неё влияют время обработки сообщения, внешние вызовы, лимиты базы данных, число параллельных операций и скорость подтверждения сообщений. Поэтому появились схемы масштабирования по бэклогу и времени ожидания.
Пусть поток сообщений поступает быстрее, чем текущий пул воркеров успевает их обрабатывать. Очередь будет расти, но CPU может оставаться низким: воркеры способны проводить значительную часть времени в ожидании сети, блокировок, ответа базы данных или свободного соединения.
Масштабирование только по CPU в этой ситуации не добавит экземпляры вовремя. Растут задержка обработки и риск истечения дедлайнов, повторной доставки сообщений, переполнения очереди и нарушения SLO по времени завершения операции.
Обратная ошибка тоже опасна: масштабирование по необработанному числу сообщений без учёта их сложности может создать слишком много воркеров и перегрузить общую зависимость. Поэтому сигнал должен учитывать не только объём работы, но и безопасную пропускную способность системы.
Основной сигнал — возраст самого старого сообщения. Он непосредственно показывает, как долго работа ждёт обработки, и хорошо связан с задержкой пользователя. Если важнее пропускная способность, используют длину очереди вместе с оценкой времени обработки одного сообщения.
Приближённо требуемое число воркеров можно оценить так: оно должно обеспечивать скорость обработки выше входной скорости с запасом, достаточным для сокращения накопленного бэклога. Для неоднородных сообщений полезнее учитывать не только количество, но и взвешенный объём работы: размер файла, ожидаемую стоимость операции или класс сложности.
Практическая схема обычно включает:
Одного мгновенного значения недостаточно: метрику сглаживают или требуют, чтобы нарушение порога сохранялось некоторое время. Иначе краткий всплеск создаст лишние экземпляры, а задержка масштабирования вниз может привести к постоянному дрожанию системы.
У очередей с несколькими группами потребителей сигнал нужно считать отдельно. Общая длина очереди может скрыть перегрузку одного класса сообщений, а средний возраст — скрыть редкие, но критичные сообщения. Для строгого SLO лучше масштабироваться по наиболее критичному классу или применять разные пулы воркеров.
CPU при этом не исключают из мониторинга. Он остаётся защитным сигналом: высокий CPU может ограничивать фактическую производительность, а низкий CPU при растущем возрасте сообщений указывает на ожидание внешнего ресурса или неверно выбранную модель параллелизма.
Сервис обрабатывал документы через очередь. Команда масштабировала воркеры по CPU: при загрузке выше 70% добавлялись экземпляры. После увеличения размера документов очередь стала расти, но CPU держался около 25%, поскольку основное время уходило на ожидание удалённого хранилища и базы данных.
Рассматривались три варианта. Увеличение порога и числа воркеров по CPU было простым, но не реагировало на реальную задержку. Масштабирование по длине очереди быстрее обнаруживало накопление, однако плохо учитывало разную стоимость документов. Масштабирование по возрасту самого старого сообщения лучше соответствовало целевому времени ожидания, но требовало корректного измерения возраста и ограничения максимального пула.
Выбрали комбинацию: возраст старого сообщения стал основным сигналом, длина очереди — дополнительным, а CPU и задержка внешних зависимостей — защитными ограничителями. Пул воркеров разделили по классам документов и ограничили суммарное число обращений к хранилищу. В результате масштабирование стало реагировать на нарушение времени ожидания, не создавая неконтролируемую нагрузку на зависимость.
1. Достаточно ли масштабироваться по длине очереди?
Нет. Одинаковая длина очереди может означать совершенно разное время ожидания, если сообщения имеют разную стоимость обработки или воркеры работают с разной скоростью. Поэтому длину очереди полезно сочетать с возрастом старого сообщения, классом работы и измеренной скоростью потребления.
Кроме того, при быстром потоке поступления очередь может быть короткой, но постоянно обновляться, а время ожидания — уже нарушать SLO. В таком случае возраст сообщений или непосредственно измеренное время ожидания информативнее одного размера очереди.
2. Почему добавление воркеров может не уменьшить бэклог?
У системы может быть общий ограничитель пропускной способности: лимит базы данных, внешнего API, соединений, диска или брокера сообщений. Дополнительные воркеры тогда лишь увеличивают конкуренцию, таймауты и количество повторных попыток, но не фактическую скорость обработки.
Перед увеличением пула нужно проверить, как меняется пропускная способность и задержка зависимостей. Если зависимость является узким местом, правильным решением может быть кэширование, пакетная обработка, разделение очередей, увеличение лимита зависимости или контролируемое ограничение потребителей.
3. Как избежать колебаний при автоматическом масштабировании?
Нужны гистерезис и разные условия для увеличения и уменьшения пула. Например, масштабироваться вверх после устойчивого превышения возраста сообщений, а уменьшаться только после более длительного периода низкого бэклога.
Также применяют минимальный и максимальный размер пула, задержку между изменениями и ограничение скорости масштабирования. Эти меры уменьшают риск цикла, при котором новые воркеры временно очищают очередь, затем удаляются, после чего следующий всплеск снова запускает дорогое масштабирование.