MAATRIX / Блог / Нагрузочное тестирование раз в полгода: чтобы знать свой потолок заранее

Нагрузочное тестирование раз в полгода: чтобы знать свой потолок заранее

MAATRIX

Система месяцами держит обычную нагрузку без единого сбоя — и именно поэтому никто не может честно ответить, сколько она выдержит, если трафик вырастет вдвое. Узнавать это в момент реального всплеска — в разгар распродажи, после вирусного поста или в день, когда конкурент лёг и весь его трафик пришёл к вам — самый дорогой способ получить эту информацию. Регулярное нагрузочное тестирование даёт тот же ответ заранее, в контролируемых условиях, с возможностью откатиться и всё поправить до того, как это увидят реальные пользователи.

Зачем тестировать регулярно, а не когда прижмёт

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

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

Второй мотив — изменения. За полгода добавляются новые интеграции, разрастаются таблицы в базе, меняются паттерны использования, кто-то «временно» отключил кэш и забыл включить обратно. Потолок, измеренный год назад, может не иметь отношения к реальности сегодня — в любую сторону: он мог вырасти после оптимизаций, а мог незаметно просесть из-за раздувшейся базы или нового медленного эндпоинта, который никто специально не нагружал.

Полугодовой цикл — практический компромисс. Раз в квартал избыточно для большинства проектов без бурного роста, раз в год — слишком редко, изменения накапливаются незаметно. Раз в полгода вы успеваете поймать драматичные изменения архитектуры и при этом не тратите на это ресурсы каждый месяц.

Что считать «потолком» и как его определить по метрикам

«Потолок» — это не момент, когда сервер падает намертво. Обычно раньше наступает точка, где сервис формально ещё отвечает, но пользоваться им уже нельзя: растёт время ответа, начинают появляться таймауты и ошибки 5xx, очереди на бэкенде не успевают разгружаться. Практический потолок — это нагрузка, при которой один или несколько показателей пересекают заранее заданную границу:

  • p95/p99 времени ответа — если обычно p95 держится в районе 200–400 мс, а на тесте он уходит за 2 секунды, это уже не «чуть медленнее», а другой пользовательский опыт.
  • Доля ошибок — обычно фиксируют границу вроде 1% ошибок 5xx или таймаутов как условный «красный флаг», после которого тест дальше не имеет смысла продолжать в текущей конфигурации.
  • Насыщение ресурсов — CPU у веб-воркеров и БД, iowait на диске, число соединений в пуле к базе, длина очереди в брокере, использование file descriptors, память под кэш.
  • Насыщение сетевых очередей — backlog на приёме соединений, nginx начинает сбрасывать новые коннекты, если worker_connections или очередь listen исчерпаны.

Смотреть только на CPU — частая ошибка: сервер с CPU на 40% вполне может уже задыхаться по числу соединений к PostgreSQL или по очереди в Redis. Полезно заранее свести дашборд, где рядом лежат RPS/нагрузка (входной параметр теста) и все перечисленные метрики (реакция системы) — тогда точка излома видна визуально, без гадания по логам постфактум.

Важно зафиксировать не одно число «система держит N RPS», а профиль деградации: как ведут себя метрики на 50%, 80%, 100%, 120% и 150% от текущей типичной нагрузки. Часто выясняется, что деградация не линейная — до определённой точки всё стабильно, а затем система «падает со скалы» за считаные секунды. Знание именно этой точки перегиба — и есть цель теста.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Где тестировать: изолированная среда или прод в тихий час

Идеальный вариант — изолированное окружение, максимально близкое к продакшену по конфигурации: та же версия ОС, тот же размер инстанса, тот же пул соединений к базе, желательно — данные сопоставимого объёма (обезличенная копия или синтетика с реалистичным распределением). Здесь можно нагружать без оглядки на реальных пользователей, ловить падения, перезапускать сколько нужно.

Проблема изолированной среды одна, но фундаментальная: она никогда не идентична проду на 100%. Другой сетевой путь, другой сосед по гипервизору, другой объём данных в кэшах ОС и БД — и результат теста может как занижать, так и завышать реальный потолок. Если стенд для нагрузочного тестирования разворачивается заново под задачу, а не живёт постоянно, стоит опираться на регламент тестового окружения — например, на подход из статьи про регламент тестового окружения и стейджа: фиксированный процесс поднятия и синхронизации конфигурации экономит время на каждом цикле теста и избавляет от сюрпризов «на стейдже работало, на проде нет».

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

Практические меры для теста на проде:

  • Заранее предупредить всю команду и, если есть SLA, — ключевых клиентов о плановом окне.
  • Тестировать через отдельный домен/поддомен или явно маркированный трафик, чтобы легко отличить тестовые запросы от реальных в логах и алертах.
  • Иметь готовую кнопку «стоп» — скрипт нагрузки должен останавливаться по одной команде, а не ждать, пока сам добежит до конца сценария.
  • Договориться с дежурным заранее, чтобы плановый рост нагрузки не улетел как ложный инцидент.
  • Не тестировать операции с необратимыми побочными эффектами (реальные платежи, отправка писем и SMS) — для них нужен отдельный тестовый режим или нагрузка только на read-эндпоинты.

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

Как проводить тест: постепенное наращивание нагрузки

Резкий скачок сразу до предполагаемого максимума — плохая идея: он не даёт увидеть, где именно начинается деградация, а сразу переводит систему в аварийный режим, из которого сложно вытащить осмысленные данные. Правильный профиль нагрузки — ступенчатый рост со стабилизацией на каждой ступени.

Практическая схема (инструменты — на выбор: k6, Yandex Tank, Locust, wrk2, Gatling — принцип одинаковый):

Ступень 1: 50% от типичной нагрузки, 5 минут стабильно
Ступень 2: 100% (типичная нагрузка), 5 минут
Ступень 3: 150%, 5 минут
Ступень 4: 200%, 5 минут
Ступень 5: 250%, 5 минут — до первого выхода метрик за красные границы

Пример сценария на k6 со ступенчатым профилем:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '5m', target: 50 },
    { duration: '5m', target: 100 },
    { duration: '5m', target: 150 },
    { duration: '5m', target: 200 },
    { duration: '5m', target: 250 },
  ],
  thresholds: {
    http_req_failed: ['rate<0.01'],
    http_req_duration: ['p(95)<800'],
  },
};

export default function () {
  const res = http.get('https://staging.example.com/api/catalog');
  check(res, { 'status 200': (r) => r.status === 200 });
  sleep(1);
}

Пороги в thresholds — это как раз формализованное определение «красной границы» из предыдущего раздела: тест сам сигнализирует, когда система перешла из режима «работает» в режим «деградирует».

Во время прогона нужен второй монитор — не с графиком RPS теста, а с системными метриками: CPU и iowait по каждой ноде, число активных соединений к базе и их состояние (active/idle/idle in transaction для PostgreSQL), длина очередей в брокере, память. Если инфраструктура уже покрыта мониторингом — держите открытым тот же дашборд, которым пользуетесь для дежурств, а не собирайте картину заново под тест.

Отдельно стоит нагружать не только «типичный» сценарий (главная страница, каталог), но и тяжёлые операции — генерацию отчётов, экспорт, поиск со сложными фильтрами, загрузку файлов. Часто именно они, а не фронтовые страницы, первыми упираются в потолок, потому что синхронно грузят базу или диск. Про то, как ошибка в этой логике превращается в постоянную головную боль, хорошо показывает случай, разобранный в статье «тестовый нагрузочный скрипт три недели бил по проду» — там нагрузочный сценарий, оставленный без присмотра, показывает, зачем нужен именно управляемый, ограниченный по времени прогон, а не «включили и забыли».

Честная фиксация результата и что делать с находками

Самая частая причина, почему нагрузочное тестирование в компании умирает после первого-второго прогона, — неприятный результат, который никто не хочет записывать. Тест показал, что система падает уже при 130% типичной нагрузки вместо ожидаемых 300% — и вместо того, чтобы зафиксировать это как факт, отчёт превращается в «тест был не совсем корректным, environment отличался от прода, попробуем ещё раз позже». Это ровно та ловушка, о которой стоит помнить: смысл теста не в том, чтобы подтвердить ожидания, а в том, чтобы узнать правду, пока она ничего не стоит.

Что должно быть в отчёте по итогам прогона, независимо от результата:

  • Дата, окружение (стенд или прод), версия кода/конфигурации на момент теста.
  • Профиль нагрузки: с какого RPS/числа пользователей начали, с каким шагом росли.
  • Точка, где метрики впервые пересекли заданные пороги — конкретное число RPS или конкурентных пользователей.
  • Какой ресурс упёрся первым (CPU веб-слоя, пул соединений к БД, диск, память, конкретный внешний сервис) — это самое ценное в отчёте, потому что указывает, что чинить в первую очередь.
  • Сравнение с предыдущим прогоном (если есть): потолок вырос, упал или не изменился — и если изменился, то предположение, из-за чего.
  • Список находок, которые требуют действий, с приоритетом — не «когда-нибудь оптимизировать», а конкретные тикеты с владельцем и сроком.

Дальше результат используется в двух направлениях. Если потолок оказался ощутимо ниже, чем предполагалось — это повод либо оптимизировать узкое место, либо честно спланировать масштабирование до того, как трафик к нему приблизится, а не после. Здесь пригождается методика подбора конфигурации под нагрузку — например, из статьи как рассчитать конфигурацию сервера под нагрузку: зная точку излома, проще посчитать, какой запас нужен под реалистичный рост, а не закладывать «с запасом» наугад.

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

Регламент: как встроить тест в календарь раз в полгода

Тест, который проводится «когда вспомнили», по факту не проводится вообще — раз в полтора-два года, обычно после инцидента. Чтобы регулярность не зависела от чьей-то памяти, нагрузочное тестирование стоит оформить как обычный эксплуатационный регламент — со своим владельцем, датой и чек-листом, по аналогии с тем, как в инфраструктуре уже наверняка оформлены другие периодические процедуры.

Минимальный набор для регламента:

ПунктЗначение
Периодичностьраз в 6 месяцев, фиксированные месяцы (например, март и сентябрь)
Владелецконкретный человек/роль, а не «команда»
Где проводитсяизолированный стенд + контрольный прогон на проде в тихий час
Длительность окна1–2 часа на прод-тест, 1 рабочий день на полный цикл со стендом
Заранее предупредитьon-call, ключевые клиенты с SLA (если применимо)
Артефакт на выходеотчёт с найденной точкой отказа и списком задач
Что делать с находкамитикеты с приоритетом, ревью на следующем прогоне

Дата в календаре — не формальность, а страховка от того самого «отменим, слишком заняты в этом квартале», которое на практике превращает «раз в полгода» в «никогда». Полезно ставить тест не в разгар высокого сезона, а в спокойный период — по той же логике, что описана в материале про регламент планового обслуживания с окном простоя: заранее известное окно снижает и риск, и сопротивление команды самой идее «трогать прод по расписанию».

Отдельная грабля — тестировать «в лоб», без подготовки среды и без базового понимания архитектуры узких мест: результат такого прогона обычно бесполезен, а иногда и опасен для стабильности. Логику этой ошибки хорошо описывает статья про антипаттерн нагрузочного теста на ноутбуке разработчика — инструмент и масштаб генератора нагрузки должны соответствовать масштабу системы, иначе тест меряет не систему, а сам генератор.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Сколько нужно готовиться к первому нагрузочному тесту?

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

Можно ли тестировать сразу на проде без стенда?

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

Что делать, если тест уронил прод раньше, чем планировалось?

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

Нужно ли нагружать все сервисы сразу, если архитектура — микросервисы?

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

Как часто нужно тестировать растущий проект с частыми релизами?

Полгода — разумный базовый интервал, но если релизы кардинально меняют нагрузочный профиль (новая тяжёлая фича, миграция базы, смена архитектуры кэширования), имеет смысл добавить внеплановый прогон именно под это изменение, не дожидаясь календарной даты.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →