Журнал Tenku

Почему сайт на VPS тормозит и как найти причину

«Хостинг тормозит» — не диагноз. Тормозит сеть, диск, память, PHP, база, внешнее API или страница с двумя мегабайтами скриптов. Апгрейд тарифа без цифр лечит редко: вы покупаете более дорогой простой. Ниже — порядок, которым можно за час понять, кто ест время, и только потом решать: кэш, чистка, другой план Tenku или другая локация.

Отделите браузер от сервера

С вашего ПК:

curl -o /dev/null -s -w "dns:%{time_namelookup} tcp:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n" https://example.ru/
  • Большой tcp — маршрут и локация, не PHP. Сравните с пингом IP. Клиенты в другом макрорегионе? Читайте про выбор дата-центра.
  • Маленький tcp, большой ttfb — сервер думает до первого байта: PHP, БД, блокировки, холодный диск, отсутствие кэша.
  • Маленький ttfb, большой total — тяжёлое тело ответа или медленная отдача большого файла. Смотрите вес HTML и медиа, gzip/brotli, не ядра.

Проверка с LTE и из другого города обязательна. Ваш офисный канал врёт.

В DevTools вкладка Network: TTFB документа vs время картинок. Картинки 5 МБ — не тариф VPS виноват.

Жива ли машина или жив ли сайт

uptime
free -h
df -h
df -i

load average сравнивайте с числом ядер. Load 8 на 1 ядре — очередь. Load 0.2 на четырёх — ищите тормоза не в CPU.

RAM: смотрите available, не «free». Linux ест кэш. Мало available + активный swap (swapon --show, vmstat 1 5 колонка si so) — память кончилась. PHP и MySQL начинают умирать по очереди.

Диск 95%+ — логи, бинарные логи MySQL, бэкапы на том же томе, sessions. Иноды 100% при «свободных гигабайтах» — миллион мелких файлов. Сайт может отдавать 500 без красивой причины.

sudo du -xhd1 /var | sort -h

Часто /var/log и /var/lib/mysql. Ротация логов — не косметика.

Кто ест CPU прямо сейчас

htop

Если нет — sudo apt install htop. Смотрите:

  • php-fpm на 100% — тяжёлые запросы или DDoS/боты на admin-ajax.
  • mysqld — запросы без индексов, отсутствие кэша.
  • gzip/brotli редко; node/python — ваш воркер.
  • неизвестный майнер — инцидент безопасности, не апгрейд.

top -H покажет потоки. steal в CPU (колонка st в vmstat) на нормальном KVM Tenku должен быть около нуля. Высокий steal — претензия к гипервизору, пишите в тикет с цифрами. Не путайте steal с us+sy своего PHP.

PHP-FPM: очередь, а не «медленный Nginx»

sudo systemctl status php8.1-fpm
ps aux | grep php-fpm | wc -l

Если в www.conf max_children=5, а запросов 40 — остальные ждут. Симптом: TTFB скачет, CPU при этом не 100%. Лечение: больше children если влезает RAM, либо кэш, либо меньше тяжёлых плагинов.

Считайте грубо: каждый php-fpm ≈ 50–150 МБ RSS на WP. Восемь детей — это гигабайт только на PHP. На тарифе 2 ГБ ещё нужны система, Nginx, MySQL.

Медленный лог PHP (в пуле):

request_slowlog_timeout = 5s
slowlog = /var/log/php8.1-fpm.slow.log

Перезагрузка пула, воспроизведение, чтение файла. Часто одна функция плагина на каждую витрину.

Access-лог Nginx: много POST на xmlrpc.php и wp-login.php — закройте xmlrpc, лимит логина, не покупайте ядра под словари.

База: самый частый тихий убийца

sudo mysqladmin processlist

Запросы Sleep толпой — не обязательно зло. Запросы Sending data / Locked секундами — зло.

Включите медленный лог MariaDB на 1–2 секунды на время отладки, не навсегда без присмотра: диск.

SHOW FULL PROCESSLIST;

EXPLAIN на подозрительный SELECT. Нет индекса по meta_key в WP — классика. Плагин «связанных записей» на wp_postmeta без индекса убивает любой NVMe.

innodb_buffer_pool_size на 128 МБ при базе 3 ГБ — сознательно медленно. Либо больше RAM (тариф), либо меньше данных в горячем наборе.

Не делайте mysqldump на проде в час пик без --single-transaction — можно положить записи.

Диск и I/O

iostat -xz 1 5

%util у диска под 100% и длинная очередь — упираетесь в I/O. На NVMe Tenku это обычно не «медленный HDD», а лавина мелких записей: journal, бинарные логи, сессии PHP в файлах, debug.log WP на 4 ГБ.

Переведите сессии PHP в Redis, выключите WP_DEBUG_LOG на проде, вынесите бэкапы. Если после этого iostat чистый, а TTFB большой — это не диск.

Память и OOM

sudo dmesg -T | grep -i "killed process"
sudo journalctl -k | grep -i oom

OOM Killer убивает MySQL или php-fpm — сайт «иногда пропадает». Лечение: меньше max_children, меньше buffer pool, больше RAM. Не swap=8G как стратегия: сервер станет медленным всегда, вместо того чтобы иногда падать. Небольшой swap как подушка — ок, не как основная память.

Nginx: 504 и 499

504 — PHP не ответил за fastcgi_read_timeout. Увеличить таймаут, чтобы «админка открылась через 3 минуты» — костыль. Найдите запрос.

499 — клиент ушёл. Часто боты и нетерпеливые люди на медленном TTFB.

Gzip включён? gzip on для text/css/js. Картинки не жмите gzip второй раз.

HTTP/2 на 443 — норма. Не путайте с «нужен HTTP/3 иначе Google».

Внешние зависимости

Сайт может ждать HTTP к API доставки, капчи, лицензии плагина, S3. ttfb большой, CPU нулевой — классика. Временно заблокируйте плагин, смотрите. curl -w к этому API с сервера:

curl -o /dev/null -s -w "%{time_starttransfer}\n" https://чужой-api

Если чужой API 800 мс — апгрейд VPS бесполезен.

Что менять, когда цифра есть

  • Сеть / tcp большой у ЦА — локация или DNS, не тариф CPU.
  • RAM в потолок — больше памяти или меньше воркеров и плагинов.
  • MySQL slow log — индексы и кэш объекта, не «ещё NVMe».
  • PHP slow log — плагин или N+1 в теме.
  • Диск 100% — логи и дампы, не ядра.
  • Steal CPU высокий — тикет в Tenku с выводом vmstat.
  • Всё зелёное, а PageSpeed красный из-за 4 МБ JS — фронт, не хостинг.

Как писать в поддержку полезно

Не: «сайт не открывается, разберитесь». Да: URL, время, curl -w вывод, free -h, uptime, кусок slow log, что уже пробовали (рестарт php-fpm, отключение плагина). Так можно отличить сеть дата-центра от WooCommerce без кэша.

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

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

Выберите тариф и локацию — VPS появится в кабинете.

Смотреть тарифы