Время ответа сервера: как измерить и на что оно делится
Из чего складывается время ответа сервера, чем оно отличается от общей скорости загрузки, чем его измерить и какие цифры считать нормой для малого сайта.
Содержание
Время ответа сервера это интервал от отправки запроса до первого байта ответа, он же TTFB. Складывается из пяти отрезков: DNS, TCP-соединение, TLS-рукопожатие, обработка запроса на сервере и передача первого байта. Норма для сайта малого бизнеса 200-500 мс, выше 600 мс уже повод разбираться. Измеряется одной командой curl за минуту.
Статья для владельца сайта, который увидел в PageSpeed красную строку про ответ сервера и не понял, кому это предъявлять: хостеру, программисту или себе. Ниже разбор пяти отрезков внутри одной цифры и четыре бесплатных способа их измерить. В конце порядок действий, который за час показывает виновника. Плагина, который чинит TTFB одной кнопкой, здесь не будет: его не существует.

За шесть лет абонентки я слышал «хостинг тормозит» сотни раз. Хостинг оказывался виноват примерно в трети случаев. В остальных сервер честно ждал, пока PHP досчитает то, что можно было посчитать один раз и положить в кэш.
Пять отрезков внутри одной цифры
Браузер не получает страницу одним куском. Между кликом и первым байтом происходит пять последовательных событий, и каждое стоит времени.
| Отрезок | Что происходит | Типичное значение |
|---|---|---|
| DNS | браузер узнаёт IP по имени домена | 0-80 мс |
| TCP connect | устанавливается соединение с сервером | 10-60 мс |
| TLS handshake | обмен сертификатами, согласование шифра | 30-120 мс |
| Ожидание сервера | Apache или nginx принял запрос, PHP считает, база отвечает | 50-2000 мс |
| Передача | первый байт пошёл к браузеру | 5-200 мс |
Первые три отрезка от вашего кода не зависят. DNS упирается в настройки зоны и TTL записей, соединение и шифрование в географию: до сервера в Москве из Петербурга ходить 8 мс, до сервера во Франкфурте 40 мс, до калифорнийского 180 мс. Разово это мелочь, но TLS-рукопожатие делает несколько круговых поездок, и 180 мс превращаются в 700.
Четвёртый отрезок и есть то, за что отвечает сайт. Именно он раздувается с 50 мс до двух секунд, и именно он лечится.
TTFB по определению включает первые четыре отрезка сразу. Поэтому фраза «у меня TTFB 800 мс» без разбивки бесполезна: восемьсот миллисекунд могут быть медленным PHP, а могут быть сервером в другом полушарии с идеально быстрым кодом. Лечение в этих случаях противоположное.
Чем измерить бесплатно
Четыре инструмента, и каждый показывает свою правду. Расхождение между ними это тоже данные: оно обычно указывает на географию или на кэш.
curl показывает разбивку по отрезкам
Единственный способ увидеть все пять чисел, а не одно итоговое. Работает в Git Bash на Windows, в терминале macOS и на любом Linux.
cat > curl-format.txt <<'EOF'
dns: %{time_namelookup}
connect: %{time_connect}
tls: %{time_appconnect}
ttfb: %{time_starttransfer}
total: %{time_total}
EOF
curl -w "@curl-format.txt" -o /dev/null -s https://example.ru/
Ответ выглядит так:
dns: 0.021
connect: 0.048
tls: 0.131
ttfb: 0.874
total: 0.902
Числа накопительные, каждое считается от старта запроса. Чистое время работы сервера это ttfb минус tls: 0.874 — 0.131 = 0.743. Три четверти секунды PHP и база думали над страницей. Инфраструктура при этом отработала за 131 мс, к хостеру претензий нет.
Один замер ничего не доказывает: попасть можно и в момент, когда сосед по shared-серверу запустил выгрузку каталога. Гоняем десять раз с паузой:
for i in $(seq 1 10); do
curl -o /dev/null -s -w "%{time_starttransfer}n" https://example.ru/
sleep 3
done
Смотреть надо на разброс. Десять значений в коридоре 0.7-0.9 это стабильно медленный код. Значения вида 0.2, 0.2, 1.8, 0.3, 2.4 это конкуренция за процессор на общем хостинге, и починка кода тут даст мало.
Вкладка «Сеть» в браузере
F12, вкладка Network, галочка «Отключить кэш», перезагрузка. Кликаем по самой первой строке (сам HTML-документ, не картинки), открываем Timing. Нужная строка называется Waiting for server response, в русском интерфейсе «Ожидание ответа сервера».
Способ хорош тем, что показывает реальную картину с вашего интернета и вашего города. Плох тем, что мерит один раз и включает в себя все проблемы вашего собственного канала. Мобильный интернет в электричке нарисует вам полторы секунды на пустом месте. Подробнее про разницу лабораторных и полевых замеров я писал в статье про измерение скорости загрузки сайта.
Яндекс Вебмастер
Раздел «Индексирование», пункт «Статистика обхода», плюс блок диагностики. Вебмастер показывает время ответа, которое видит поисковый робот, усреднённое за месяц, с графиком по дням.
Это самый честный источник для российского сайта. Робот Яндекса ходит из России, ходит регулярно, ходит по всем страницам, а не только по главной. Если на графике ровная линия 300 мс, которая в июне подскочила до 1200 и не вернулась, вы точно знаете дату аварии и можете вспомнить, что тогда установили.
PageSpeed Insights
Показывает строку «Сократите время ответа сервера» и подсвечивает её красным на значениях выше 600 мс. Порог фиксированный, спорить с ним бесполезно.
Замер один, лабораторный, из дата-центра Google. Для сайта на российском хостинге это регулярно даёт лишние 200-400 мс на дорогу, которых у ваших посетителей из Петербурга нет. Цифру PageSpeed стоит держать в голове, но решения принимать по Вебмастеру.
Какая цифра считается нормальной
Универсальной нормы нет, есть норма для типа сайта. Требовать 100 мс от магазина с фильтрами по десяти параметрам бессмысленно.
| Тип страницы | Хорошо | Терпимо | Чинить |
|---|---|---|---|
| Статика или страница из кэша | до 150 мс | 150-300 мс | больше 400 мс |
| Визитка на WordPress без кэша | до 400 мс | 400-700 мс | больше 800 мс |
| Каталог на 500 позиций | до 500 мс | 500-900 мс | больше 1200 мс |
| Магазин, страница товара | до 600 мс | 600-1000 мс | больше 1500 мс |
| Корзина и оформление заказа | до 800 мс | 800-1500 мс | больше 2000 мс |
| Админка WordPress | до 900 мс | 900-1800 мс | больше 2500 мс |
Корзина и личный кабинет всегда медленнее витрины, потому что их нельзя закэшировать целиком: содержимое у каждого посетителя своё. Админка медленнее фронта по той же причине плюс проверки прав на каждый чих.
Порог 600 мс из PageSpeed это граница, за которой Google рекомендует заняться сервером. Для страницы товара в магазине 700 мс всё равно остаются рабочей цифрой, и сокращать их до 400 мс имеет смысл только после того, как закрыты картинки и скрипты. Экономия 300 мс на сервере не видна на фоне трёх мегабайт фотографий.
Где теряются секунды
Четвёртый отрезок раздувается по нескольким сценариям, и они хорошо различимы.
PHP считает то, что можно не считать
Классика WordPress: тридцать активных плагинов, каждый цепляется к хуку init и делает что-то полезное. По отдельности каждый стоит 5-15 мс, вместе триста.
Замерить вклад можно грубым, но честным способом: отключить все плагины, снять curl, включать по одному и снимать снова. Скучно, зато работает без профилировщика. Полчаса на сайт с двадцатью плагинами.
Отдельная категория это плагины конструкторов страниц. Elementor или WPBakery на визитке легко добавляют 200-300 мс к каждому запросу, потому что вёрстка страницы каждый раз собирается из сериализованной структуры в базе.
База отвечает медленно
Симптом: время ответа растёт линейно с количеством записей. Год назад было 300 мс, стало 900, товаров стало вчетверо больше.
Ищем медленные запросы. На shared-хостинге лог медленных запросов обычно недоступен, но статистику собирает Query Monitor для WordPress или встроенный отладчик Битрикса. Про разбор конкретных запросов у меня есть подробный текст про медленные запросы MySQL.
Быстрая проверка на раздутый autoload в WordPress, она занимает секунды и часто сразу даёт ответ:
SELECT option_name, LENGTH(option_value) AS bytes
FROM wp_options
WHERE autoload = 'yes'
ORDER BY bytes DESC
LIMIT 20;
Нормальный суммарный autoload это 200-800 КБ. Я видел 14 МБ: удалённый плагин аналитики оставил в опциях полугодовой журнал событий, и WordPress тянул его из базы на каждый запрос, включая запросы к картинкам.
Внешние запросы прямо из кода
Самый обидный сценарий. Виджет курсов валют, подгрузка отзывов с внешнего сервиса, проверка лицензии плагина, счётчик подписчиков. Всё это делается синхронно во время генерации страницы: PHP отправляет HTTP-запрос наружу и ждёт ответа.
Пока внешний сервис жив и быстр, вы платите 80-150 мс и не замечаете. Когда сервис ложится или его блокируют, вы платите таймаут, а это 5 или 30 секунд на каждый заход посетителя.
Поймать такие запросы в WordPress можно одним фильтром во временном мю-плагине:
add_filter('pre_http_request', function ($pre, $args, $url) {
error_log('HTTP OUT ' . $_SERVER['REQUEST_URI'] . ' -> ' . $url);
return $pre;
}, 10, 3);
Открываем главную, смотрим error_log в корне сайта. Если там при простом просмотре страницы висят три обращения к чужим доменам, вы нашли свои полсекунды. Лечится переносом таких вызовов в фоновую задачу с сохранением результата в транзиент на час.
Кэша просто нет
На чистом WordPress без кэширующего плагина каждый заход это полный цикл: загрузка ядра, инициализация плагинов, 40-80 запросов к базе, сборка шаблона. Триста миллисекунд на этом сжигается ещё до того, как начнётся ваш код.
Хостинг или сайт: проверка статикой
Дешёвый способ разделить ответственность за тридцать секунд. Кладём в корень сайта текстовый файл и меряем его.
echo ok > /home/user/public_html/ping.txt
curl -w "tls %{time_appconnect} ttfb %{time_starttransfer}n"
-o /dev/null -s https://example.ru/ping.txt
curl -w "tls %{time_appconnect} ttfb %{time_starttransfer}n"
-o /dev/null -s https://example.ru/
Статический файл не касается PHP и базы вообще: веб-сервер просто отдаёт его с диска. Дальше читаем результат по таблице.
| Статика | Динамика | Кто виноват |
|---|---|---|
| 60 мс | 900 мс | сайт: PHP, база, плагины |
| 550 мс | 700 мс | инфраструктура: канал, география, перегруз узла |
| 400 мс | 2500 мс | оба, начинать с сайта |
| ночью 60 мс, днём 500 мс | ночью 300, днём 1800 | соседи по shared и лимиты тарифа |
Последняя строка про общий хостинг: процессорное время там делится между сотнями сайтов, и в пиковые часы вам достаётся меньше. Если разброс замеров в течение дня трёхкратный, а код не менялся, это упор в лимиты. Что с этим делать, я расписал в статье про TTFB больше 600 мс на shared-хостинге.
Ещё одна проверка, которую делают редко: снимите замер по IP сервера, минуя DNS и CDN. Иногда выясняется, что лишние 200 мс живут в цепочке из трёх CNAME-записей или в бесплатном прокси, который посадили перед сайтом ради защиты от ботов.
Кэш страниц лечит симптом
Кэширующий плагин превращает 900 мс в 70 мс. Выглядит как победа, и в отчёте PageSpeed это действительно победа. Но кэш ничего не ускорил, он просто перестал вызывать медленный код для гостей.
Полный ценник платят те, кто мимо кэша не проходит:
- первый посетитель после сброса кэша (а сбрасывается он при каждой публикации),
- поисковый робот, который часто заходит на редкие страницы с холодным кэшем,
- покупатель в корзине и на оформлении заказа,
- вы сами в админке,
- авторизованный клиент в личном кабинете.
Плюс кэш маскирует деградацию. Код медленно ухудшается год за годом, а вы этого не видите, пока в один день кэш не отключится ради отладки или пока хостер не выключит модуль.
Правильный порядок такой: сначала довести время ответа без кэша до приличных цифр, потом включить кэш поверх. Обратный порядок означает, что вы никогда не узнаете, сколько на самом деле стоит ваша главная страница. Уровни кэширования и что где включать я разбирал в тексте про четыре уровня кэша сайта.
Диагностика за час: пять шагов
Шаг 1
Снимите десять замеров curl по главной странице с паузой в 3 секунды. Запишите минимум, максимум и типичное значение. Стабильные числа означают код, скачущие означают хостинг.
Шаг 2
Разделите замер на части: ttfb минус tls даёт чистую работу сервера. Если эта разница меньше 150 мс, а общий TTFB большой, ваша проблема в дороге и сертификатах, а не в сайте. Дальше можно не копать, идите к хостеру или меняйте площадку.
Шаг 3
Положите ping.txt в корень и сравните статику с динамикой. Разница больше чем в пять раз указывает на PHP и базу, разница меньше двух раз на инфраструктуру.
Шаг 4
Если виноват сайт, отключите все плагины на копии (не на живом сайте) и снимите замер. Включайте плагины по одному, отмечая прирост. Обычно два-три плагина дают 70 процентов лишнего времени.
Шаг 5
Проверьте autoload запросом из раздела про базу и включите лог исходящих HTTP-запросов на десять минут. Эти две проверки занимают пятнадцать минут и в половине случаев закрывают вопрос без всякого профилировщика.
Чек-лист того, что стоит зафиксировать письменно после диагностики: дата замера, тип страницы, десять значений TTFB, значение по статике, список отключённых плагинов с приростом каждого. Через полгода, когда сайт снова начнёт тормозить, этот листок сэкономит вам повторный час.
Частые вопросы
Какое время ответа сервера считается нормальным?
Для страницы из кэша хорошим считается значение до 150 мс, для визитки на WordPress без кэша до 400 мс, для страницы товара в магазине до 600 мс. PageSpeed подсвечивает красным всё выше 600 мс. Значения больше 1500 мс на витрине означают, что сайт нужно разбирать, а не докупать хостинг.
Чем время ответа сервера отличается от скорости загрузки сайта?
Время ответа это только первый байт: пока браузер ждёт, экран пустой. Скорость загрузки включает ещё картинки, шрифты, скрипты и отрисовку. Сайт с ответом в 200 мс может рисоваться пять секунд из-за трёх мегабайт неоптимизированных фотографий. Это две разные задачи, чинятся они по-разному.
Влияет ли время ответа сервера на позиции в Яндексе?
Влияет косвенно. Прямого фактора ранжирования «TTFB» нет, но медленный ответ снижает скорость обхода: робот выделяет вашему сайту квоту времени, и при ответе в две секунды он успевает обойти впятеро меньше страниц. Плюс растут отказы, а поведение пользователей Яндекс учитывает уже напрямую.
Поможет ли переезд на VPS, если сервер отвечает две секунды?
Только если проверка статикой показала медленную отдачу обычного файла. Когда ping.txt отдаётся за 60 мс, а главная за 2000 мс, дело в коде: на VPS вы получите те же две секунды за большие деньги. Сначала диагностика, потом переезд, иначе вы перевезёте медленный код на дорогую площадку.
Что делать с полученной цифрой
Снимите десять замеров curl прямо сейчас, это займёт минуту. Дальше два сценария. Если разброс большой и статика тоже медленная, вопрос к хостингу, и решается он сменой тарифа или площадки. Если числа стабильные и высокие, дело в сайте, и лечится оно по шагам выше.
Разбор чужого сайта с отчётом по пяти отрезкам и списком виновников занимает у меня рабочий день. Это разовая работа, цены на неё и на регулярное обслуживание есть на странице тарифов. Если сайт уже лежит или отвечает по десять секунд, пишите через форму, такое разбираю в день обращения.