Нагрузочное тестирование сайта: ab, wrk и k6

Администрирование
Нагрузочное тестирование сайта: ab, wrk и k6

Нагрузочное тестирование отвечает на вопрос, который лучше задать до рекламной кампании, а не во время неё: сколько посетителей выдержит ваш сайт, прежде чем начнёт отдавать ошибки. В этой статье — практика стресс-теста сайта тремя инструментами: простым ab (Apache Bench), быстрым wrk и сценарным k6. Разберём команды с примерами, научимся читать RPS и латентность p95/p99 и определим момент, когда оптимизация уже не помогает и пора апгрейдить тариф VPS.

Главное правило: тестируйте только свои сайты

Прежде чем запускать хоть одну команду, зафиксируем: нагрузочный тест можно направлять только на собственный сайт — или на чужой при наличии письменного разрешения владельца. Со стороны сервера-жертвы поток запросов от ab или wrk неотличим от DoS-атаки: тот же шквал соединений с одного IP. Тест чужого ресурса «просто посмотреть» — это правонарушение, жалоба вашему хостеру и блокировка сервера. У любого провайдера, включая Cheap-Host, такая активность прямо запрещена правилами.

И даже на своём проекте соблюдайте гигиену:

  • предупредите коллег и не тестируйте боевой сайт в час пик — выберите ночное окно;
  • если сайт за CDN или анти-DDoS-прокси, тестируйте напрямую origin-сервер, иначе получите бан своего IP и цифры прокси, а не сервера;
  • включите мониторинг (htop, а лучше Grafana + Prometheus) — без графиков CPU и памяти вы увидите «сколько», но не поймёте «почему»;
  • отключите на время теста уведомления мониторинга, чтобы не разбудить дежурного.

Откуда запускать нагрузку? Не с самого тестируемого сервера (генератор отберёт CPU у сайта и исказит результат) и не с домашнего Wi-Fi (узким местом станет ваш интернет). Идеальный вариант — отдельный VPS: у Cheap-Host для этого хватит NAT Pro за 199 ₽/мес (2 vCPU, 4 ГБ RAM) — исходящих соединений он генерирует достаточно, а трафик безлимитный.

Три инструмента: когда какой

ИнструментЧто умеетКогда использовать
ab (Apache Bench)Долбит один URL, простой отчётБыстрая проверка за 30 секунд, «дымовой» тест
wrkМногопоточный, HTTP keep-alive, перцентилиПоиск потолка RPS сервера
k6Сценарии на JavaScript, этапы нагрузки, порогиРеалистичная имитация пользователей, регулярные тесты

ab: быстрый тест за 30 секунд

Apache Bench входит в пакет apache2-utils:

sudo apt update
sudo apt install -y apache2-utils
ab -n 1000 -c 10 https://example.com/

Здесь -n 1000 — всего запросов, -c 10 — одновременных соединений. Ключевые строки отчёта:

Requests per second:    287.41 [#/sec] (mean)
Time per request:       34.792 [ms] (mean)
Failed requests:        0
Percentage of the requests served within a certain time (ms)
  50%     31
  95%     58
  99%    112

Requests per second — это и есть RPS, пропускная способность. Failed requests должно быть 0: если появились ошибки, сервер уже захлёбывается. Таблица перцентилей внизу важнее среднего: строка «95% — 58 мс» означает, что 95 из 100 запросов уложились в 58 мс.

Ограничения ab: один URL, слабая работа с keep-alive (флаг -k есть, но по умолчанию выключен), однопоточность. Для серьёзной нагрузки берём wrk.

wrk: ищем потолок производительности

wrk написан на C, использует несколько потоков и событийную модель — с одной средней машины он выжимает десятки тысяч RPS. Установка на Ubuntu 24.04:

sudo apt install -y wrk
wrk -t4 -c100 -d60s --latency https://example.com/

Параметры: -t4 — 4 потока (по числу ядер генератора), -c100 — 100 открытых соединений, -d60s — минута теста, --latency — подробная статистика задержек. Пример вывода:

Running 1m test @ https://example.com/
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    45.21ms   68.34ms   1.02s    91.24%
    Req/Sec   712.50    120.11     1.05k    72.00%
  Latency Distribution
     50%   28.15ms
     75%   49.32ms
     90%   98.77ms
     99%  341.02ms
  170514 requests in 1.00m, 2.51GB read
Requests/sec:   2841.90
Transfer/sec:     42.81MB

Методика поиска потолка: повторяйте тест, удваивая -c (50 → 100 → 200 → 400), и следите за двумя кривыми. Пока RPS растёт, а латентность стабильна — запас есть. Как только RPS упёрся в плато, а p99 полетела вверх — вы нашли предел сервера. Число до плато и есть его честная ёмкость.

k6: сценарии, похожие на живых пользователей

Реальные посетители не долбят одну страницу — они ходят по сайту с паузами. k6 описывает такое поведение скриптом на JavaScript. Установка из официального репозитория:

sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install -y k6

Сценарий load-test.js с плавным ростом до 100 виртуальных пользователей (VU) и порогами качества:

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

export const options = {
  stages: [
    { duration: "1m", target: 20 },   // разогрев
    { duration: "3m", target: 100 },  // рост до пика
    { duration: "2m", target: 100 },  // удержание пика
    { duration: "1m", target: 0 },    // спад
  ],
  thresholds: {
    http_req_duration: ["p(95)<500"], // 95% запросов быстрее 500 мс
    http_req_failed: ["rate<0.01"],   // ошибок меньше 1%
  },
};

export default function () {
  const res = http.get("https://example.com/");
  check(res, { "status 200": (r) => r.status === 200 });
  sleep(Math.random() * 3 + 1); // пауза 1–4 с, как у человека
}

Запуск: k6 run load-test.js. Если пороги из thresholds нарушены, k6 завершится с ошибкой — удобно для запуска в CI: тест производительности станет таким же обязательным, как юнит-тесты. Как гонять такие проверки автоматически, мы рассказывали в статье про self-hosted runner GitHub Actions.

Как читать результаты: RPS и латентность

Две метрики описывают производительность с разных сторон:

  • RPS (requests per second) — сколько запросов сервер обрабатывает в секунду. Это ёмкость: «сколько влезет».
  • Латентность — сколько ждёт каждый запрос. Это качество: «насколько быстро». Смотрите на p95 и p99, а не на среднее — среднее прячет хвост медленных запросов, которые и раздражают пользователей.

Чтобы перевести RPS в посещаемость: пользователь генерирует запрос к бэкенду примерно раз в 5–10 секунд (остальное — статика и чтение). Значит, 100 стабильных RPS — это порядка 500–1000 одновременных посетителей. Ориентиры «нормы» сильно зависят от стека:

  • статика через Nginx — тысячи RPS даже на младшем тарифе;
  • WordPress без кеша — 10–50 RPS (каждый запрос — PHP плюс запросы к MySQL);
  • WordPress с полностраничным кешем — 300–1000+ RPS;
  • API на Node.js/Go с лёгкой логикой — сотни и тысячи RPS.

Здоровый результат — когда при целевой нагрузке (пиковая посещаемость × 3) ошибок нет, а p95 держится ниже 300–500 мс. Если нет — ищем узкое место.

Узкое место: оптимизировать или апгрейдить тариф

Во время теста держите открытым htop на тестируемом сервере и смотрите, что кончается первым:

  • CPU в 100% на php-fpm или приложении — сначала кеширование (OPcache, Redis, полностраничный кеш), потом больше ядер;
  • кончается RAM, в dmesg — OOM-killer, растёт swap — уменьшить пулы, но чаще это прямой сигнал на тариф с большей памятью;
  • CPU свободен, а RPS низкий — упёрлись в лимиты конфигурации: worker_connections Nginx, pm.max_children PHP-FPM, лимиты открытых файлов. Начните с оптимизации Nginx под нагрузку;
  • высокий iowait — медленный диск; на NVMe-тарифах встречается редко и обычно означает неоптимальные запросы к БД.

Когда конфиги выжаты, а кеш включён, дальнейший рост даёт только железо. Признаки, что пора апгрейдить тариф: CPU стабильно выше 70% в обычные (не тестовые) пики, свободной памяти меньше 15%, p95 растёт от недели к неделе при том же трафике. Удобно, что у Cheap-Host апгрейд CPU/RAM/диска выполняется без потери данных: например, с тарифа Pro (750 ₽/мес, 12 vCPU, 16 ГБ RAM) на Ultra (1500 ₽/мес, 20 vCPU, 32 ГБ RAM, 192 ГБ NVMe) можно перейти без переустановки и переноса сайта — после апгрейда просто повторите тот же тест wrk и сравните цифры.

FAQ

Законно ли нагрузочное тестирование?

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

Какой RPS считается нормальным для сайта?

Зависит от контента: статика через Nginx выдаёт тысячи RPS даже на слабом VPS, WordPress без кеша — 10–50 RPS, с кешем — сотни. Сравнивайте не с чужими цифрами, а со своей пиковой посещаемостью с запасом в 3–5 раз.

Чем отличаются ab, wrk и k6?

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

Почему важна латентность p95, а не средняя?

Среднее скрывает проблемы: при среднем 100 мс каждый двадцатый запрос может занимать 3 секунды. p95 показывает время, в которое укладываются 95% запросов, — честная оценка того, что видит реальный пользователь в худшем случае.

Откуда запускать нагрузочный тест — с сервера или со своей машины?

Лучше с отдельного VPS в другой сети: тест с самого сервера не учитывает сеть и отбирает CPU у сайта, а домашний интернет сам станет узким местом. Дешёвый NAT VPS за 59–199 ₽/мес — подходящая машина-генератор нагрузки.

Вывод

Нагрузочное тестирование — это полчаса работы, которые страхуют от худшего сценария: сайт падает ровно в момент, когда на него пришёл трафик. Схема простая: быстрый прогон ab, поиск потолка wrk, реалистичный сценарий k6 — и решение по фактам: тюнить конфиги, включать кеш или брать тариф мощнее. Если текущий сервер потолок уже показал — у Cheap-Host тариф Pro за 750 ₽/мес (12 vCPU, 16 ГБ RAM, 128 ГБ NVMe) с апгрейдом до Ultra без потери данных: KVM, безлимитный трафик, выдача за минуту. Тарифы — на cheap-host.onl.

Читайте также