Что такое High-Load: определяем границы и ключевые метрики системы
Что такое High-Load: определяем границы и ключевые метрики системы
Представьте два сервиса. Первый — новостной портал, который отдает статичные страницы и обрабатывает 10 000 запросов в секунду. Второй — система распознавания лиц для умного города, к которой обращаются всего 50 раз в секунду. Какой из них является высоконагруженным?
Интуиция подсказывает выбрать первый вариант из-за красивой цифры. Но на практике новостной сайт можно раздавать через кэширующий CDN, вообще не нагружая сервера. А вот 50 потоков тяжелого машинного обучения заставят кластер из десятков мощных машин работать на пределе возможностей.
High-Load (высокая нагрузка) — это не конкретное число запросов в секунду. Это состояние системы, при котором её текущая архитектура перестает справляться с ростом нагрузки, и для дальнейшего масштабирования требуются качественные, а не количественные изменения.
Высокая нагрузка начинается там, где заканчиваются возможности одного физического сервера, базы данных по умолчанию или стандартного синхронного кода. Чтобы понять, в какой момент система переходит эту границу, инженеры используют специфический набор метрик.
Язык высоких нагрузок: базовые метрики
Невозможно проектировать архитектуру, опираясь на понятия «быстро» или «медленно». Нам нужны точные координаты.
- RPS (Requests Per Second) — количество запросов, которые система получает за одну секунду. Это показатель входящего потока.
- Throughput (Пропускная способность) — объем полезной работы или данных, обрабатываемых за единицу времени (например, мегабайт в секунду или транзакций в секунду).
- Error Rate (Уровень ошибок) — процент запросов, завершившихся неудачей (обычно это HTTP-статусы 5xx). В здоровой системе он стремится к нулю.
- Latency (Задержка или время ответа) — время, которое проходит от получения запроса до отправки ответа клиенту.
Именно с Latency связана главная ловушка для начинающих архитекторов.
Ложь среднего времени ответа
Представьте, что вы измерили время ответа вашего API для 100 пользователей. 99 из них получили ответ за 10 миллисекунд. Но один запрос, из-за блокировки в базе данных, выполнялся 5 секунд (5000 миллисекунд).
Если мы посчитаем среднее арифметическое, то получим около 60 миллисекунд. Глядя на эту цифру в дашборде, вы решите, что система работает отлично. Но реальность такова: один из ваших клиентов прямо сейчас смотрит на зависший экран и, скорее всего, закрывает приложение.
Чтобы видеть реальную картину, в высоконагруженных системах используют перцентили (percentiles).
- p50 (Медиана): 50% запросов выполняются быстрее этого времени. Это показатель того, что видит типичный пользователь.
- p95: 95% запросов выполняются быстрее этого времени.
- p99: 99% запросов укладываются в это время. Это показатель «хвоста» (long-tail latency) — самых проблемных и медленных запросов.
В SLA (соглашении об уровне обслуживания) серьезных систем всегда фигурируют перцентили. Например: «p99 должен быть меньше 200 мс». Это гарантирует, что 99 из 100 пользователей получат быстрый ответ.
Физика бэкенда: Закон Литтла
Метрики не существуют сами по себе. Они жестко связаны математическими законами. Главный закон, который должен понимать архитектор, пришел из теории массового обслуживания — это Закон Литтла.
Он связывает входящую нагрузку (RPS), время обработки (Latency) и количество одновременных соединений (Concurrency), которые сервер должен держать в памяти.
Где:
- — количество запросов, находящихся в обработке одновременно (Concurrency).
- — интенсивность входящего потока (RPS).
- — среднее время обработки одного запроса (Latency, в секундах).
Практический пример: Ваш сервис получает 1000 запросов в секунду (). База данных отвечает быстро, и время обработки запроса составляет 0.1 секунды (). Считаем: . В любой момент времени ваш сервер держит в памяти всего 100 активных соединений. С этим справится даже очень слабый сервер.
Но вдруг база данных начинает тормозить. Время ответа () вырастает с 0.1 до 2 секунд. RPS при этом не изменился. Считаем: . Количество одновременных соединений мгновенно подскочило до 2000. Каждое соединение требует оперативной памяти и процессорного времени. Серверу не хватает ресурсов, он начинает отклонять новые запросы (растет Error Rate), система падает.
Именно здесь кроется ответ на вопрос, почему язык Go стал стандартом для высоконагруженных систем. В языках вроде Python или Ruby (в традиционных синхронных фреймворках) на каждый запрос выделяется тяжелый процесс операционной системы. Сервер может упасть уже на нескольких сотнях одновременных соединений ().
В Go каждый запрос обрабатывается в легковесной горутине (goroutine), которая потребляет всего пару килобайт памяти. Go-сервер может легко держать десятки и сотни тысяч одновременных соединений, давая вам запас прочности при внезапных скачках Latency.
Насыщение и деградация
Когда система достигает предела своих возможностей, происходит насыщение (Saturation) — утилизация ресурсов (CPU, памяти, пропускной способности сети) приближается к 100%.
Важно понимать: деградация системы происходит нелинейно. Если загрузка CPU выросла с 50% до 60%, время ответа почти не изменится. Но когда загрузка переходит границу в 85-90%, запросы начинают выстраиваться в очередь внутри самого сервера. В этот момент Latency взлетает по экспоненте, а за ним, по закону Литтла, взлетает и количество открытых соединений. Возникает каскадный сбой.
Понимание того, как метрики связаны между собой, позволяет не просто констатировать факт падения сервера, а предвидеть его. В следующей главе мы разберем, что делать, когда система упирается в потолок ресурсов одного сервера, и чем вертикальное масштабирование отличается от горизонтального.
