Набираете адрес, жмёте Enter, и через полсекунды страница уже на экране. Кажется, что браузер просто «скачал файл». На самом деле за эти полсекунды он успел спросить у нескольких серверов, где живёт сайт, договориться о соединении, проверить паспорт сервера, придумать общий секретный ключ, отправить запрос и дождаться, пока сервер соберёт страницу. Каждый шаг можно измерить — и в этом цикле мы разберём их по одному на живом примере, на этом самом сайте.
Это первая часть цикла «Что происходит, когда открываешь сайт».
Один запрос, разложенный по времени
У curl есть ключ -w, который печатает, сколько миллисекунд прошло к концу каждого этапа. Запускаем с сервера в дата-центре — то есть из совсем другой сети, чем сам сайт:
curl -so /dev/null -w 'dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
https://alekseychikun.ru/blog/
dns=0.036213 tcp=0.063994 tls=0.192034 ttfb=0.501969 total=0.557516
Числа накопительные: каждое — время от старта до конца этапа. Если вычесть соседние, получится длительность каждого шага:
| Этап | Что происходит | Мс |
|---|---|---|
| DNS | узнаём IP-адрес по имени сайта | 36 |
| TCP | открываем соединение: «можно?» — «можно» — «поехали» | 28 |
| TLS | проверяем сертификат и договариваемся о ключах шифрования | 128 |
| ожидание | запрос ушёл, сервер собирает страницу, первый байт ответа в пути | 310 |
| тело | докачиваем остальные 44 КБ HTML | 55 |
Что здесь видно сразу
Сеть быстрая, медленно всё остальное. Пакет доходит до сервера и обратно за 28 мс — ровно столько заняло открытие TCP-соединения, это один круг. Дорога через двенадцать узлов разных операторов обходится дешевле, чем любой из следующих шагов.
TLS дороже TCP в четыре раза. Тут не только сеть: сервер подписывает рукопожатие своим ключом, клиент проверяет цепочку сертификатов. Как это устроено и почему замок в адресной строке что-то значит — в седьмой и восьмой частях.
Больше всего времени — на сервере. 310 мс между «запрос отправлен» и «пришёл первый байт» — это в основном PHP, который собирает страницу, и один круг по сети. Если страница лежит в кэше, этот отрезок сжимается в разы.
Второй запрос быстрее почти вдвое
dns=0.000594 tcp=0.029706 tls=0.098910 ttfb=0.257860 total=0.316496
DNS теперь занял 0,6 мс вместо 36: адрес уже лежит в кэше резолвера, ходить по цепочке серверов не нужно. TLS — 69 мс вместо 128, ожидание ответа — 159 вместо 310. Сеть осталась той же, 29–30 мс на круг. Ускорилось то, что можно запомнить.
Первый заход всегда дороже. Поэтому мерить «скорость сайта» одним запросом бессмысленно: вы увидите либо холодный путь, либо тёплый, и не узнаете, какой именно. Делайте три-пять запросов подряд и смотрите на разброс.
Маршрут цикла
Дальше по шагам, в том порядке, в каком их проходит браузер:
- DNS — как имя превращается в адрес, и почему после переезда сайт ещё сутки открывается на старом сервере;
- IP-адрес, порт и маршрут — через какие узлы идёт пакет и что такое домашний NAT;
- TCP — рукопожатие на живом захвате трафика и как самому снять такой захват;
- TLS — рукопожатие, сертификат, цепочка доверия и почему человек посередине не читает ваши данные;
- HTTP — запрос и ответ, чем отличаются версии 1.1, 2 и 3;
- обратная дорога — где на самом деле уходит время, и как по уровням искать, что сломалось, когда «сайт не открывается».
Все команды из цикла можно повторить у себя: понадобятся curl, dig, mtr, openssl и tcpdump. На Linux и macOS они есть или ставятся одной командой, на Windows проще всего запустить их в контейнере с сетевыми утилитами.
Сайт открывается медленно, а где именно — непонятно?
Пришлите адрес — разложу запрос по этапам и покажу, что из них можно ускорить.
// загружаю комментарии…