Как ускорить медленный DNS-запрос
Медленный DNS-запрос это время, потраченное до того, как соединение с сайтом вообще началось, и почти всегда его лечит смена резолвера, которому вы задаете вопрос. Страница еще не начала грузиться. Устройство все еще выясняет, куда отправлять запрос.
Что именно измеряет медленный запрос
Загрузка страницы начинается с разрешения имени, потом идет соединение TCP, потом рукопожатие TLS, потом собственное время раздумий сервера. К DNS относится только первый этап, и только его часто можно улучшить, вообще не трогая сайт.
Здесь путают два числа. Закэшированный запрос почти ничего не стоит, потому что ответ уже лежит на вашей машине или в одном шаге от нее. Холодный запрос может включать обращение к корню, потом к домену верхнего уровня, потом к серверам имен самого домена, и каждое это круговой рейс через то расстояние, которое отделяет вас от этих серверов. Меньше 20 мс на прогретом кэше и меньше 100 мс на холодном это ничем не примечательные цифры. Приближение к секунде означает, что один из шагов далеко, перегружен или упирается в таймаут и повторяется.
Современные страницы усугубляют это множеством имен хостов. Шрифтам, аналитике, картинкам и платежным виджетам нужен свой запрос каждому, и браузер, разрешающий десять имен по 300 мс, потратил на DNS три секунды до того, как отрисовал хоть что-то полезное.
Убедитесь, что тормозит именно DNS
Измерьте до того, как что-либо менять. Самая наглядная одиночная команда разбивает запрос на фазы:
curl -o /dev/null -s -w "dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n" https://example.com
Если time_namelookup составляет малую долю от общего времени, DNS вам не мешает и читать надо про время ответа сервера. Если это треть или больше, продолжайте. Отдельно по запросу время печатает сам dig:
dig example.com | grep "Query time"
dig @1.1.1.1 example.com | grep "Query time"
dig @8.8.8.8 example.com | grep "Query time"
В Windows то же измерение делает PowerShell:
Measure-Command { Resolve-DnsName www.example.com }
Measure-Command { Resolve-DnsName www.example.com -Server 1.1.1.1 }
Сравните свой резолвер по умолчанию с публичными. Большой разрыв говорит, что чинить надо на вашей стороне. Похожие цифры везде указывают на серверы имен самого домена.
Один результат полностью выводит вас за пределы этого руководства. Если резолвер мгновенно отвечает NXDOMAIN, имя не опубликовано, и перед вами другая задача, описанная в DNS_PROBE_FINISHED_NXDOMAIN.
Почему это происходит
- Далекий резолвер. Публичные сервисы работают через anycast, поэтому один и тот же адрес отвечает из ближайшей точки. Резолвер провайдера или единственный офисный сервер так не умеют, и каждый запрос платит полный круговой рейс.
- Первый сервер в списке мертв. Клиент досиживает таймаут и только потом спрашивает второй. В системах на glibc по умолчанию до первого повтора проходит 5 секунд, и это ровно та пауза, которую описывают словами «висит, а потом открывается».
- Очень низкие TTL. TTL в 30 или 60 секунд означает, что почти каждый посетитель платит за свежий запрос, потому что закэшированная копия уже устарела.
- Длинные цепочки CNAME. Каждое звено это еще один запрос. Цепочки из трех или четырех звеньев обычны за CDN и маркетинговыми инструментами.
- Медленные авторитативные серверы имен. DNS-провайдер с небольшим числом площадок отвечает быстро части мира и медленно всем остальным.
- Проверка DNSSEC. Проверка цепочки добавляет запросы. Обычно она дешева, но частично сломанная цепочка вызывает повторы, которые выглядят как медлительность.
- Поисковые домены. Резолвер с настроенными суффиксами сначала пробует
example.com.corp.localи только потомexample.com, тратя по неудачному запросу на каждый суффикс. - Запросы AAAA без IPv6. Система спрашивает записи обоих типов и ждет ответ, которым все равно не сможет воспользоваться.
- VPN или фильтрующий прокси, который гонит каждый запрос по туннелю к резолверу на другом континенте.
- Роутер в роли форвардера с крошечным кэшем и слабым процессором.
Как это починить
На устройстве
- Очистите кэши, чтобы измерения были честными:
ipconfig /flushdnsв Windows,sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponderв macOS,sudo resolvectl flush-cachesв Linux. - Посмотрите, какие серверы прописаны и в каком порядке:
Get-DnsClientServerAddress,scutil --dnsилиresolvectl status. Уберите запись, которая больше не отвечает: мертвый первый сервер стоит вам таймаута на каждом холодном запросе. - В Linux сократите ожидание на время разбора, добавив
options timeout:2 attempts:2в/etc/resolv.conf, и уберите неиспользуемые суффиксыsearch. - Отключите VPN и измерьте снова. Если цифра упала вдвое, дело в туннеле и менять надо настройку его резолвера.
В сети
- Задайте резолвер в DHCP на роутере, а не на каждом устройстве отдельно, чтобы все клиенты получили одну и ту же быструю пару.
- Пропишите форвардеру роутера публичный резолвер вместо провайдерского по умолчанию или обойдите форвардер совсем, раздав клиентам публичные адреса напрямую.
- В корпоративной сети с собственным DNS-сервером проверьте, что он пересылает запросы, а не делает полную рекурсию с одной площадки, и что его кэша хватает на весь рабочий день.
На вашем домене
- Поднимите TTL для записей, которые меняются редко. Пять минут это разумный минимум для записи, которую может понадобиться быстро перенести; час или сутки подходят всему стабильному.
- Спрямляйте цепочки CNAME там, где можете. Указывайте запись сразу на конечную цель, а не на череду псевдонимов:
dig www.example.com CNAME +shortпокажет глубину вашей цепочки. - Возьмите DNS-провайдера с anycast-серверами имен и держите минимум два сервера имен в разных сетях.
- Проверьте, что DNSSEC валидируется. Сравните обычный запрос с запросом без проверки:
dig example.com @1.1.1.1противdig +cd example.com @1.1.1.1. Большая разница или SERVFAIL только в первом случае означают, что цепочка сломана.
Проверка снаружи
Ваши собственные замеры описывают одну сеть в один момент времени, а это наименее полезная выборка из возможных. Резолвер в 8 мс от вас может оказаться в 400 мс от клиента в другом регионе, и жалуется как раз этот клиент.
Начните с замера самих авторитативных серверов: так вы убираете все кэши между собой и источником:
dig NS example.com +short
dig @ns1.example-dns.net example.com | grep "Query time"
dig example.com +trace
Вывод +trace проходит делегирование по шагу за раз, поэтому подвисший шаг видно, а не размазано по среднему. Затем запустите проверку DNS-запроса, которая разрешает имя из точек проверки в разных странах и показывает результат каждой отдельно. Это то измерение, которое нельзя снять с ноутбука: оно показывает, медленны ли ваши серверы имен везде, что указывает на провайдера, или только с одного континента, что указывает на географию его сети. Если часть локаций возвращает не более медленный, а другой ответ, вопрос уже в распространении, и о нем написано в как проверить распространение DNS.
Задержка, которая не ломается, а сползает
Задержка DNS редко ломается заметно. Она сползает: сервер имен теряет площадку, TTL занижают на время миграции и забывают вернуть, и через шесть недель сайт кажется вялым по причинам, которые никто не может назвать. Одиночный замер тренда не покажет, поэтому время запроса стоит писать по расписанию из тех регионов, где живут ваши посетители. HostTracker следит за сайтами с 2004 года и сейчас наблюдает более 500 000 сайтов из точек проверки в 158 городах, храня историю, в которой медленное сползание становится видно. Остальные руководства собраны в кластере починки, а случай, когда не возвращается вообще ничего, это DNS-сервер не отвечает.