Нагрузочное тестирование чаще всего вспоминают в двух ситуациях: перед крупным маркетинговым запуском или уже после того, как прод лег. В итоге тесты делаются в спешке, на глазок, без цели и методики. Результат предсказуем: красивые графики, которые мало что говорят о реальной устойчивости продакшена.
В этой статье разберем практический подход к нагрузочному тестированию для веб‑проектов: чем отличается staging от prod, какие типы тестов действительно полезны, как использовать k6 и wrk, и как выстроить процесс так, чтобы он работал регулярно, а не «раз в катастрофу».
Зачем вообще нужно нагрузочное тестирование
Главная цель нагрузочного тестирования — не «сломать сервер», а понять, как система ведет себя при разных уровнях нагрузки и где именно начинаются проблемы. Это не только про CPU и RPS, но и про:
- задержки на каждом слое (балансировщик, веб‑сервер, PHP/Node/Python, база, кеши);
- ограничения по файловым дескрипторам и соединениям;
- ошибки уровня приложения (тайм‑ауты, дедлоки, «too many connections»);
- деградацию UX при пиках нагрузки (рост TTFB, долгие запросы).
Важно четко разграничить:
- нагрузочное тестирование — проверяем работу в ожидаемом диапазоне (например, до 2000 RPS) при разумном времени отклика;
- стресс‑тест — выясняем, где система ломается и как именно;
- тест стабильности / долговременный тест — проверяем утечки памяти, перегрев кэшей, деградацию индексов.
Без этой терминологии на практике все называют «нагрузочным тестом», а потом сложно интерпретировать результаты.
Staging против prod: почему нельзя верить только стенду
Идеальный сценарий — staging полностью копирует prod: такие же ресурсы, версия ОС и пакетов, конфиги Nginx/Apache, версии PHP и библиотек, та же схема базы и сопоставимый объем данных.
На практике staging обычно проще и дешевле: меньше CPU и RAM, урезанные лимиты, обрезанный дамп БД. Отсюда типичные ловушки:
- индексы и статистика в БД не совпадают с продом;
- случайные таблицы заметно меньше, чем в реальности;
- отключены фоновые воркеры, очередь, планировщик задач;
- другая версия ядра/библиотек или PHP‑расширений.
В итоге тесты на staging дают красивую цифру «держим 3000 RPS», а прод ложится уже на 800 реальных запросах, да еще и с другим распределением типов запросов.
Staging — это площадка для экспериментов и обкатки изменений. Но подтверждать гипотезы о предельной нагрузке и деградации все равно приходится на проде, аккуратными и безопасными методами.
Минимальные требования к полезному staging
Чтобы результаты нагрузочного тестирования на staging хоть как‑то коррелировали с продом, имеет смысл придерживаться нескольких правил:
- Та же версия кода, что и на проде (именно та ветка/релиз).
- Та же конфигурация Nginx/Apache, PHP‑FPM, базы, Redis/Memcached.
- Похожий объем данных и структура (копия прод‑БД с обезличиванием персональных данных, если нужно).
- Аналогичная топология: балансировщик, воркеры, отдельный сервер БД, очереди — пусть и меньшего размера, но с теми же ролями.
- Включены все фоновые процессы, которые есть на проде (очереди, крон‑задачи, обработка событий).
Если хотя бы эти пункты соблюдены, относительные выводы по staging (какая конфигурация лучше, помогает ли кеш, какие индексы полезны) часто переносятся на прод почти один в один.
Если ваш текущий проект еще живет на простом shared‑тарифе, а нагрузочные тесты уже упираются в лимиты соседи‑по‑серверу, имеет смысл заранее планировать переезд на отдельный VDS‑сервер, где можно гибко управлять ресурсами и конфигурацией под тесты.
Типы тестов: что действительно нужно веб‑проекту
Для типичного веб‑приложения (PHP, Node.js, Python, Go, Java — не критично) полезны три класса тестов:
- Smoke / sanity нагрузка — небольшой стабильный поток запросов, чтобы убедиться, что стенд вообще работает под нагрузкой и нигде не падает.
- Нагрузочный тест в диапазоне ожиданий — постепенный рост нагрузки до планируемых пиков с замером времени ответа и ресурсов.
- Стресс‑тест — выход за пределы нормального диапазона, чтобы увидеть, как именно система деградирует и где узкое место.
Отдельно можно и нужно выделять:
- longevity / soak тесты (например, 12–24 часа) — ловят утечки памяти, переполнение пулов, разрастание логов.
- регрессионное нагрузочное тестирование — сравнение результатов до/после изменений конфигурации или релиза.

Если вы уже планируете миграцию с одной площадки на другую, полезно заранее продумать стратегию нагрузочных прогонов и переключения трафика. Об этом подробнее можно почитать в материале про переезд сайта без даунтайма и потери трафика.
Инструменты: зачем два разных — k6 и wrk
Существует десяток популярных инструментов, но сочетание k6 и wrk покрывает большинство реальных задач для веб‑проектов.
wrk: синтетика и «пределы железа»
wrk — это высокопроизводительный HTTP‑генератор нагрузки, который отлично показывает потолок RPS при простых сценариях (например, один URL или небольшой набор URL, без сложной логики).
Когда он полезен:
- оценить «сырой» предел по RPS для статики или простой API‑ручки;
- померить эффект от оптимизаций на уровне веб‑сервера (Nginx, кеширование, компрессия, HTTP/2);
- сравнить конфигурации (разные
worker_connections,keepalive_timeout, буферы и т.п.).
Минусы wrk:
- сложно моделировать сложные пользовательские сценарии (логин, корзина, чек‑аут);
- нет «из коробки» интеграции с CI/CD, сложнее хранить сценарии как код;
- меньше метрик по бизнес‑уровню (процентили, пользовательские теги, сценарии).
Поэтому wrk хорошо использовать как «осциллограф» для бэкенда и сети, а не как единственный инструмент нагрузки.
k6: сценарии, CI и ближе к реальному трафику
k6 — инструмент нагрузочного тестирования с декларативными сценариями на JS. Он позволяет описывать почти реальное поведение пользователей:
- переходы по страницам;
- логин и использование токенов;
- разные типы запросов и вероятность их появления;
- распределения пауз между действиями.
Плюсы k6 для практики:
- сценарии — обычные файлы в репозитории, можно ревьюить и запускать из CI;
- поддержка сложных сценариев, параметров, data‑driven тестов;
- удобная работа с метриками: p95/p99, кастомные метрики, теги;
- возможность отдавать метрики во внешние time‑series хранилища и дашборды.
Идеальная связка в реальных проектах: wrk используют для тонкой доводки HTTP‑стека и бэкенда, k6 — для сценарных тестов, близких к прод‑нагрузке.
Базовая методика: от реального трафика к профилю нагрузки
Самая большая ошибка — запускать тесты с «круглым» числом запросов в секунду (100, 1000, 5000) без связи с реальными логами.
Нужно начать с анализа текущего прод‑трафика:
- какой средний RPS в будни и в выходные;
- какие пики встречаются в течение дня (например, утренний и вечерний всплески);
- какое распределение типов запросов (страницы, API, поисковые запросы, POST‑операции);
- какие медианы и p95/p99 времени ответа сейчас, без теста.
По логам nginx/apache или метрикам из Prometheus/Graphite можно примерно восстановить профиль:
- базовая нагрузка — например, 200–300 RPS;
- типичный пик — 800–900 RPS вечером;
- максимальный исторический пик — 1200 RPS, раз в месяц.
Из этого строим целевой сценарий нагрузочного тестирования:
- нагрузочный тест до +30–50% от типичных пиков (например, до 1500 RPS);
- стресс‑тест до момента деградации (возможно, 2000–2500 RPS) с фиксированными шагами роста;
- выделение особо тяжелых ручек (по логам) и отдельные тесты на них.
Практический пример: wrk для оценки предела простого API
Предположим, у нас есть простая API‑ручка /api/v1/search, которая возвращает JSON. Мы хотим понять, как меняется RPS при оптимизациях Nginx и backend‑кеша.
Базовый сценарий с wrk может выглядеть так (упрощенно):
wrk -t4 -c200 -d60s --latency /api/v1/search?q=test
Где:
-t4— четыре потока генератора;-c200— 200 одновременных соединений;-d60s— длительность теста 60 секунд;--latency— включить подробную статистику по задержкам.
Порядок действий при оптимизации:
- Замер до изменений, фиксируем RPS, среднее время ответа и процентили.
- Вносим одну конкретную оптимизацию (например, включаем кеш в Nginx или меняем лимиты keep‑alive).
- Повторяем тест с теми же параметрами.
- Сравниваем результаты, смотрим не только на среднее, но и на p95/p99.
Важно: wrk сам по себе может упереться в лимиты клиентской машины (CPU, сеть). Поэтому генератор нагрузки лучше запускать либо с отдельного сервера, либо с нескольких, чтобы они не были узким местом.
Практический пример: k6 для сценариев «как у пользователей»
Теперь рассмотрим k6. Допустим, типичный пользователь делает следующее:
- Открывает главную страницу.
- Переходит в каталог.
- Открывает 3–5 карточек товара.
- Кладет один товар в корзину.
- Переходит к оформлению заказа.
В k6 это можно описать одним сценарием, а затем задать профиль нагрузки (например, плавный рост от 0 до 500 одновременных виртуальных пользователей за 10 минут, удержание на плато 20 минут и плавный спад).
Такая модель позволяет:
- видеть деградацию конкретных шагов (где именно «тормозит» опыт пользователя);
- собирать статистику по каждому типу операций;
- проверять, не вылетают ли ошибки приложения (500, 502, 504, бизнес‑ошибки в JSON) при росте нагрузки.
k6 также удобен для регрессионного нагрузочного тестирования: сценарий остается тем же, а вы запускаете его до и после изменения кода/конфигурации и сравниваете p95/p99 по ключевым шагам.

Что и как измерять во время теста
Нагрузочное тестирование без нормальных метрик — бессмысленно. Нужно собирать как минимум три слоя данных:
- На стороне генератора нагрузки (k6, wrk): RPS, процентили задержек, количество ошибок, распределение по статус‑кодам.
- На стороне инфраструктуры: CPU, RAM, диск (IOPS, латентность), сеть, соединения, очереди, лимиты дескрипторов.
- На уровне приложения и БД: время выполнения запросов, медленные запросы, блокировки, число активных соединений и транзакций.
На практике удобно использовать:
- системные метрики (например,
top,htop,iostat,vmstat,ssпри ручных тестах); - графики из Prometheus и Grafana, Zabbix или других систем мониторинга;
- slow‑query‑логи для MySQL/PostgreSQL;
- лог веб‑сервера (nginx/apache) с полным набором полей, включая время обработки запроса и upstream‑задержки.
Важно заранее договориться, какие метрики будут критерием успеха. Например:
- p95 TTFB не более 400 мс при 1000 RPS;
- ошибки 5xx не более 0,1% запросов;
- загрузка CPU на веб/бэк не более 75%, на БД — не более 80%;
- отсутствие растущих очередей в Redis или системе фоновых задач.
Как безопасно тестировать prod
Полностью избегать нагрузочного тестирования на проде — тоже крайность. Есть сценарии, которые никак не эмулируешь на staging: реальная латентность сети от пользователей, поведение CDN, особенности балансировщиков и внешних интеграций.
Чтобы тестировать боевую среду безопасно, стоит придерживаться ряда правил.
Окна низкой активности и ограничение процента трафика
Первое — запускать тесты в окна минимальной пользовательской активности (глубокая ночь по основному часовому поясу аудитории, крупные праздники для B2B‑сервиса и т.п.).
Второе — ограничить долю нагрузки, которую вы добавляете сверху боевого трафика. Например:
- не более +10–20% к текущему RPS;
- строгий лимит по длительности (например, по 10–15 минут на каждый шаг).
При таком подходе, даже если что‑то пойдет не так, пользователи заметят лишь небольшое увеличение задержек, а не полноценный даунтайм.
Таргетирование по IP и отдельные backend‑пути
Еще одна техника — отделить тестовый трафик от пользовательского:
- маркировать запросы нагрузочного теста по заголовку (например,
X-Load-Test: 1) и обрабатывать их особым образом (логировать отдельно, отключать лишние функции, если это допустимо); - использовать отдельный домен или поддомен, указывающий на тот же backend, но позволяющий отличать логи и трафик;
- жестко ограничить количество источников нагрузки (конкретные IP‑адреса), чтобы не спровоцировать защиту от DDoS.
Главное — чтобы безопасность и анти‑DDoS‑механизмы не приняли нагрузочное тестирование за атаку. Иногда это требует настройки whitelist для IP‑адресов генератора нагрузки.
Типичные ошибки и анти‑паттерны нагрузочного тестирования
Вот несколько практических ошибок, которые регулярно встречаются:
- Тест только «главной страницы». В реальном трафике есть десятки URL, API‑ручек, форм, некоторые из них в разы тяжелее главной.
- Игнорирование кэшей. Запуск теста кэшируемых страниц без очистки кеша или, наоборот, постоянный сброс кеша, что не соответствует реальной жизни.
- Отсутствие прогрева. Начинать замер производительности сразу с холодной системы и делать выводы по первым минутам.
- Тест без логирования и мониторинга. Потом очень сложно понять, что именно пошло не так, кроме «серверу было плохо».
- Сравнение только по RPS. Можно получить более высокий RPS ценой пикового p99 в секунды и огромной доли 5xx — это не победа.
- Изменение нескольких параметров сразу. Нельзя понять, какая именно правка улучшила или ухудшила ситуацию.
Встраиваем нагрузочное тестирование в процесс
Чтобы нагрузочное тестирование staging и prod не превратилось в разовые героические усилия, его нужно сделать частью обычного рабочего процесса.
Практический минимум:
- Сценарии — в репозитории. Все скрипты для k6 и wrk хранятся рядом с кодом, проходят код‑ревью и версионируются.
- Четкий чек‑лист, когда запускать нагрузочные тесты: крупные релизы, смена конфигурации БД, включение нового кеша, переезд на другой тип дисков и т.п.
- Заведение задач на основе результатов. Каждый тест должен заканчиваться списком конкретных изменений (добавить индекс, поменять лимиты пула соединений, увеличить RAM и т.д.).
- Повторный прогон после изменений. Без этого вы не докажете, что оптимизация реально сработала.
На более зрелом этапе можно завести регулярные прогонки (раз в неделю или раз в месяц) с автоматическим запуском k6 из CI, чтобы отслеживать тренды производительности и не допускать постепенной деградации.
Итоги
Нагрузочное тестирование staging и prod — это не про красивый отчёт с графиками, а про дисциплину и системный подход:
- staging помогает безопасно экспериментировать и отрабатывать сценарии — но реальные ограничения выявляются только на prod;
- wrk полезен как «микроскоп» для HTTP‑стека и отдельных ручек, k6 — как инструмент для сценариев, похожих на реальное поведение пользователей;
- профиль нагрузки должен строиться из реальных логов и метрик, а не выдуманных цифр;
- любое тестирование без мониторинга и четких критериев успеха почти бесполезно;
- самое ценное в нагрузочных тестах — не сам факт их запуска, а изменения, которые вы делаете по результатам.
Если нагрузочные тесты будут частью обычной работы (release process, изменения в инфраструктуре, настройка кешей и БД), они перестанут быть страшным и редким мероприятием и действительно помогут держать прод под контролем, а не ждать следующего падения под неожиданным трафиком.


