DNS отвечает 200 мс — это треть времени открытия сайта: считаем вклад резолвинга
Открываете DevTools, смотрите на водопад загрузки страницы и видите, что первый запрос к домену начинается не сразу, а после заметной паузы с подписью "DNS Lookup". Для одного домена это может быть 20 мс и незаметно на глаз. Но на странице обычно не один домен — свой сервер, CDN, шрифты, аналитика, виджеты — и каждый добавляет собственный резолвинг в свой момент времени. Разберёмся, из чего складывается эта пауза, почему она не всегда дорогая и что реально можно сделать, чтобы она не съедала треть времени открытия сайта.
Содержание
- Путь DNS-запроса: от браузера до авторитативных серверов
- Кеш браузера, ОС и резолвер провайдера — зачем нужны три уровня
- TTL записи: сколько стоит дорогой путь и как часто он повторяется
- Каждый сторонний домен — отдельный lookup, и как это складывается в waterfall
- Как измерить вклад DNS в загрузку страницы: DevTools и curl
- Что реально ускоряет DNS-часть загрузки
Путь DNS-запроса: от браузера до авторитативных серверов
Когда браузеру нужно узнать IP-адрес домена, он не сразу идёт в интернет. Запрос проходит через несколько уровней, и на каждом есть шанс получить ответ быстро, не доходя до самого дорогого варианта.
Первым делом браузер смотрит в собственный кеш DNS — у Chrome и Firefox он свой, отдельный от системного. Если записи там нет или она устарела, запрос уходит на уровень операционной системы: в Linux это обычно systemd-resolved или nscd, в Windows — DNS Client, в macOS — mDNSResponder. Они тоже кешируют ответы и могут закрыть запрос без выхода в сеть.
Если и там пусто, запрос уходит к резолверу, который прописан в сетевых настройках — это может быть DNS провайдера (обычно он самый близкий по сети, но не всегда самый быстрый) или публичный резолвер вроде 1.1.1.1 (Cloudflare) или 8.8.8.8 (Google), если пользователь или администратор явно их указал. Этот резолвер — рекурсивный: он берёт на себя всю дальнейшую работу и возвращает браузеру уже готовый IP-адрес.
Дорогой путь начинается, если у рекурсивного резолвера тоже нет актуального ответа в кеше. Тогда он идёт по цепочке:
- Спрашивает корневой сервер (root), какой сервер отвечает за зону верхнего уровня (
.com,.ru,.ioи так далее). - Спрашивает TLD-сервер, какой NS обслуживает конкретный домен.
- Спрашивает авторитативный сервер домена — тот, где реально хранится A- или AAAA-запись — и получает финальный ответ.
Каждый из этих трёх шагов — это отдельный сетевой запрос-ответ, и если авторитативный сервер физически далеко (например, у DNS-провайдера домена нет anycast-узла рядом с резолвером пользователя), сумма может набежать заметная. После этого резолвер кеширует результат на время, указанное в TTL записи, и возвращает ответ браузеру. О том, как именно рекурсивный резолвер обходит эту цепочку и почему это в норме укладывается в десятки миллисекунд, подробно разобрано в статье про путь DNS-запроса до авторитативного сервера.
Кеш браузера, ОС и резолвер провайдера — зачем нужны три уровня
Смысл всей этой многоуровневой конструкции — не заставлять полную цепочку "корень → TLD → авторитативный сервер" отрабатывать на каждый чих. Она нужна только при промахе кеша (cache miss), а промахи в норме случаются редко: TTL-записи большинства доменов рассчитаны так, чтобы резолвер долго отдавал ответ из памяти.
Кеш браузера живёт, пока открыта вкладка (и немного после), кеш ОС переживает закрытие браузера, а кеш резолвера провайдера или публичного сервиса общий на всех пользователей этой сети — то есть если сосед по подсети уже открывал тот же сайт минуту назад, ваш запрос почти наверняка попадёт в кеш резолвера и не пойдёт дальше. Именно поэтому "холодный" первый визит на сайт для конкретного пользователя обычно немного дороже по DNS, чем повторные.
Практическая проблема в том, что вы не управляете первыми двумя уровнями — они на стороне пользователя. Вы управляете только TTL записи на своей стороне и выбором authoritative DNS-провайдера — то, насколько быстро он отвечает, когда до него всё-таки доходит рекурсивный запрос.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверTTL записи: сколько стоит дорогой путь и как часто он повторяется
TTL (time to live) — это число секунд, которое DNS-резолвер имеет право хранить ответ в кеше, прежде чем спросить снова. Оно задаётся в самой записи на стороне authoritative-сервера, а не выбирается резолвером — резолвер обязан ему подчиниться (за редкими исключениями агрессивного кеширования у некоторых провайдеров).
Логика простая: чем больше TTL, тем реже происходит дорогой путь с обходом корневых, TLD и авторитативных серверов, и тем меньше пользователей вообще замечают паузу на DNS — для них ответ уже лежит в кеше резолвера или ОС. Но у длинного TTL есть обратная сторона: если вам нужно срочно поменять IP (миграция на другой сервер, аварийное переключение), часть пользователей продолжит стучаться по старому адресу, пока не истечёт TTL у их резолвера. Реальный разбор такого случая, когда TTL в сутки превратил быструю миграцию в двухдневный процесс, — в статье про TTL 86400 при переезде на новый сервер.
Слишком короткий TTL — тоже не бесплатно: каждое его истечение заставляет резолвер снова идти к authoritative-серверу, а это дополнительная нагрузка на DNS-инфраструктуру и для части пользователей — лишняя пауза на резолвинг именно в момент, когда кеш только что протух. При большом трафике короткий TTL ощутимо увеличивает число запросов, которые обслуживает ваш DNS-провайдер, а если у него лимит на количество запросов в секунду — это отдельный фактор для планирования, разобранный в статье про то, сколько DNS-запросов в секунду держит резолвер. Подробнее о том, почему изменения в DNS расходятся по пользователям волнами, а не мгновенно, — в статье про TTL и неравномерное распространение изменений.
Разумный баланс для большинства сайтов — TTL в диапазоне от нескольких минут до часа для записей, которые могут понадобиться поменять быстро (A/AAAA основного домена), и более длинный TTL (несколько часов и больше) для записей, которые меняются редко (MX, TXT, статичные поддомены). Перед плановой миграцией TTL стоит заранее снизить — это классическая практика: сначала уменьшить TTL и подождать, пока старое значение вымоется из кешей, потом менять IP, потом вернуть TTL обратно.
Каждый сторонний домен — отдельный lookup, и как это складывается в waterfall
Здесь кроется главная причина, почему DNS ощутимо влияет на загрузку страницы, даже если каждый отдельный резолвинг быстрый. Браузер резолвит IP не один раз на страницу, а один раз на каждый уникальный домен, к которому обращается. Типичная современная страница тянет ресурсы не только со своего домена:
- сам сайт —
example.com; - CDN для статики —
cdn.example-cdn.net; - шрифты —
fonts.googleapis.comиfonts.gstatic.com(это два разных домена); - аналитика —
www.google-analytics.comили аналог; - виджеты, чаты, платёжные кнопки — ещё по домену на каждый.
Если на странице 6-8 уникальных доменов, и хотя бы часть из них резолвится "вхолодную" (нет в кешах пользователя), суммарное время на DNS для всех этих доменов может оказаться сравнимо с временем самой полезной загрузки. Причём резолвинг для стороннего домена — это блокирующий шаг именно для запроса к этому домену: браузер не может начать TCP-соединение и тем более TLS-handshake, пока не получит IP. На waterfall это видно как узкая цветная полоска в начале каждой строки, помеченная "DNS Lookup" — и если таких полосок много и они не переиспользуют уже тёплые домены, они выстраиваются в заметную сумму, особенно если браузер резолвит их последовательно, а не параллельно (что зависит от лимитов на одновременные подключения и от того, как страница объявляет ресурсы).
Важный нюанс: если несколько ресурсов идут с одного и того же домена (например, все шрифты у Google Fonts грузятся через fonts.gstatic.com), резолвинг для этого домена происходит один раз, а не на каждый файл — дальше используется уже полученный и закешированный на время TTL IP. Поэтому вклад DNS растёт не от числа запросов, а именно от числа уникальных доменов.
Как измерить вклад DNS в загрузку страницы: DevTools и curl
Прежде чем что-то оптимизировать, стоит увидеть цифры на своём конкретном сайте — общие рассуждения про "DNS может стоить заметную часть времени" ничего не говорят про то, сколько теряете именно вы.
Chrome DevTools. Откройте вкладку Network, перезагрузите страницу с очищенным кешем (Cmd/Ctrl+Shift+R или галочка "Disable cache" при открытых DevTools), кликните на любой запрос и откройте вкладку Timing. Там будет разбивка фаз запроса, и один из первых блоков — "DNS Lookup". Если он есть и заметен — резолвинг для этого домена не был в кеше на момент запроса. Если блока нет вовсе (фаза нулевая или отсутствует) — IP уже был известен браузеру. Полезно пройтись по всем сторонним доменам страницы и посмотреть, у скольких из них DNS Lookup заметный, а не близкий к нулю.
curl с -w. Для разового измерения времени резолвинга к конкретному домену, без браузера и его собственного кеша:
curl -w "dns: %{time_namelookup}s connect: %{time_connect}s tls: %{time_appconnect}s ttfb: %{time_starttransfer}s total: %{time_total}s\n" \
-o /dev/null -s https://example.com
time_namelookup — это время от старта запроса до получения IP-адреса, то есть чистая стоимость DNS-резолвинга curl'ом (через системный резолвер). Если хотите исключить локальный кеш ОС и проверить именно ответ конкретного резолвера, используйте dig или kdig напрямую:
dig @1.1.1.1 example.com A +stats
В выводе dig есть строка Query time, которая показывает именно это. Полезно прогнать один и тот же домен через несколько резолверов (провайдера, 1.1.1.1, 8.8.8.8) и сравнить — но делайте несколько замеров подряд, а не один: первый запрос почти всегда покажет "холодную" цифру с обходом всей цепочки, а последующие — уже кешированный ответ, и разница между ними — это и есть наглядная иллюстрация того, зачем нужен TTL.
Для оценки вклада DNS во всю страницу удобно смотреть на суммарную "критическую" часть — то есть DNS для доменов, без которых не может начаться рендеринг (основной домен, CDN с критичным CSS/JS), а не для всех подряд: резолвинг третьестепенного виджета, который загружается асинхронно после отрисовки страницы, не блокирует восприятие скорости пользователем, даже если формально занимает время в waterfall.
Что реально ускоряет DNS-часть загрузки
DNS prefetch и preconnect для сторонних доменов. Это самый дешёвый способ убрать видимую задержку — просто сказать браузеру заранее, ещё до того, как понадобится конкретный ресурс, что домен скоро пригодится:
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link rel="preconnect" href="//fonts.gstatic.com" crossorigin>
dns-prefetch запускает только резолвинг заранее, preconnect идёт дальше — резолвит DNS, устанавливает TCP-соединение и, если это HTTPS, проходит TLS handshake, так что к моменту реального запроса остаётся только отправить HTTP-запрос. Разница на глаз обычно небольшая для одного домена, но если критичных сторонних доменов несколько и они сейчас резолвятся последовательно в браузере, суммарный выигрыш становится заметен. Не стоит развешивать preconnect на все домены подряд — браузер ограничивает число одновременных ранних соединений, и злоупотребление может, наоборот, отвлечь ресурсы от действительно важных доменов.
Сокращение числа уникальных доменов. Каждый сторонний домен — это не только DNS, но и отдельное TCP/TLS-соединение. Если можно раздавать шрифты со своего домена или через тот же CDN, что и остальную статику, вместо стороннего хостинга — вы убираете целый резолвинг и целое соединение. То же касается аналитики: часть решений умеют работать через прокси на вашем же домене, что убирает лишний DNS-lookup, хотя и требует дополнительной настройки на стороне сервера.
Выбор быстрого authoritative DNS-провайдера. Это касается только "холодных" запросов, когда рекурсивный резолвер идёт до конца цепочки — но именно они формируют первое впечатление у нового посетителя. Провайдер с anycast-сетью и присутствием узлов близко к вашей аудитории отвечает быстрее в среднем по геонезависимости, чем DNS-хостинг с одной точкой присутствия. Точные цифры задержки у конкретных провайдеров сильно зависят от того, где физически находится ваша аудитория и через какого резолвера она ходит, поэтому смысла гадать без собственных замеров нет — но общий принцип: чем больше anycast-узлов у DNS-провайдера и чем ближе они к пользователям, тем меньше шанс, что холодный резолвинг окажется дорогим.
Разумный TTL — компромисс, а не крайность. Как уже разобрано выше: слишком долгий TTL снижает гибкость при смене IP, слишком короткий добавляет лишнюю нагрузку на резолвинг и на сам DNS-провайдер. Для записей, которые реально могут понадобиться сменить быстро (например, A-запись основного сайта), разумный диапазон — от нескольких минут до часа в спокойном режиме, с временным снижением перед плановыми изменениями инфраструктуры.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько вообще "весит" DNS в общем времени загрузки страницы?
Зависит от числа уникальных доменов на странице и от того, сколько из них резолвятся "вхолодную" у конкретного пользователя. Для одного домена с тёплым кешем это может быть околонулевая величина, для страницы с десятком сторонних доменов при первом визите — заметная доля времени до начала полезной загрузки. Точную цифру для своего сайта нужно смотреть в DevTools или через curl -w, обобщённые проценты без собственных замеров — не более чем ориентир.
Помогает ли переход на публичный резолвер вроде 1.1.1.1 или 8.8.8.8 ускорить загрузку сайтов?
Это решение на стороне пользователя, а не владельца сайта, и оно влияет на скорость резолвинга доменов, которые этот резолвер ещё не кешировал. Выигрыш зависит от того, насколько резолвер провайдера медленнее или быстрее публичного в конкретной сети — универсального ответа "да, всегда быстрее" нет.
preconnect можно ставить на любое количество доменов без риска?
Нет — браузеры ограничивают число одновременно устанавливаемых ранних соединений, и если пометить preconnect слишком много доменов, часть из них не даст выигрыша либо оттянет ресурсы от по-настоящему критичных. Имеет смысл использовать его точечно — для 2-4 доменов, без которых страница не может начать рендериться.
Почему при повторном визите на сайт DNS почти не заметен в waterfall, а при первом — заметен?
Потому что при первом визите записи ещё нет в кеше браузера и, возможно, в кеше ОС и резолвера, поэтому запрос идёт по полной цепочке. При повторном визите (в пределах TTL) ответ уже лежит в одном из кешей и отдаётся почти мгновенно.
Стоит ли делать TTL максимально длинным, раз это снижает число резолвингов?
Нет, если планируете когда-либо менять IP быстро — длинный TTL означает, что часть пользователей продолжит стучаться по старому адресу ещё долго после смены записи. Разумнее держать TTL умеренным для записей, которые могут потребовать оперативной смены, и снижать его заранее перед плановой миграцией.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →