← Все статьи
Полезные статьи

Сайт тормозит: как найти причину на сервере

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

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

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

Шаг 0. Убедиться, что дело в сервере

Прежде чем лезть в консоль, отделите проблемы сервера от проблем фронтенда.

Замерьте время ответа сервера — это то, за сколько он отдаёт саму страницу, без картинок и скриптов:

curl -o /dev/null -s -w "Время ответа: %{time_total}s\n" https://example.com

Ориентиры:

Время Что это значит
меньше 0,3 с с сервером всё в порядке, ищите в вёрстке и скриптах
0,3–1 с терпимо, но есть что улучшать
больше 1 с проблема на сервере, продолжаем диагностику

Если сервер отвечает за 0,2 секунды, а страница «грузится вечно» — дело не в нём. Смотрите вес изображений, количество подключаемых скриптов и внешние виджеты: чаты, аналитику, карты. Один чужой скрипт способен затормозить всю страницу.

Шаг 1. Посмотреть общую картину

Подключитесь к серверу и выполните:

uptime
free -h
df -h

Три команды дают три ответа.

Load average выше числа ядер (nproc) — не хватает процессора, запросы стоят в очереди.

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

Диск заполнен больше чем на 90% — часть операций уже не проходит. При 100% сайт просто ляжет.

Дальше идём в ту сторону, где нашлась аномалия.

Шаг 2. Если не хватает процессора

Смотрим, кто именно грузит:

htop

Сортировка по CPU — клавиша F6 или щелчок по колонке. Дальше по тому, что увидели:

Грузит php-fpm — тяжёлый код или отсутствие кэша. Самый частый случай на WordPress и Bitrix.

Грузит mysqld — проблема в запросах к базе, переходите к шагу 4.

Грузит незнакомый процесс — разберитесь, что это. Бывает, что сервер майнит чужую криптовалюту после взлома через старый плагин. Проверьте:

ps aux --sort=-%cpu | head -10

Если процесс подозрительный — не спешите просто убивать его, сначала посмотрите, откуда он запущен:

ls -l /proc/PID/exe

Нагрузка от ботов. Посмотрите, кто ходит на сайт:

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

Если один адрес сделал десятки тысяч запросов — это парсер или атака. Заблокировать:

ufw deny from 1.2.3.4

Отдельная тема, если запросов много и с разных адресов: Защита от DDoS.

Шаг 3. Если кончилась память

Найдите главных потребителей:

ps aux --sort=-%mem | head -10

Дело в PHP-FPM. Чаще всего процессов запущено больше, чем помещается в память. Посчитайте: сколько памяти занимает один процесс (обычно 50–120 МБ) и сколько их может быть запущено одновременно.

nano /etc/php/8.3/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

Значение pm.max_children подбирается так: свободная память, делённая на размер одного процесса. На 2 ГБ с учётом базы и системы это обычно 8–12.

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

Дело в MySQL. По умолчанию MySQL настроен довольно скромно, но на маленьких серверах и это много. Ключевой параметр:

nano /etc/mysql/mysql.conf.d/mysqld.cnf
innodb_buffer_pool_size = 512M

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

systemctl restart mysql

Утечка в приложении. Если процесс растёт день ото дня и сбрасывается только при перезапуске — это утечка. Временное решение — перезапуск по расписанию, правильное — искать причину в коде.

Шаг 4. Если упёрлись в базу

База данных — самая частая причина медленных сайтов после отсутствия кэша.

Включите журнал медленных запросов:

nano /etc/mysql/mysql.conf.d/mysqld.cnf
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
systemctl restart mysql

Через день посмотрите, что накопилось:

tail -50 /var/log/mysql/slow.log

Или сразу сводку по самым тяжёлым:

mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

Чаще всего в топе оказываются запросы без индексов. Проверить конкретный запрос:

EXPLAIN SELECT * FROM orders WHERE email = 'test@example.com';

Если в колонке type стоит ALL — база перебирает всю таблицу целиком. Индекс решает проблему мгновенно:

CREATE INDEX idx_email ON orders(email);

На таблице в сотни тысяч строк разница бывает в сотни раз.

Посмотреть, что происходит в базе прямо сейчас:

SHOW FULL PROCESSLIST;

Запросы, висящие по несколько секунд, видно сразу.

Шаг 5. Если упёрлись в диск

apt install sysstat -y
iostat -x 1 5

Смотрите на %util — если близко к 100, диск загружен полностью. Растущий await означает, что операции ждут очереди.

Кто именно пишет:

apt install iotop -y
iotop -o

Типичные виновники: бэкап, запущенный в рабочее время, переиндексация, логи в режиме отладки, забытый debug.log на несколько гигабайт.

Проверьте размер логов — они разрастаются незаметно:

du -sh /var/log/*

Шаг 6. То, что помогает почти всегда

Если конкретного виновника не нашлось, а сайт всё равно небыстрый, три вещи дают результат в большинстве случаев.

Кэширование страниц. Готовая HTML-страница вместо сборки заново при каждом заходе. На WordPress это плагины кэша, на Bitrix — встроенный кэш, для остальных — кэш на уровне nginx. Разница обычно кратная.

Отдача статики через nginx. Картинки, стили и скрипты не должны проходить через PHP:

location ~* \.(jpg|jpeg|png|gif|webp|svg|css|js|woff2)$ {
    expires 30d;
    access_log off;
}

Сжатие ответа:

gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_min_length 1024;

Страница уезжает клиенту в несколько раз меньшим объёмом.

Полный рабочий конфиг с этими блоками: Как разместить сайт на VPS.

Шаг 7. Когда сервера действительно мало

Есть ситуации, когда оптимизировать больше нечего. Признаки:

  • кэш настроен, медленных запросов нет, индексы на месте
  • load average стабильно выше числа ядер круглосуточно
  • память занята приложением, а не кэшем, и своп в работе
  • рост посещаемости в разы за последние месяцы

Тогда вопрос решается не настройками, а ресурсами: переход на тариф выше занимает несколько минут и не требует переноса данных. Когда упираются уже и в топовый тариф, смотрят в сторону разнесения ролей или физической машины: Выделенный сервер или VPS.

Порядок диагностики кратко

Что проверить Команда На что смотреть
Время ответа curl -w "%{time_total}" больше 1 с — сервер
Нагрузка uptime выше числа ядер
Память free -h используется своп
Диск: место df -h больше 90%
Диск: скорость iostat -x 1 5 %util около 100
Процессы htop кто в топе
База slow.log запросы дольше 1 с
Трафик access.log один IP с тысячами запросов

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

Сайт тормозит только вечером, в чём дело? Либо пиковая посещаемость, либо совпадение с расписанием задач. Проверьте crontab -l — нередко это бэкап или выгрузка, запущенные в неудачное время.

Помогает ли перезагрузка сервера? Как временная мера — да, она сбрасывает зависшие процессы и освобождает память. Но если через день всё повторяется, причина не устранена, а спрятана.

Как понять, тормозит сервер или интернет у посетителя? Замерьте время ответа командой curl с другой машины. Если сервер отвечает быстро, а у клиента медленно — дело в канале или в его устройстве.

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

Что делать, если ничего не помогло? Соберите вывод команд из таблицы выше и напишите в поддержку. По цифрам узкое место видно почти всегда, и это быстрее, чем перебирать настройки наугад.

Итог

Диагностика — это движение от общего к частному: время ответа, потом ресурсы, потом конкретный процесс, потом конкретный запрос. Такой порядок экономит часы по сравнению с угадыванием.

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

Сервер, который не тормозит →

Команда Puws.Cloud
Puws.Cloud
Начать

СЕРВЕР ДЛЯ ВАШЕГО ПРОЕКТА

Начните
с тарифа.

ПОЛЕЗНОЕ О СЕРВЕРАХИнструкции
и советы.
Открыть блог
Наш Аптайм