1. Гайды
  2. Сеть и диагностика

Анатомия медленного запроса: куда уходят миллисекунды

Сайт «тормозит», но что именно: сеть, рукопожатия или сам бэкенд? HTTPS-запрос раскладывается на пять фаз, каждую можно измерить одной командой.

Актуально для замеры Globalping и curl -w 2026-09-24; RFC 9293, RFC 8446, RFC 5246/7918, RFC 9000, RFC 9113/9114; curl 8.18Обновлено 24.09.2026 7 мин чтения

«Сайт медленный» звучит как диагноз, но это жалоба. Пока не видно, на какую фазу запроса ушло время, чинить можно что угодно: хостера, nginx, CDN или собственные нервы.

Из чего состоит запрос

Первый HTTPS-запрос к серверу по новому соединению проходит пять фаз. Почти все они стоят целое число RTT (round-trip time, время «туда и обратно» до сервера), поэтому расстояние до сервера умножается на число рукопожатий.

  1. Клиент
  2. TCP готов
  3. TLS 1.3 готов
  4. Первый байт
  5. Ответ скачан
Минимальная цена первого запроса по новому соединению с TLS 1.3 (по RFC 9293 и RFC 8446)
ФазаЧто происходитСколько стоит
DNSРезолвер ищет A/AAAA. Если ответ есть в кэше, почти бесплатноот ~0 до сотен мс, зависит от резолвера и TTL
TCPSYN → SYN/ACK → ACK. Клиент считает соединение установленным, получив SYN/ACK (RFC 9293, рис. 6)1 RTT
TLS 1.3ClientHello → ServerHello…Finished → Finished, после чего клиент уже шлёт данные (RFC 8446, рис. 1)1 RTT; ещё +1, если сервер ответил HelloRetryRequest
TLS 1.2Полное рукопожатие: две пары сообщений до первых данных (RFC 5246, рис. 1). False Start сокращает его до одного RTT (RFC 7918)2 RTT
Ожидание ответа (TTFB)Запрос долетает до сервера, сервер думает, первый байт летит обратно1 RTT + время бэкенда
ЗагрузкаТело ответазависит от размера и канала

В TLS 1.3 есть и 0-RTT: при повторном подключении клиент шлёт данные сразу. Но RFC 8446 прямо предупреждает, что у таких данных нет защиты от повтора (replay), поэтому включать 0-RTT для запросов, которые что-то меняют, нельзя.

В QUIC (HTTP/3) криптографическое и транспортное рукопожатие совмещены (RFC 9000, раздел 7), отдельной фазы TCP там нет.

Реальный замер: где сеть, а где сервер

Globalping отдаёт тайминги по фазам, а не накопительно. Согласно спецификации API: dns время резолва, tcp от конца DNS до установленного TCP, tls от TCP до готового TLS, firstByte от готового соединения до первого байта ответа, download от первого байта до конца.

Вот запрос к wikipedia.org с домашней пробы в Москве (сеть Timeweb):

DNS 1 мс
TCP 41 мс
TLS 47 мс
Ожидание ответа 42 мс
Всего131 мс
GET https://wikipedia.org/ с домашней пробы Globalping, Москва (Timeweb), TLS 1.3, ответ 301; измерение 2WKLWjmKdGA5YlAJj00021Bt7, 24.09.2026

Все три сетевые фазы примерно равны: 41, 47 и 42 мс. Это и есть RTT до сервера, помноженный на три рукопожатия. Серверу на ответ-редирект понадобилась миллисекунда-другая, загрузка заняла 0 мс. Такой запрос ускоряется только одним способом: сократить число RTT или сам RTT.

А вот habr.com/ru/articles/ из той же пробы:

DNS 6 мс
TCP 2 мс
TLS 3 мс
Ожидание ответа 225 мс
Загрузка 1 мс
Всего237 мс
GET https://habr.com/ru/articles/ с домашней пробы Globalping, Москва (Timeweb), TLS 1.3, ответ 200; измерение 2mP4kZK2aazEwqUJW00021Bt9, 24.09.2026. Загрузка не показательна: API Globalping возвращает не больше 10 КБ тела

RTT около 2 мс, сервер буквально рядом, а первый байт пришёл через 225 мс. Около 220 мс из них бэкенд генерировал страницу. Сеть тут не виновата, и CDN перед таким сайтом не поможет, если страница не кэшируется.

Важно

Главное правило чтения: большой TTFB при быстрых DNS, TCP и TLS означает медленный сервер, а не медленную сеть. Если все фазы примерно равны и велики, проблема в расстоянии. Если одна фаза выбивается, смотри на неё.

Одна страница из разных стран

Та же проверка wikipedia.org, общее время по пробам:

Фалькенштайн, Hetzner42 мс
Амстердам, DELUXHOST73 мс
Сингапур, OVH80 мс
Хельсинки, Hetzner100 мс
Москва, Timeweb (дом.)131 мс
Москва, Yandex.Cloud148 мс
Санкт-Петербург, Selectel190 мс
Курск, Kursktelecom (дом.)325 мс
Новосибирск, МТС (дом.)334 мс
Томск (дом.)337 мс
Алматы, NLS Kazakhstan (дом.)1825 мс
Полное время GET https://wikipedia.org/ по пробам Globalping, измерение 2WKLWjmKdGA5YlAJj00021Bt7, 24.09.2026. «дом.» означает домашнего провайдера

Что тут видно:

  • Сингапур быстрее Москвы, хотя дальше от Европы. DNS Википедии отдал сингапурской пробе другой адрес (103.102.166.224 вместо 185.15.59.224), и TCP до него занял 1 мс. Это и есть «ближе к пользователю»: точка присутствия рядом снимает сразу все RTT-фазы.
  • Сибирь медленнее Москвы в 2,5 раза: TCP 90 мс вместо 41. Каждое рукопожатие повторяет эту разницу.
  • Алматы: фаза tcp 1122 мс при TLS 124 мс. Раз TLS (один RTT) занял ~120 мс, то TCP-рукопожатие за 1122 мс похоже на повтор SYN: по RFC 6298 начальный таймаут повторной передачи равен 1 секунде. В проверке github.com той же минутой у пробы из той же сети tcp был 1101 мс. Если так, один потерянный пакет на рукопожатии добавил к запросу целую секунду.
  • Курск: DNS 113 мс, дольше, чем TCP. Холодный кэш резолвера бьёт по первому запросу.

Замер у себя: curl -w

У curl тайминги накопительные, от начала запроса (man curl, раздел --write-out): time_namelookup до конца резолва, time_connect до установленного TCP, time_appconnect до готового TLS, time_starttransfer до первого байта, time_total всё целиком. Длительность фазы — разность соседних значений.

Готовый формат в файле:

cat > ~/curl-phases.txt <<'EOF'
     dns: %{time_namelookup}\n
 connect: %{time_connect}\n
     tls: %{time_appconnect}\n
    ttfb: %{time_starttransfer}\n
   total: %{time_total}\n
    http: %{http_version}  ip: %{remote_ip}  code: %{http_code}\n
EOF
curl -so /dev/null -w @$HOME/curl-phases.txt https://example.com/

Или сразу по фазам в миллисекундах:

curl -so /dev/null -w '%{time_namelookup} %{time_connect} %{time_appconnect} %{time_starttransfer} %{time_total}\n' https://example.com/ \
  | awk '{printf "DNS %.0f  TCP %.0f  TLS %.0f  сервер %.0f  загрузка %.0f (мс)\n", $1*1000, ($2-$1)*1000, ($3-$2)*1000, ($4-$3)*1000, ($5-$4)*1000}'

Реальный вывод для habr.com/ru/articles/ с машины автора, 24.09.2026:

DNS 6  TCP 17  TLS 24  сервер 240  загрузка 169  (мс)

Картина та же, что у Globalping: сетевые фазы в десятки миллисекунд, сервер в сотни. Загрузка тут настоящая, curl скачал всю страницу (около 340 КБ).

Лайфхак

Меряй несколько раз. Тот же github.com/torvalds/linux с той же машины в один заход дал TTFB 496 мс, в следующий 73 мс. Одиночный замер TTFB говорит о кэше бэкенда не меньше, чем о бэкенде.

Похожую однострочную команду до api.telegram.org сообщество держит в наборе тестов VPS.

Что с этим делать

Что видноПричинаЧто делать
Все сетевые фазы равны и великиДалеко до сервераСервер или CDN ближе к аудитории. По опыту сообщества, у части EU-хостеров нет прямых стыков с РФ, отсюда лишние десятки мс ( Прочее по хостингам)
TCP + TLS платятся на каждый запросНет переиспользования соединенийkeep-alive: HTTP/1.1 по умолчанию держит соединения постоянными (RFC 9112, раздел 9.3); HTTP/2 гонит много запросов по одному соединению (RFC 9113)
TLS занимает два RTTTLS 1.2Включить TLS 1.3 на сервере
Потери на плохих каналах тормозят всёHTTP/2 поверх TCP: потерянный пакет останавливает все потоки (RFC 9114, раздел 1.1)HTTP/3 (QUIC), где потоки независимы
DNS долгий на первом запросеХолодный кэш резолвера, маленький TTLНе ставить TTL в секунды без нужды: TTL и есть время, сколько запись можно кэшировать (RFC 1035)
TTFB большой при быстрой сетиБэкендПрофилировать приложение, кэшировать ответы, смотреть базу. Сеть тут ни при чём

Эффект keep-alive легко увидеть: если дать curl два URL одной командой, второй запрос пойдёт по тому же соединению (переменная num_connects покажет 0).

curl -s -o /dev/null -o /dev/null \
  -w 'conns=%{num_connects} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer}\n' \
  https://github.com/torvalds/linux https://github.com/torvalds/linux

В замере 24.09.2026 первый запрос: conns=1, TLS готов на 54 мс, первый байт на 73 мс. Второй: conns=0, connect и tls по нулям, первый байт на 19 мс.

Проверить на host.pink

  • host.pink/check/example.com: HTTPS-запрос с ~12 проб по миру, включая домашних провайдеров РФ. В каждой строке общее время, TLS и TTFB. В терминале: curl "host.pink/check/example.com?t=http". Под результатом есть ссылка на тот же замер на globalping.io с полными таймингами.
  • Досье домена: NS, DNS-записи, сертификаты. Полезно, когда тормозит именно DNS.
  • Если сеть в порядке, а из РФ не открывается вообще, это уже другой разбор: Сайт не открывается из РФ. Про TTL и резолверы в сообществе: DNS.

Источники

  • RFC 9293, раздел 3.5, рис. 6: трёхстороннее рукопожатие, клиент в ESTABLISHED после SYN/ACK
  • RFC 8446: рис. 1 (полное рукопожатие TLS 1.3), раздел 2.1 (HelloRetryRequest), раздел 2.3 и 8 (0-RTT и replay)
  • RFC 5246, рис. 1: полное рукопожатие TLS 1.2; RFC 7918: False Start «сокращает задержку рукопожатия до одного RTT»
  • RFC 6298, раздел 2: начальный RTO 1 секунда
  • RFC 9000, раздел 7: совмещённое рукопожатие QUIC; RFC 9113, раздел 2: мультиплексирование HTTP/2; RFC 9114, раздел 1.1: блокировка всех потоков HTTP/2 при потере пакета
  • RFC 9112, раздел 9.3: постоянные соединения HTTP/1.1; RFC 1035, раздел 3.2.1: TTL
  • curl(1), --write-out: time_namelookup, time_connect, time_appconnect, time_starttransfer, time_total, num_connects
  • Спецификация API Globalping: значения timings (dns, tcp, tls, firstByte, download), тело ответа ограничено 10 КБ
  • Замеры 24.09.2026: Globalping 2WKLWjmKdGA5YlAJj00021Bt7 (wikipedia.org), 2zj11OrwPfFIQdNdZ00021Bt8 (github.com), 2mP4kZK2aazEwqUJW00021Bt9 (habr.com); curl 8.18 с машины автора
  • База: Тесты VPS, Прочее по хостингам, DNS