Диагностика веб-сервера начинается с четырёх ресурсов и логов: процессор, память, диск, сеть. Пять-шесть команд в консоли за пару минут показывают, во что сервер упёрся прямо сейчас. Нагрузочное тестирование сервера отвечает на другой вопрос: сколько посетителей сервер выдержит, прежде чем начнёт тормозить. Это лучше узнать до распродажи.
Первый симптом проблем - медленный отклик. Страницы открываются заметно дольше обычного, часть запросов отваливается по таймауту, корзины бросают на полпути. Вы смотрите на мониторинг и видите: загрузка CPU 85%, память забита, но непонятно, что именно жрёт ресурсы.
Чтобы проверить нагрузку на сервер, начните с базовых метрик. Процессор, оперативная память, дисковая система и сеть определяют производительность любого веб-сервера. Посмотрите на загрузку CPU: если она постоянно выше 70-80%, запаса почти не осталось. Один резкий скачок трафика - и время ответа поползёт вверх.
Одной цифры загрузки мало. Load average в Linux считает процессы, которые ждут процессор, и заодно те, что застряли в ожидании диска. Load average 8 на восьмиядерном сервере значит, что все ядра заняты, но очереди нет. На двухъядерной виртуалке та же цифра означает очередь. Сравнивайте его с числом ядер из nproc.
На арендованной виртуалке смотрите ещё и на steal - столбец st в top. Это время, которое гипервизор отдал чужим машинам на том же хосте. Если steal стабильно держится на уровне 5-10% и выше, часть процессорного времени у вас отбирают соседи, и одной оптимизацией кода это не вылечить.
Оперативная память - ещё один больной вопрос. Когда RAM заканчивается, система выгружает страницы памяти в swap на диск, и производительность падает в разы. Мало свободной памяти в free -h - ещё не тревога: Linux занимает её под кеш и отдаёт по первому требованию, смотреть надо на столбец available. Настоящий признак нехватки - столбцы si и so в выводе vmstat 1, которые держатся выше нуля: память постоянно гоняется между RAM и диском.
С дисковой подсистемой сложнее. IOPS (операции ввода-вывода в секунду) - вот что важно. У вас может быть терабайт свободного места, но если диск не успевает обрабатывать запросы, база данных будет тормозить. Задержку показывает iostat -xz 1: это столбцы r_await и w_await, время обработки запроса в миллисекундах. Столбцу %util на SSD и RAID не верьте. Он показывает долю времени, когда у устройства была хоть одна операция, а NVMe-накопитель обслуживает десятки запросов параллельно и при 100% ещё может иметь запас.
Сводная шпаргалка для Linux:
| Что подозреваем | Команда | На что смотреть |
|---|---|---|
| Процессор | uptime, nproc, top | load average против числа ядер; us - приложения, sy - ядро |
| Соседи на VPS | top | st (steal) стабильно заметный - проблема на хосте |
| Память | free -h, vmstat 1 | available (столбец free почти всегда мал из-за кеша); si/so постоянно больше нуля - своппинг |
| Диск | iostat -xz 1 (пакет sysstat), top | растут r_await/w_await и очередь aqu-sz (в старых версиях avgqu-sz); высокий wa в top |
| Сеть и соединения | ss -s, ip -s link | число соединений, ошибки и отброшенные пакеты на интерфейсе |
| Какой процесс виноват | ps aux --sort=-%cpu | head, ps aux --sort=-%mem | head | кто вверху списка |
| Кто тормозит: nginx или бэкенд | access-лог с $request_time и $upstream_response_time | разбор ниже |
Один замер ничего не доказывает, нужна динамика. Load average 12 в течение минуты после ночного бэкапа и load average 12 весь рабочий день - это две отдельные проблемы. Первая лечится расписанием, вторая требует разбора.
Логи - ваш лучший друг при диагностике. Веб-сервер пишет в логи всё: успешные запросы, ошибки, время обработки. Анализ логов покажет, какие URL вызывают больше всего проблем, где возникают 500-е ошибки, какие запросы обрабатываются слишком долго. Где искать логи и как их читать, мы разбирали в статье как посмотреть логи сервера.
Стандартный формат лога nginx время ответа не записывает. Добавьте в секцию http свой формат с двумя переменными и укажите его в уже существующей строке access_log. $request_time - сколько запрос провёл в nginx целиком, включая отдачу клиенту. $upstream_response_time - сколько из этого nginx ждал ответа бэкенда: PHP-FPM, приложения на Node.js или Python.
log_format timing '$remote_addr [$time_local] "$request" $status '
'rt=$request_time urt=$upstream_response_time';
access_log /var/log/nginx/access.log timing;
Вторую строку access_log с тем же файлом рядом со старой не добавляйте: nginx запишет каждый запрос дважды. Если в блоке server у сайта прописан свой access_log, формат timing укажите и там, иначе строка из секции http для этого сайта не сработает. После правки - nginx -t и systemctl reload nginx. Если оба значения большие и почти равны, тормозит приложение или база. Если rt большой, а urt маленький, бэкенд ответил быстро, и время уходит на отдачу: медленный канал клиента или тяжёлые файлы без сжатия.
Системы мониторинга вроде Zabbix или Prometheus с Grafana помогают не ждать, пока проблема станет критической. Настроили алерты - получили уведомление, что что-то идёт не так, ещё до того, как пользователи начали жаловаться.
Хорошо, когда можно быстро найти проблему. Ещё лучше - не допустить её вообще. Нагрузочное тестирование - это как краш-тест для автомобиля, только для вашего веб-сервера. Вы искусственно создаёте экстремальные условия и смотрите, где система сломается.
Цель нагрузочного тестирования - найти границы производительности. Сколько одновременных пользователей выдержит сервер? При какой нагрузке начнётся деградация? Где та критическая точка, после которой всё рухнет? Ответы на эти вопросы нужны до того, как на сайт хлынет толпа реальных посетителей.
Перед нагрузочным тестированием проведите функциональное. Убедитесь, что сервер корректно отвечает на запросы, что все скрипты работают, что нет очевидных багов. Бессмысленно нагружать систему, которая и без нагрузки работает криво.
«Давайте запустим 10 000 запросов и посмотрим, что будет» - так нагрузочное тестирование не проводят. Нагрузку увеличивают постепенно и фиксируют критические моменты.
Точка деградации - момент, когда сервер начинает замедляться. Например, при 100 одновременных пользователях время ответа 200 мс, при 150 - уже 400 мс. Деградация началась. Система ещё работает, но уже не так резво.
Подкритическая точка - это когда нарушаются соглашения об уровне обслуживания (SLA). Если вы обещали пользователям время отклика не больше 500 мс, а при 200 одновременных подключениях оно выросло до 700 мс - вы в подкритической зоне.
Точка отказа - полный коллапс. Сервер перестаёт обрабатывать запросы, отдаёт ошибки 500 или вообще не отвечает. Это тот предел, после которого система нуждается в масштабировании или серьёзной оптимизации. Почему появляется ошибка 500 на сервере и как её убрать, разбираем отдельно.
Три точки находятся аккуратным тестом со ступенями нагрузки. Порядок такой:
Быстро прикинуть одну страницу можно утилитой ab. Она входит в пакет apache2-utils в Debian и Ubuntu и в httpd-tools в RHEL-семействе:
ab -k -n 5000 -c 50 https://test.example.ru/catalog/
Здесь 5000 запросов, 50 одновременных, -k включает keep-alive. У ab есть пределы: он однопоточный, отправляет запросы по HTTP/1.0 и на мощном сервере упрётся в одно ядро генератора раньше, чем сервер - в свои ресурсы.
Для нагрузки побольше подойдёт wrk: он многопоточный и показывает распределение задержек. В Debian и Ubuntu ставится одноимённым пакетом, в RHEL-семействе в базовых репозиториях его нет, и его собирают из исходников.
wrk -t4 -c200 -d60s --latency https://test.example.ru/catalog/
Четыре потока, 200 соединений, минута теста, --latency выводит перцентили времени ответа.
Когда нужны ступени нагрузки и автоматический вердикт «прошёл или нет», удобен k6. Сценарий пишется на JavaScript, критерии успеха задаются прямо в нём:
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
stages: [
{ duration: '5m', target: 100 },
{ duration: '10m', target: 100 },
{ duration: '5m', target: 300 },
{ duration: '10m', target: 300 },
],
thresholds: {
http_req_duration: ['p(95)<500'],
http_req_failed: ['rate<0.01'],
},
};
export default function () {
http.get('https://test.example.ru/catalog/');
sleep(1);
}
Запуск - k6 run test.js. Если 95-й перцентиль превысит 500 мс или ошибок станет больше 1%, k6 пометит тест проваленным. В стандартных репозиториях дистрибутивов k6 нет: его ставят из репозитория Grafana или запускают Docker-образом grafana/k6.
Частая ошибка - тестировать сайт через CDN или защиту от DDoS. Под нагрузкой защита начнёт отбивать запросы генератора, и в отчёте появятся ошибки вроде 403 или 429, к серверу не относящиеся. Тестируйте напрямую по адресу сервера или добавьте IP генератора в белый список защиты. Да и в целом CDN снимает нагрузку только со статики - разобрали, когда CDN не поможет ускорить сайт.
Инструментов много, выбирать надо исходя из задач.
| Инструмент | Как задаётся нагрузка | Когда брать | Ограничения |
|---|---|---|---|
| ab | ключи командной строки | быстро прикинуть одну страницу | однопоточный, HTTP/1.0, без сценариев |
| Siege | командная строка, список URL в файле | прогнать несколько страниц вперемешку | статистика базовая |
| wrk | командная строка, скрипты на Lua | высокая нагрузка с одной машины, перцентили | сценарии пользователя писать неудобно |
| k6 | сценарий на JavaScript | ступени, критерии успеха, запуск после каждого деплоя | нужно писать код |
| Apache JMeter | сценарий собирается в графическом редакторе | сложные сценарии: вход, корзина, заказ; много протоколов | тяжёлый, на Java |
| Gatling | код на Java, Kotlin или Scala | командам разработки, интеграция в CI/CD | порог входа выше |
| Locust | сценарий на Python | если команда пишет на Python; есть веб-интерфейс | один процесс нагружает одно ядро, для больших нагрузок запускают несколько воркеров |
| Яндекс.Танк | конфиг в YAML, генераторы Phantom или Pandora | высокая нагрузка и подробные отчёты, открытый код | Phantom не умеет HTTP/2, для него берут Pandora |
Для серьёзного анализа используют Apache JMeter. Бесплатный, с графическим интерфейсом, в нём собирают сложные сценарии нагрузки. Можно эмулировать поведение реальных пользователей: вход на сайт, переход по страницам, добавление товара в корзину, оформление заказа. JMeter записывает все метрики и строит графики. Графический интерфейс нужен для сборки сценария, а сам тест запускают из консоли: jmeter -n -t plan.jmx -l result.jtl. Иначе интерфейс отнимает ресурсы у генератора.
Gatling - ещё один популярный инструмент. Ориентирован на разработчиков, сценарии пишутся кодом. Удобен для интеграции в CI/CD: нагрузочные тесты запускаются автоматически после каждого деплоя.
NeoLoad и WAPT - коммерческие решения с распределённым тестированием и готовыми отчётами для руководства. Малому и среднему бизнесу обычно хватает бесплатных инструментов из таблицы, а покупку зарубежной лицензии стоит заранее проверить на доступность в России.
Тестирование производительности (performance testing) - базовый вариант. Проверяете, как сервер ведёт себя при ожидаемой нагрузке. Если в среднем у вас 500 одновременных пользователей, создаёте именно такую нагрузку и смотрите на время отклика, потребление ресурсов.
Стресс-тестирование (stress testing) - здесь нагрузка превышает плановую. Цель - найти точку отказа и понять, как система восстанавливается после пикового всплеска. Такие тесты показывают запас прочности.
Тестирование масштабируемости проверяет, насколько хорошо система растёт вместе с нагрузкой. Добавили второй сервер - производительность удвоилась? Или появилось узкое место на уровне базы данных, и дополнительные серверы не помогают? Как распределять запросы между несколькими машинами, мы писали в материале про балансировку нагрузки между серверами.
Длительный тест (тест на стабильность) - обычная рабочая нагрузка на несколько часов. Он ловит то, чего не видно за десять минут: утечки памяти и диск, который постепенно забивается логами.
Сначала разберитесь, как читать отчёт. Инструменты выдают три главные цифры: запросы в секунду (RPS), время ответа и долю ошибок. Среднее время ответа почти ничего не говорит. 900 ответов по 100 мс и 100 зависших по 5 секунд дадут в среднем около 600 мс, и по среднему такой сервер выглядит терпимо. Показательнее перцентили: p95 - время, быстрее которого пришли 95% ответов, p99 - 99%. Медленный хвост как раз и видят те, кто пишет в поддержку.
RPS растёт вместе с нагрузкой до какого-то предела, потом упирается в полку, а время ответа и ошибки ползут вверх. Полка RPS и есть ёмкость сервера на этом сценарии.
Дальше анализируете узкие места. Процессор загружен на 100% - значит, либо оптимизируете код, либо увеличиваете мощность CPU. Память заканчивается - добавляете RAM или ищете утечки. Диск не справляется с IOPS - переходите на SSD или настраиваете кеширование.
Часто хватает настроек, и железо менять не нужно. Проверьте количество рабочих процессов, настройки keep-alive, лимиты соединений, параметры кеширования. У nginx это worker_processes и worker_connections, у PHP-FPM - pm.max_children: если дочерних процессов не хватает, запросы встают в очередь при свободном процессоре, а в логе PHP-FPM появляется предупреждение о достигнутом лимите.
| Что упёрлось | Сначала попробуйте | Когда нужно железо |
|---|---|---|
| Процессор 90-100% под нагрузкой | кеширование страниц, OPcache для PHP, число воркеров, тяжёлые запросы к базе | код и кеш уже настроены, а RPS упирается в полку при загруженных ядрах |
| Высокий steal на VPS | другой тариф или перенос на другой хост у провайдера | steal не уходит - выделенный или собственный сервер |
| Память, своппинг | лимиты воркеров и пулов, размер кеша базы | после настройки available всё равно уходит в ноль под рабочей нагрузкой |
Диск: растёт await, высокий wa | индексы в базе, кеш в памяти, логи и временные файлы на другой диск | база на HDD или SATA SSD упирается в задержки - переход на NVMe |
| Канал | сжатие, кеширование статики, CDN | канал загружен в пик, а трафик продолжает расти |
База данных - традиционное узкое место. Индексы, запросы, количество соединений - всё это влияет на производительность. Нагрузочное тестирование покажет, какие запросы тормозят больше всего. Дальше - работа с профилировщиком и оптимизация.
Сетевые каналы тоже важны. Если гигабитное подключение забито на 90%, никакие оптимизации сервера не помогут. Нужен либо канал шире, либо CDN для раздачи статического контента.
Для небольшой компании развилка обычно простая. Сайт на арендованной виртуалке упирается в тариф или в соседей по хосту, и тест честно покажет, есть запас или нет. А если сайт, 1С и почта живут на одном собственном сервере, тест нередко показывает, что веб-серверу мешают соседние сервисы.
Нагрузочное тестирование - не разовая акция перед запуском проекта. Код меняется, нагрузка растёт, появляются новые функции. Регулярное тестирование помогает отловить деградацию производительности на ранних этапах.
Встройте нагрузочные тесты в процесс разработки. После каждого значительного обновления прогоняйте базовый набор тестов. Если производительность упала больше чем на 10% - повод разобраться, что пошло не так.
Автоматизированные системы мониторинга дополняют нагрузочное тестирование. Тесты показывают, что может произойти при определённой нагрузке. Мониторинг показывает, что происходит прямо сейчас. Связка из этих инструментов даёт полную картину здоровья веб-сервера. А чтобы видеть, какая функция или какой запрос к базе тормозит внутри приложения, нужен APM - про мониторинг производительности приложений у нас отдельный разбор.
Нагрузочное тестирование окупается не везде. Бывает, что время лучше потратить на другое:
rt маленький, а страница открывается секунды, тормозит фронтенд: тяжёлые картинки и сторонние скрипты. Это ищут в инструментах разработчика браузера (F12, вкладка «Сеть») или в PageSpeed Insights.Со стороны нагрузочный тест выглядит как DDoS-атака: огромный поток запросов с одного или нескольких адресов. Если тестируете рабочий сервер, заранее предупредите хостинг-провайдера и уточните, разрешены ли такие тесты по договору. Иначе вашу активность примут за атаку и заблокируют адрес генератора, а то и сам сервер.
Чужие сайты без письменного разрешения владельца не нагружают. Для владельца такой тест ничем не отличается от атаки.
Под высокой нагрузкой вылезают ошибки, незаметные в спокойном режиме: гонки при одновременной записи (race conditions), утечки памяти, некорректная обработка ошибок, когда вместо аккуратной страницы пользователь видит служебную информацию. После теста прочитайте логи: ошибки в них скажут больше, чем цифры RPS.
Нагрузочное тестирование требует времени и ресурсов. Нужно настроить инструменты, написать сценарии, проанализировать результаты, внести изменения. Но это дешевле, чем разбираться с упавшим сайтом в разгар распродажи.
Веб-сервер, который стабильно работает при любой нагрузке, - это результат продуманного подхода, регулярных проверок и готовности инвестировать время в профилактику. Потому что чинить упавший сервер ночью в субботу значительно дороже и неприятнее, чем протестировать его заранее в рабочее время.
Можно, если стенда нет, но осторожно: в часы минимальной посещаемости, ступенями, с остановкой при первых ошибках и с предупреждением хостера. До точки отказа рабочий сервер не доводят - её ищут на стенде.
Отталкивайтесь от реального пика: сколько человек одновременно на сайте в пиковый час по аналитике или логам. Для проверки запаса обычно берут пик с множителем 2-3, для поиска точки отказа поднимают нагрузку, пока не пойдут ошибки. Виртуальный пользователь без пауз нагружает сервер сильнее живого человека, поэтому в сценарий добавляют паузы между действиями.
Путаница из-за слова. Стресс-тест внутри нагрузочного тестирования - это нагрузка на сайт сверх плановой. А стресс-тест сервера как железа гоняет процессор, память и диски на полную часами, чтобы найти брак и перегрев до ввода в работу. Утилиты и цели у него другие, о них - в статье чем протестировать железо сервера.
Обычно тест бьёт в одну страницу, которая целиком отдаётся из кеша, а живые люди ходят в поиск и корзину. Вторая причина - генератор стоит в той же сети, что и сервер, и задержки канала до пользователей в тест не попадают. Третья - сервер отвечает быстро, а тормозит фронтенд.
Нужна история метрик: разовый top в спокойную минуту ничего не покажет. Поставьте мониторинг или хотя бы sar из пакета sysstat и сопоставьте всплески с расписанием бэкапов и задач cron. В Debian и Ubuntu сбор истории после установки sysstat выключен: включите его строкой ENABLED="true" в /etc/default/sysstat и перезапустите службу sysstat.
По теме: высоконагруженные системы: архитектура и масштабирование · Apache или Nginx: что выбрать
Тест показал, что сервер упёрся в железо?
Инженеры ITTELO подберут конфигурацию под вашу нагрузку: сколько ядер, памяти и какие накопители нужны сайту и базе. Соберём и протестируем сервер под задачу перед отгрузкой, дадим гарантию и поддержку после продажи. На рынке серверов 11+ лет.
Готовые конфигурации: сервер в стойку · +7 (800) 551-80-12 · info@ittelo.ru