Ёмкость и планирование нагрузки
Смоделировал обычную очередь: один обработчик, запрос обслуживается в среднем 10 миллисекунд, запросы приходят случайно. При загрузке 50% среднее время ответа 20,1 миллисекунды. При 90% - 99,2. То есть нагрузка выросла меньше чем вдвое, а ждать стали в пять раз дольше. А квантиль 0,99 - значение, ниже которого лежат 99% запросов, - вырос с 92,8 миллисекунды до 463,6.
Стержень: время ответа растёт не линейно с нагрузкой, а разгоняется у предела; поэтому планируют запас, а не «загрузим до сотни».
// Формулировки: «почему при 90% загрузки всё тормозит?», «сколько серверов нужно?», «как готовиться к пику?»
Почему нельзя загружать под завязку
Причина в случайности. Запросы приходят не ровным строем, а пачками, и обслуживаются тоже за разное время. Когда обработчик свободен половину времени, пачка рассасывается быстро. Когда он занят 90% времени, каждая пачка становится очередью, а очередь - это ожидание, которое добавляется к обслуживанию.
Полные числа моего замера: загрузка 50% - среднее 20,1 и квантиль 0,99 равен 92,8 миллисекунды; 70% - 32,8 и 146,3; 80% - 50,7 и 233,4; 90% - 99,2 и 463,6; 95% - 190,0 и 797,8. Обрати внимание: от 90% к 95% нагрузка выросла на пять процентов, а время ответа - вдвое.
// Отсюда практика планирования. Целятся в загрузку 50-70% в обычное время, чтобы был запас на пик и на потерю части мощности. Считают не по среднему, а по пиковой минуте: сервис, живущий в среднем на 40%, в вечерний час может быть на 85%. И помнят, что при отказе одной из трёх машин оставшиеся получают полуторную нагрузку - если они уже работали на 70%, то мгновенно окажутся за сотней.
- загрузка
- доля времени, которую обработчик занят
- очередь
- ожидание перед обслуживанием; именно она разгоняет время ответа
Сколько нужно и откуда берётся число
Базовый расчёт устроен просто. Если один экземпляр обрабатывает запрос за 10 миллисекунд, то на одном потоке это 100 запросов в секунду. Нужно держать 2000 - значит, нужно 20 обработчиков при стопроцентной загрузке, а с целевой загрузкой 60% уже 34. Плюс запас на отказ: если хотим пережить потерю одной машины из пяти, добавляем ещё четверть.
Второй вход в тот же расчёт - через число одновременных запросов. Среднее число запросов «внутри» сервиса равно потоку, умноженному на время обработки: 2000 в секунду по 50 миллисекунд - это 100 запросов одновременно. Это же число задаёт размеры пулов - заранее подготовленных запасов соединений к базе, потоков и рабочих мест.
// И два ограничения, которые ломают красивую арифметику. Первое: узкое место обычно не там, где считали. Прибавили экземпляров приложения - упёрлись в число соединений к базе. Второе: не всё масштабируется добавлением экземпляров. Один экземпляр базы на запись, одна часть потока сообщений, которую читает ровно один потребитель, один общий замок - это места, где добавление машин не помогает вовсе, и их надо знать заранее.
- пропускная способность
- сколько запросов в секунду тянет один обработчик
- число одновременных запросов
- поток, умноженный на время обработки; задаёт размеры пулов
Пики и скорость появления ёмкости
Готовность к пику держится на двух вопросах сразу: «сколько» и «как быстро». Автомасштабирование выглядит спасением, пока не посчитаешь время реакции: заметить рост (десятки секунд), принять решение, запустить машину или контейнер, дождаться прогрева приложения и наполнения кэшей. В сумме легко набегают минуты, а пик распродажи или рассылки приходит за секунды.
Отсюда разделение. Плавные предсказуемые изменения (день-ночь, будни-выходные) закрывают автомасштабированием. Известные заранее пики - предварительным увеличением по расписанию, за час до события. Внезапные всплески - запасом, который уже стоит и прогрет, плюс ограничением частоты запросов и очередями, которые превращают отказ в ожидание.
// И полезная привычка: проверять расчёт нагрузочным испытанием, а не верить арифметике. Тест ищет то, чего нет в формуле: узкое место в чужом сервисе, предел числа соединений, лишний поход в базу на каждый запрос. Заодно он даёт настоящие числа для планирования вместо оценочных.
- время появления ёмкости
- сколько проходит от роста нагрузки до готового обслуживать экземпляра
- предварительное увеличение
- поднять мощность заранее под известное событие
- ограничение частоты
- приём, превращающий отказ в ожидание или в вежливый отказ части запросов
Как отвечать: «Загрузка процессора 85%, время ответа выросло вдвое. Докупать сервера?»
Сначала проверю, что упёрлись именно в процессор, а не в число соединений к базе, диск или чужой сервис - узкое место редко там, где смотрят в первую очередь. Но само по себе поведение нормальное и ожидаемое: время ответа растёт не линейно, а разгоняется у предела. Я моделировал очередь с обслуживанием по десять миллисекунд: при загрузке 50% среднее время 20 миллисекунд, при 90% - 99, а от 90% к 95% оно ещё удваивается. То есть последние проценты загрузки стоят дороже всех предыдущих. Поэтому целюсь в 50-70% в обычное время и считаю по пиковой минуте, а не по среднему за сутки. И обязательно закладываю запас на отказ: если из трёх машин выпадет одна, оставшиеся получат полуторную нагрузку, и при исходных 70% они мгновенно окажутся за сотней.
Ответ сначала ставит под сомнение диагноз, потом объясняет нелинейность числами и заканчивается запасом на отказ. Это разговор про планирование, а не про покупку железа.
На чём валятся
- −Планируют загрузку под 90% и удивляются росту времени ответа.
- −Считают по среднему за сутки, а не по пиковой минуте.
- −Не закладывают запас на отказ: выпадение одной машины из трёх добавляет остальным половину нагрузки.
- −Надеются на автомасштабирование там, где пик приходит быстрее, чем поднимается экземпляр.
- −Верят арифметике без нагрузочного испытания и упираются в узкое место, которого не было в расчёте.
Проверьте себя
Пять вопросов из банка по этой подтеме. Всего их 6, остальные разбираются в тренажёре.
- Планируем ёмкость по средней нагрузке за месяц. Что не так с этим подходом?A)Среднее считают по неверному окну: нужно брать неделюB)Средние по разным сервисам не складываютсяC)Систему кладут пики, а среднее их прячетD)Среднее не учитывает рост числа пользователей за месяц
показать ответ и разбор
+C)Систему кладут пики, а среднее их прячет// разбор: Пользователи приходят волнами: утренний вход, обеденный всплеск, рассылка, распродажа. Сервис падает в пике, а среднее по месяцу об этом молчит — оно может быть вчетверо ниже. Планируют по пиковым значениям с запасом на рост и на отказ части ёмкости: если при выпадении одной зоны из трёх нагрузка перераспределится, оставшиеся должны выдержать.
- При загрузке 60% сервис отвечает за 100 мс, при 85% — за 800 мс, хотя ресурсы ещё есть. Почему так резко?A)Ошибка измерений: на высокой нагрузке метрики запаздываютB)У предела очередь растёт нелинейноC)Сборщик мусора включается только под нагрузкой и добавляет паузыD)Балансировщик при высокой загрузке переключается на резервные узлы
показать ответ и разбор
+B)У предела очередь растёт нелинейно// разбор: Время ответа складывается из обработки и ожидания в очереди. Пока утилизация невелика, очередь пуста и виден только сам расчёт; ближе к пределу каждая новая единица нагрузки добавляет всё больше ожидания — рост гиперболический. Потому целятся не в стопроцентную загрузку, а в 60-70% с запасом: он оплачивает всплески, деплои и отказ части мощностей.
- Ожидается всплеск от рассылки: трафик вырастет вшестеро за минуту. Почему нельзя положиться на автоскейл?A)Автоскейл ограничен числом реплик в манифестеB)Метрики нагрузки собираются раз в минуту и опоздаютC)Правила скейлинга не умеют реагировать на резкий ростD)Ёмкость приезжает минутами, зависимости — дольше
показать ответ и разбор
+D)Ёмкость приезжает минутами, зависимости — дольше// разбор: Между всплеском и готовыми подами лежат несколько шагов: сбор метрик, решение автоскейлера, планирование, загрузка образа, прогрев приложения, а при нехватке ёмкости ещё и заказ ноды. Это минуты, а всплеск случается за секунды. Плюс база и внешние API так быстро не растут вовсе. Под известный пик греют заранее: поднимают реплики по расписанию, прогревают кэши, ставят на входе очередь или ограничение скорости.
- Почему сервис не гоняют в проде близко к 100% утилизации, даже если «ресурсы же есть»?A)Так требуют лицензии на процессоры облакаB)У 100% выше энергопотребление на ваттC)Иначе метрики утилизации перестают собиратьсяD)Нужен запас на всплески, отказ узла и деградацию
показать ответ и разбор
+D)Нужен запас на всплески, отказ узла и деградацию// разбор: Работа на пределе не оставляет запаса: любой всплеск трафика, отказ ноды (её нагрузка переедет на соседей) или деградация зависимости мгновенно перегружают систему, а у предела задержка растёт нелинейно. Поэтому держат headroom — целевую утилизацию заметно ниже 100% (часто 50–70%), чтобы пережить пик и потерю части мощности без падения. Запас — это не «простой ресурсов», а купленная устойчивость.
- Нужно узнать реальный потолок сервиса до того, как в него упрётся прод. Как это выяснить?A)Прикинуть потолок по загрузке CPU на глазB)Подождать реального пика и замерить в продеC)Нагрузочным тестом найти «колено» — где растёт задержкаD)Взять цифры из документации библиотеки/фреймворка
показать ответ и разбор
+C)Нагрузочным тестом найти «колено» — где растёт задержка// разбор: Потолок находят нагрузочным тестированием: под контролем повышают запросы в секунду (или конкурентность) на реалистичном трафике и смотрят, где задержка/ошибки начинают расти нелинейно — это «колено», за ним система деградирует. Так узнают безопасный рабочий уровень и куда ставить лимиты/автоскейл заранее, а не ценой прод-инцидента. Прикидки по CPU и цифры из доков не учитывают ваш профиль нагрузки.
дальше
Теорию прочитали. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.