День 2694. #ЗаметкиНаПолях
Планирование Мощностей для API. Начало
Представьте митинг по релизу. Кто-то спрашивает: «Сможет ли API справиться с "чёрной пятницей"?» - тишина. Старший инженер говорит что-то вроде: «Скорей всего. Мы сейчас используем более мощные серверы», - и все переходят к следующему вопросу. Эта фраза — догадка, произнесённая уверенным голосом, а через 3 недели она превращается в инцидент в 2 часа ночи. Планирование мощностей — то, что поможет в этом случае дать реальный ответ. Не ощущение, а измеренное число с указанием условий измерения рядом с ним. Рассмотрим, как это сделать на практике в ASP.NET Core API.
Метрики CPU и памяти обманчивы
Многие планы загрузки ресурсов представляют собой всего два графика: CPU и память. У сервера есть запас по обоим параметрам, поэтому вывод: «всё в порядке». Затем трафик резко возрастает, и API сбоит, в то время как CPU загружен на 40%.
Дело в том, что проблемы, которые действительно возникают первыми, редко проявляются как перегрузка CPU:
1. Исчерпание пула соединений - приложение исчерпывает количество соединений с БД задолго до того, как БД исчерпает ресурсы CPU, и очередь запросов будет ожидать свободного соединения.
2. Голодание пула потоков - несколько блокирующих вызовов под нагрузкой приводят к тому, что пул потоков не может достаточно быстро расти, и задержка резко возрастает, даже если ни один ресурс не выглядит перегруженным.
3. Конкуренция за блокировки - горячая блокировка превращает параллельную работу в непрерывную обработку одного файла.
4. Задержка в очереди - фоновая обработка отстаёт, поэтому запись "успешно выполняется", но пользователь не видит результата в течение 30 секунд.
5. Коллапс задержки p95 - среднее значение по-прежнему выглядит отлично, но 1 запрос из двадцати выдаёт тайм-аут.
Таким образом, вопрос, на который отвечает планирование мощностей, не в том, "есть ли у нас свободные ресурсы CPU". Он более узкий и полезный: «Какой объем трафика может выдержать этот API, прежде чем качество обслуживания пользователей начнёт ухудшаться?»
Все остальное служит для ответа на этот вопрос.
Полезные для измерения показатели
Самая большая ошибка - отслеживание средней задержки. Средние значения скрывают тех, кто действительно страдает. Если средний ответ 80мс, а p99 — 4 секунды, значимая часть пользователей испытывает серьёзные проблемы.
Вот что важно отслеживать (в порядке убывания значимости для выявления реальных проблем):
1. Задержки p95 и p99 - в хвосте задержек источник проблем. p95 — ваш SLO; p99 – насколько всё плохо, в худших случаях.
2. Запросы в секунду (RPS) - для каждого класса конечных точек, а не одно глобальное число. Конечная точка чтения и конечная точка записи не имеют ничего общего.
3. Одновременные пользователи/запросы в процессе выполнения -
сколько запросов одновременно выполняется, что фактически создаёт нагрузку на пулы и потоки.
4. Частота тайм-аутов и частота ошибок - разница между «медленно» и «сломано».
5. Использование пула соединений с БД - наиболее распространённый скрытый потолок в API.
6. Глубина очереди и задержка обработки - для всего асинхронного, насколько отстают фоновые обработчики.
Если хотите добавить только один параметр на панель мониторинга, пусть это будет p95 для каждой конечной точки. Это сразу же меняет ситуацию.
Базовый цикл
Планирование мощностей — не документ, который вы пишете один раз. Это цикл, который вы запускаете, и он всегда выглядит одинаково:
1. Сначала определите SLO: «p95 менее 300мс, частота ошибок менее 1%» — это целевой показатель, по которому можно проводить тестирование. Зафиксируйте это число, прежде чем что-либо запускать, иначе вы будете изменять правила игры в зависимости от результатов.
2. Проведите тест на установившееся состояние (steady-state) при нагрузке, которая, по вашему мнению, отражает нормальный трафик. Это точка отсчёта.
3. Проведите тест на пиковую нагрузку с резким и быстрым нарастанием. Steady-state-тест показывает крейсерскую высоту; пиковая нагрузка показывает, что произойдёт, когда начнётся «чёрная пятница».
4. Найдите первое узкое место и устраните только его. Когда система даёт сбой, что-то выходит из строя в первую очередь. Исправьте это, затем проведите повторное тестирование — потому что исправление обычно просто перемещает потолок к следующему узкому месту, и нужно это заметить.
5. Заложите запас прочности, затем публикуйте. После того, как вы окажетесь в пределах SLO, заложите 30-50% запаса сверх ожидаемой пиковой нагрузки и запишите полученное число. Пиковая нагрузка, значения которой никто не знает, равносильна её отсутствию.
Продолжение следует…
Источник: https://thecodeman.net/posts/capacity-planning-for-dotnet-apis-from-guessing-to-measured-scaling
Post #3224
1.36K
- 👍 8