DNS и путь запроса
Что это такое
DNS — это распределённая система имён, отображающая имя, например имя внутреннего сервиса, в IP-адрес. Устроена она как иерархия серверов, каждый из которых отвечает за одну часть имени, а поверх идёт обильное кэширование, которое удерживает трафик в разумных рамках. Как только имя разрешено, запрос проходит по цепочке шагов — поиск имени, установка соединения, согласование протокола, запрос, ответ, — и каждый шаг добавляет круговой обход, прежде чем двинутся полезные байты.
Почему это важно
Разрешение имён — самый часто забываемый источник задержки и самый часто забываемый источник отказов. Кэш DNS с долгим сроком жизни продолжает слать трафик на машину, которую вы давно вывели из эксплуатации, а медленный резолвер задерживает каждое новое соединение вашего сервиса. Результат кэшируется, поэтому проблема часто всплывает только при холодном старте или после развёртывания, — и выглядит оттого случайной. Подсчёт шагов превращает «сеть медленная» в число, привязанное к шагу.
Ключевые идеи
Имя читается справа
Имя устроено как путь по иерархии, который читают справа налево. Самая правая метка — домен верхнего уровня, дальше идёт домен организации, а затем поддомены. У каждого уровня есть авторитативные серверы, которые указывают на уровень ниже, и ни один сервер не знает все имена — именно поэтому система и может расти без центральной копии.
api.internal.example.com
com -> серверы реестра .com
example.com -> авторитативные серверы example
internal.example.com -> внутренняя зона
api.internal.example.com -> запись, которую вы запросили
Разрешение один раз проходит иерархию, затем кэширует
Резолвер спрашивает сверху вниз и кэширует каждый ответ на срок жизни записи. Первый поиск может занять несколько круговых обходов, а каждый поиск внутри этого срока не стоит ничего. Отсюда и то, что изменение записи видно не везде сразу: разные резолверы держат старый ответ, пока их копия не истечёт. Короткие сроки распространяют изменения быстро и повышают нагрузку запросов, долгие — наоборот.
первый поиск: клиент -> резолвер -> корень -> com -> example -> ответ
поиск из кэша: клиент -> резолвер -> ответ (без сети)
Путь запроса — это последовательность круговых обходов
Между набором имени и чтением ответа последовательно происходит несколько разных шагов. Имя должно разрешиться, транспортное соединение — установиться, любое рукопожатие безопасности — завершиться, а прикладной протокол затем отправляет запрос и ждёт первый байт. Каждый шаг обходится как минимум в один круговой обход через расстояние между клиентом и сервером.
разрешить имя (0-n круговых обходов, 0 из кэша)
открыть соединение (1 круговой обход)
рукопожатие безопасности (1-2 круговых обхода)
отправить запрос (1 круговой обход до первого байта)
Расстояние задаёт нижнюю границу
Быстрее света по этому пути круговой обход быть не может, поэтому у сервера на другом конце мира нижняя граница — несколько сотен миллисекунд, и никакое изменение приложения её не уберёт. Доступных исправлений два: сократить число круговых обходов (переиспользовать соединения, разрешать имя заранее, обходить лишние рукопожатия) или перенести сервер ближе к пользователю. Обычная форма второго — кэширование на периферии.
Кэш есть на каждом слое
Браузер кэширует ответы, операционная система кэширует их, резолвер кэширует их тоже, а сервисная сетка может закэшировать ещё раз. Каждый кэш держит копию ровно столько, сколько объявлено в сроке жизни записи. При отладке практический вопрос звучит не «что говорит DNS», а «что считает слой, с которым говорит мой код, и когда он это узнал».
Практика
Проследите имя вручную
Спросите у резолвера имя и прочтите срок жизни ответа. Спросите у публичного резолвера то же самое имя и сравните, затем повторите сразу же и отметьте, какие поиски ушли в сеть.
Готово, когда: вы можете назвать записанный срок жизни, сказать, какие поиски обслужены из кэша, и объяснить, что изменилось бы, будь срок равен одной секунде.
Замерьте каждый шаг запроса
Возьмите один URL, который вызывает ваше приложение. Запишите время на разрешение имени, на соединение, до первого байта ответа и общее.
Готово, когда: четыре числа примерно складываются в общее, и вы можете назвать наибольшее и сказать, фиксированная это стоимость или на каждый запрос.
Частые ошибки
- Убеждение, что изменение DNS вступает в силу немедленно — каждый резолвер, у которого есть ответ, держит его до истечения срока; исправить: понижайте срок задолго до запланированной миграции.
- Разрешение имени на каждый запрос — каждое новое соединение платит за поиск, который убрал бы кэшированный результат; исправить: держите соединение открытым или разрешите имя один раз и переиспользуйте адрес.
- Путаница кэшированного ответа с авторитативным — отладка против кэша даёт устаревший результат, который выглядит текущим; исправить: запрашивайте авторитативный сервер, когда ответ важен.
- Игнорирование рукопожатия при подсчёте стоимости запроса — запрос, измеренный десятками миллисекунд, состоит в основном из установки; исправить: разделите фазы и атакуйте круговые обходы, а не нагрузку.
- «Сеть медленная» как одна проблема — разрешение, соединение, рукопожатие и передача отказывают и замедляются по-разному; исправить: измеряйте фазы по отдельности, прежде чем что-то менять.
Что читать дальше
- Пакеты, TCP/IP и порты (01-cs-fundamentals/03-computer-networks/01-packets-tcp-ip-and-ports) — транспорт под этими круговыми обходами, поэтому читайте первым.
- Основы сетей (HTTP / DNS / TLS) (06-cloud-devops/10-networking-fundamentals-http-dns-tls) — прикладные протоколы и рукопожатие безопасности, которые эта запись только называет.
- Веб-производительность (Core Web Vitals) (02-frontend/26-web-performance-core-web-vitals) — те же круговые обходы, измеренные из браузера, где пользователь их чувствует.