← Все статьи

Нагрузочное тестирование

Метрики нагрузочного тестирования: RPS, latency, percentiles и их правильная интерпретация

Разбираем ключевые метрики нагрузочного тестирования: RPS, latency, percentiles (P95, P99), error rate и другие. Показываю, как правильно их интерпретировать, почему average вводит в заблуждение и как по метрикам понять реальное поведение системы под нагрузкой.

нагрузочное тестированиеperformance testsperformance analysisload testingrpsметрики производительностиqaqa automationтестированиепроизводительность

Метрики нагрузочного тестирования: RPS, latency, percentiles и их правильная интерпретация

Вступление

В нагрузочном тестировании проблема почти никогда не в том, что «мы не можем запустить тест». Проблема — в том, что после запуска мы не понимаем, что означают цифры.

Перед тем как запускать нагрузочное тестирование, важно ответить на простой вопрос: а что именно мы будем измерять и зачем?

На практике часто происходит обратное. Тест запускают, получают набор графиков и цифр — и дальше начинается попытка «угадать», что всё это значит. Система выдержала нагрузку или нет? Стало лучше по сравнению с прошлым запуском? Где узкое место? Ответов нет, потому что изначально не было понимания, какие метрики важны и как их интерпретировать.

Метрики — это не просто цифры в отчёте. Это инструмент для принятия решений: сравнить результаты с бейслайном, понять поведение системы под нагрузкой и корректно выбрать профиль нагрузки. Без этого нагрузочное тестирование легко превращается в формальность — вроде что-то прогнали, но реальной ценности не получили.

Важно: метрики всегда зависят от цели теста

Один и тот же набор метрик может интерпретироваться по-разному в зависимости от типа тестирования.

В этой статье мы говорим про классическое нагрузочное тестирование (load), где цель — понять, как система ведёт себя при ожидаемой нагрузке: выдерживает ли она её, укладывается ли в SLA, есть ли запас.

Но если это стресс-тест — вас уже интересует, где система «ломается». Там нормой становится рост ошибок и деградация latency.

В тестах на отказоустойчивость (resilience / chaos) метрики читаются ещё иначе: ошибки и деградация допустимы, если система корректно восстанавливается.

Поэтому прежде чем анализировать цифры, всегда нужно зафиксировать контекст: что именно мы сейчас проверяем и какой результат считаем «нормальным».

1. Основные метрики отклика

Response Time (время отклика)

Когда говорят про производительность системы, почти всегда имеют в виду именно время отклика — сколько прошло от отправки запроса до получения полного ответа.

На первый взгляд всё просто. На практике — это одна из самых неправильно интерпретируемых метрик.

Главная проблема в том, что Response Time — это не одно число, а распределение значений. И если смотреть на него неправильно, можно прийти к полностью неверным выводам о системе.

Average Response Time (среднее)

Пример: Average response time

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

Классическая ситуация: 9 запросов отработали за 100 мс, один — за 5 секунд. Среднее получится около 590 мс.

Если смотреть только на average, создаётся ощущение, что система «тормозит».
Но в реальности 90% пользователей получили быстрый ответ.

Бывает и наоборот. Например, половина запросов — 100 мс, половина — 900 мс. Среднее около 500 мс выглядит «приемлемо», но фактически половина пользователей уже сталкивается с заметной задержкой.

Среднее значение удобно для общего ориентира, но на него нельзя опираться при принятии решений.

Median (P50)

Пример: Median Response Time

Медиана показывает, как ведёт себя «типичный» пользователь.

Это значение, ниже которого укладывается 50% всех запросов. В отличие от среднего, медиана почти не чувствительна к редким выбросам.

Если P50 = 120 мс — значит, половина пользователей получает ответ быстрее этого значения. Это хороший индикатор «нормального» поведения системы.

Но медиана не показывает проблем на хвостах — а именно там чаще всего и скрываются реальные деградации.

Percentiles (P90, P95, P99)

Пример: Percentiles (P90, P95, P99)

Процентили — это главный инструмент анализа времени отклика.

Например: P95 = 1500 мс означает, что 95% запросов завершились быстрее 1.5 секунды, а оставшиеся 5% — медленнее.

И именно эти 5% — это реальные пользовательские проблемы. Это те случаи, когда интерфейс «подвис», операция выполняется слишком долго или пользователь начинает повторно нажимать кнопку.

P99 показывает ещё более «тяжёлый хвост». Если он сильно отличается от P95, это сигнал, что в системе есть редкие, но очень долгие операции. На практике это часто:

  • блокировки в базе,
  • асинхронная обработка / очереди,
  • медленные внешние сервисы,
  • деградация под нагрузкой.

Именно поэтому в SLA почти всегда фигурируют процентили, а не среднее.

Min / Max Response Time

Пример: Min / Max Response Time

Минимум и максимум часто игнорируют, но они тоже дают полезный контекст.

Минимальное значение показывает «идеальный сценарий» — когда всё отработало быстро, без конкуренции за ресурсы.

Максимальное значение, наоборот, помогает быстро увидеть проблемы. Если max уходит в десятки секунд — это почти всегда таймауты, зависшие запросы или проблемы на уровне инфраструктуры.

Average vs Percentiles — короткое правило

Если смотреть только на среднее — можно легко обмануть себя и команду.

Если смотреть на P95 и P99 — становится видно, как система ведёт себя под нагрузкой на самом деле.

Именно поэтому в реальных проектах ключевые решения почти всегда принимаются по процентилям, а не по average.

2. Метрики нагрузки

Если метрики отклика отвечают на вопрос «насколько быстро работает система», то метрики нагрузки — это про «сколько она вообще может переварить».

И здесь тоже есть несколько распространённых заблуждений, которые регулярно ломают интерпретацию тестов.

RPS (Requests per Second)

Пример: Requests per Second

RPS — это количество запросов, которое система обрабатывает в секунду. По сути, это основной показатель пропускной способности.

Именно через RPS обычно оценивают, выдерживает ли система целевую нагрузку. Например, если сервис стабильно держит 100 RPS при P95 = 300 мс — это уже осмысленный результат, который можно сравнивать с требованиями или бейслайном.

Но важно понимать: RPS сам по себе ничего не говорит о качестве работы системы.

Можно легко получить высокий RPS ценой деградации:

  • растёт время отклика,
  • увеличивается количество ошибок,
  • пользователи начинают «ждать».

Поэтому RPS всегда нужно смотреть вместе с latency и error rate.

Throughput

Throughput часто путают с RPS, хотя это чуть более широкое понятие.

Если RPS — это количество запросов, то throughput может означать объём данных, проходящих через систему за единицу времени. Например, MB/s.

Это становится критичным в сценариях:

  • загрузки и скачивания файлов,
  • стриминга,
  • работы с большими payload’ами.

Два сервиса могут показывать одинаковый RPS, но радикально отличаться по throughput — просто потому, что один гоняет JSON на 1 КБ, а другой — файлы по 10 МБ.

Virtual Users (VUs)

Пример: Virtual Users

Virtual Users — это количество пользователей, которых вы эмулируете в тесте. Это не реальные пользователи, а их модель: сценарии, действия, задержки, последовательность запросов.

И здесь часто возникает первая ошибка: VU ≠ нагрузка. 100 VU — это не «100 запросов в секунду» и даже не обязательно «много».

Например, если каждый пользователь делает один запрос раз в 10 секунд, то: 100 VU → всего ~10 RPS.

И наоборот, 10 VU могут генерировать сотни RPS, если они работают без пауз.

Concurrent Users (одновременные пользователи)

Это количество пользователей, которые в конкретный момент времени активны: отправляют запрос, ждут ответ или находятся в процессе выполнения сценария.

Разница с VU тонкая, но важная. VU — это «сколько пользователей мы создали». Concurrent users — это «сколько из них сейчас реально нагружают систему».

Например, если у вас есть think time между действиями, часть пользователей в каждый момент времени просто «думает» и не создаёт нагрузку.

Поэтому 100 VU не означает 100 одновременных запросов.

Связка VU → RPS (ключевая мысль)

Один из самых частых вопросов: «Сколько нужно пользователей, чтобы получить 200 RPS?»

Ответ: зависит от сценария.

RPS — это производная от:

  • количества VU,
  • скорости выполнения сценария,
  • think time,
  • времени отклика системы.

Поэтому правильный подход — не «выставить VU», а контролировать RPS или хотя бы понимать, как он формируется.

Latency vs Response Time

Эти термины часто используют как синонимы, но между ними есть разница.

Latency — это время до получения первого байта ответа.
Response Time — это время до получения полного ответа.

В простых API разница может быть незаметной. Но в реальных системах (стриминг, большие ответы, медленные сети) она становится критичной.

Пример: сервер начал отвечать быстро (низкая latency), но сам ответ «льётся» 2 секунды. Пользователь всё равно ждёт эти 2 секунды — и для него важен именно response time.

3. Метрики ошибок

Если время отклика показывает, насколько быстро работает система, то метрики ошибок отвечают на более жёсткий вопрос: а работает ли она вообще стабильно под нагрузкой?

И здесь важно не просто увидеть «есть ошибки или нет», а понять их природу.

Error Rate

Пример: Failures per Second

Error Rate — это процент запросов, завершившихся с ошибкой.

На первый взгляд всё просто: если из 10 000 запросов 50 завершились неуспешно, значит error rate = 0.5%. Но ключевой момент — какие именно это ошибки.

Одинаковый error rate может означать совершенно разные проблемы:

  • 0.5% 500-х ошибок → система не справляется под нагрузкой
  • 0.5% таймаутов → система слишком медленная
  • 0.5% 4xx → возможно, проблема вообще в тестовых данных или сценарии

Поэтому сам по себе процент — это только сигнал. Разбираться нужно глубже.

HTTP Status Code Distribution

Распределение по статус-кодам — это первый шаг к пониманию, что происходит.

  • Если растут 5xx — почти всегда проблема на стороне сервера: перегрузка, ошибки в коде, проблемы с зависимостями.
  • Если растут 4xx — это уже вопрос к сценарию: невалидные данные, неправильная последовательность действий, истёкшие токены.

Типичный кейс: запустили нагрузку, увидели 10% ошибок — паника. Начали разбираться — оказалось, половина из них 401, потому что токен не обновлялся.

И это уже не проблема производительности.

Timeouts

Таймауты — один из самых неприятных типов ошибок. Они означают, что система не успела ответить за отведённое время.

И здесь важно понимать: таймаут — это не просто ошибка, это уже симптом деградации.

Часто это выглядит так:

  • растёт нагрузка,
  • увеличивается P95 / P99,
  • затем начинают появляться таймауты.

То есть таймауты — это, по сути, «продолжение» проблем с latency.

Connection Errors

Connection errors возникают ещё до обработки запроса — на этапе установки соединения.

Это могут быть:

  • проблемы с TCP,
  • ошибки SSL,
  • отказ в соединении (connection refused).

Такие ошибки часто указывают на инфраструктурные ограничения:

  • переполненные connection pool’ы,
  • лимиты на уровне балансировщика,
  • исчерпанные ресурсы (например, file descriptors).

Если при росте нагрузки начинают появляться connection errors — это почти всегда сигнал, что система «ломается» на уровне инфраструктуры, а не бизнес-логики.

4. Продвинутые метрики

Эти метрики реже обсуждают на старте, но именно они часто объясняют, почему система ведёт себя так, а не иначе.

Если базовые метрики отвечают на вопрос «что происходит», то продвинутые — «почему это происходит».

Think Time и Pacing

Think Time — это пауза между действиями пользователя. В реальной жизни никто не делает 10 запросов подряд без остановки: пользователь читает, думает, кликает.

В нагрузочном тесте это поведение нужно моделировать явно.

Если этого не делать, получается синтетическая нагрузка, которая не имеет ничего общего с реальностью. Например, 100 пользователей начинают «долбить» API без пауз — и система падает. Возникает вопрос: проблема в системе или в тесте?

Чаще всего — в тесте.

Pacing решает немного другую задачу. Это контроль частоты выполнения сценария одним пользователем. Например, можно задать, что один пользователь проходит сценарий не чаще одного раза в 10 секунд, независимо от того, как быстро он завершился.

На практике think time делает поведение реалистичным, а pacing — предсказуемым.

Dropped Requests и Retries

Под нагрузкой система может начать «отбрасывать» запросы.

Dropped requests — это ситуации, когда соединение разрывается или запрос не доходит до обработки. Часто это происходит на уровне балансировщиков или прокси, когда ресурсы исчерпаны.

Это важный сигнал: система уже не просто замедляется, она начинает терять запросы.

Retries — это обратная сторона. Клиент (или тест) может автоматически повторять запросы после ошибки.

И здесь кроется опасный эффект: система начинает деградировать → появляются ошибки → включаются ретраи → нагрузка ещё больше растёт → система деградирует ещё сильнее.

В итоге можно получить «лавину», когда сами ретраи усиливают проблему. Если в тесте используются retries, их нужно обязательно учитывать при анализе — иначе RPS и error rate будут искажены.

CPU Time per Request

Пример: использование CPU

Эта метрика показывает, сколько процессорного времени тратится на обработку одного запроса.

Её редко смотрят напрямую, но она очень полезна для понимания масштабируемости.

Простой пример: если один запрос требует 50 мс CPU, а у вас есть 1 CPU-секунда в секунду, то теоретический предел — около 20 RPS на ядро.

Если при росте нагрузки CPU стремится к 100%, а время отклика растёт — это явный признак CPU-bound системы. В этом случае горизонтальное масштабирование или оптимизация кода могут дать быстрый эффект.

Если же CPU загружен на 30%, а latency всё равно высокий — значит, узкое место где-то ещё: база данных, сеть, внешние сервисы.

Сводная таблица метрик (шпаргалка)

МетрикаЧто измеряетЗачем нужнаКак интерпретировать
Response TimeПолное время ответаОбщая производительностьСмотреть только в распределении, не как одно число
Average (avg)Среднее времяБыстрая оценкаЧасто вводит в заблуждение из-за выбросов
Median (P50)«Типичный» пользовательПонимание нормального поведенияХорошо показывает базовый UX, но скрывает проблемы
P90 / P95 / P99Хвосты распределенияSLA, реальный UXКлючевая метрика: показывает деградацию и проблемы
Min / MaxЛучший / худший кейсПоиск аномалийMax помогает ловить таймауты и зависания
RPSЗапросы в секундуПропускная способностьВсегда смотреть вместе с latency и error rate
ThroughputОбъём данных (MB/s)Data-heavy сценарииВажен для файлов, стриминга, больших payload
Virtual Users (VU)Количество пользователейМодель нагрузкиСам по себе ничего не значит без сценария
Concurrent UsersАктивные пользователиРеальная нагрузкаМожет сильно отличаться от VU
LatencyВремя до первого байтаСетевые и streaming сценарииМожет быть низким при высоком response time
Error Rate% ошибокСтабильность системыНужно анализировать по типам ошибок
HTTP Codes200 / 4xx / 5xxДиагностика5xx — сервер, 4xx — чаще сценарий
TimeoutsНеуспевшие ответыДеградацияОбычно следствие роста latency
Connection ErrorsОшибки соединенияИнфраструктураЧасто лимиты или перегрузка
Think TimeПаузы пользователяРеализм нагрузкиБез него тесты нереалистичны
PacingЧастота сценарияКонтроль нагрузкиДелает тест предсказуемым
Dropped RequestsПотерянные запросыКритическая деградацияСистема уже не справляется
RetriesПовторные запросыПоведение клиентаМожет усиливать нагрузку и искажать метрики
CPU / RequestCPU на запросМасштабируемостьПозволяет оценить предел RPS на ядро

Пример интерпретации

Представим, вы запустили нагрузочный тест и получили такие цифры:

  • RPS = 200
  • P95 = 950 мс
  • P99 = 1800 мс
  • Error Rate = 0.7%
  • CPU = 90%
  • RAM = 65%

Теперь самое интересное — как это читать.

Первое, на что стоит посмотреть — это связка RPS и latency. 200 RPS при P95 < 1 секунды — это, в целом, хороший результат. Система держит нагрузку и не уходит в критическую деградацию. Если это соответствует целевому профилю — уже неплохо.

Но дальше смотрим на P99. 1.8 секунды — это заметный разрыв с P95. Значит, есть «тяжёлый хвост»: небольшая часть запросов выполняется сильно дольше остальных. И это как раз те самые пользователи, которые будут жаловаться, что «иногда всё подвисает».

Следующий шаг — ошибки. 0.7% — вроде бы небольшая цифра, но в абсолютных значениях это уже ощутимо. При 200 RPS это примерно 1–2 ошибки в секунду. И вот тут важно не число само по себе, а природа ошибок.
Если это таймауты — значит, система не успевает обрабатывать часть запросов.
Если 5xx — возможно, уже есть деградация под нагрузкой.
Если 4xx — возможно, проблема вообще в сценарии.

Дальше — CPU. 90% загрузки — это почти потолок. Это сильный сигнал, что система близка к своему пределу. В таком состоянии любое увеличение нагрузки, скорее всего, приведёт к росту latency и ошибок.

И вот здесь появляется важный вывод: даже если сейчас «всё вроде нормально», запас по производительности почти отсутствует.

RAM при этом на уровне 65% — значит, память не является узким местом. Можно сфокусироваться именно на CPU: профилирование, оптимизация, масштабирование.

Итоговое чтение ситуации

Система в текущей точке работает стабильно, но уже на грани:

  • нагрузку держит,
  • но есть проблемы на хвостах (P99),
  • появляются ошибки,
  • CPU почти упёрся в лимит.

Это классический момент, когда тест ещё «зелёный», но инженер уже понимает:
дальше без оптимизации или масштабирования будет только хуже.

Заключение

Метрики сами по себе ничего не значат — важна их связка и правильная интерпретация. Именно это отличает «прогон нагрузки» от настоящего инженерного анализа системы.