Переключили DNS на резервный сервер, а трафик шёл на старый ещё сутки: TTL и чужие кеши
Основной сервер упал, вы за пару минут переключили A-запись домена на резервный — и с чистой совестью выдохнули. А через час выясняется, что часть пользователей всё ещё бьётся в мёртвый старый IP, заказы не проходят, а вы третий раз перепроверяете, что запись точно поменялась. DNS-запись действительно поменялась мгновенно. Трафик — нет. Разберёмся, почему так происходит и что с этим можно сделать заранее, а что — только принять как ограничение самого DNS.
Содержание
- Что на самом деле происходит при смене A-записи
- TTL, который никто не подумал снизить заранее
- Резолверы и провайдеры не всегда честно соблюдают TTL
- Кеш на уровне ОС и браузера клиента
- Как готовиться к плановому переключению заранее
- Почему аварийный DNS failover не бывает мгновенным
- Альтернативы DNS-failover: anycast и балансировщик перед бэкендами
Что на самом деле происходит при смене A-записи
Когда вы меняете A-запись в панели управления доменом, обновление применяется на авторитативных серверах домена практически сразу — это тот единственный момент во всей цепочке, который действительно происходит мгновенно. Дальше начинается путь ответа до конечного пользователя, а на этом пути авторитативный сервер почти никогда не участвует напрямую.
Браузер и приложение на устройстве пользователя не спрашивают ваш авторитативный DNS каждый раз — они идут к рекурсивному резолверу: DNS провайдера, корпоративному резолверу офиса или публичному вроде 1.1.1.1 и 8.8.8.8. Резолвер либо уже знает ответ (он лежит у него в кеше с прошлого запроса), либо идёт спрашивать авторитативный сервер сам и после этого кеширует результат у себя — на срок, который вы задали через TTL записи. Подробно эта цепочка разобрана в статье про то, кто на самом деле отвечает на ваш DNS-запрос: в норме отвечает не ваш сервер, а чужой кеш, и это касается не только обычных запросов, но и failover.
Отсюда и весь эффект: вы изменили ответ у источника, но большинство пользователей продолжают получать копию старого ответа, которая физически лежит не у вас, а на тысячах чужих резолверов по всему миру. Пока не истечёт TTL конкретной закешированной записи у конкретного резолвера, он не пойдёт спрашивать заново — и будет упорно отдавать старый IP, даже если вы давно всё поменяли.
TTL, который никто не подумал снизить заранее
TTL (time to live) A-записи — это не рекомендация, а часть протокола DNS: число секунд, в течение которых резолвер имеет право отдавать закешированный ответ, не перепроверяя его у авторитативного сервера. Если на записи стоит TTL 86400 (сутки) — а это дефолт у многих регистраторов и панелей, который никто не трогает, потому что запись годами не менялась — то каждый резолвер, успевший спросить адрес до вашего аварийного переключения, имеет полное право отдавать старый IP ещё почти сутки.
dig @8.8.8.8 example.com +noall +answer
example.com. 71234 IN A 203.0.113.10 # старый IP, TTL всё ещё тикает почти сутки
Число в столбце TTL — это не настройка зоны, а обратный отсчёт до истечения конкретной закешированной копии у конкретного резолвера. У авторитативных серверов при этом уже стоит новый ответ:
dig @ns1.your-dns-provider.com example.com A +short
203.0.113.55 # новый IP резервного сервера, отдаётся с первой секунды
Разрыв между этими двумя dig-запросами — и есть источник проблемы. Механика того, почему изменение доходит волнами, а не разом, подробно разобрана в статье про TTL DNS-записи и неравномерное распространение изменений — при аварийном failover она работает точно так же, как при плановой миграции, просто у вас не было времени подготовиться заранее.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверРезолверы и провайдеры не всегда честно соблюдают TTL
Даже если бы все резолверы мира строго следовали заявленному TTL, картина была бы предсказуемой: старый ответ живёт ровно TTL секунд с момента последнего опроса, и точка. На практике часть резолверов — некоторые крупные публичные DNS, часть корпоративных и провайдерских резольверов с собственными политиками кеширования — не гарантирует точное соблюдение TTL. Кто-то кеширует дольше заявленного из соображений производительности и снижения нагрузки на upstream, кто-то, наоборот, может обновить раньше срока при активном prefetch.
Точную долю таких резолверов назвать нельзя — это не задокументированное поведение, а наблюдаемое на практике расхождение, которое разнится от провайдера к провайдеру и меняется со временем. Единственный рабочий способ увидеть реальную картину — не гадать, а проверить эмпирически: опросить несколько независимых резолверов напрямую и посмотреть на разброс.
for r in 8.8.8.8 1.1.1.1 9.9.9.9 77.88.8.8; do
echo "=== $r ==="
dig @$r example.com A +noall +answer
done
Плюс к этому — публичные сервисы проверки распространения DNS (DNS propagation checker) опрашивают резолверы в разных странах и показывают, у кого уже новый IP, а у кого ещё старый. Это не даёт точного ETA до нуля старого трафика, но даёт честную картину прогресса вместо предположений с одной рабочей машины.
Кеш на уровне ОС и браузера клиента
Даже после того как резолвер провайдера пользователя отдал свежий ответ, между резолвером и приложением есть ещё один слой кеша — локальный, на устройстве самого пользователя. Операционная система держит собственный DNS-кеш поверх системного резолвера, и он живёт по своим правилам, иногда не строго привязанным к TTL записи:
# Windows: посмотреть локальный DNS-кеш
ipconfig /displaydns
# Windows: сбросить локальный DNS-кеш
ipconfig /flushdns
# macOS: сбросить кеш системного резолвера
sudo killall -HUP mDNSResponder
# Linux с systemd-resolved: посмотреть и сбросить статистику кеша
resolvectl statistics
sudo resolvectl flush-caches
Браузеры добавляют ещё один уровень поверх ОС — свой собственный DNS-кеш (в Chrome его можно посмотреть на chrome://net-internals/#dns), который тоже не обязан синхронно реагировать на смену записи у резолвера. А для уже открытых вкладок и активных соединений добавляется третий фактор, который вообще не про DNS: keep-alive HTTP-соединение или установленный TLS-туннель продолжает жить с уже установленным IP, пока само соединение не разорвётся — приложению попросту незачем повторно резолвить домен, пока текущее соединение живо.
Итог: даже идеально быстрый резолвер провайдера — не гарантия того, что конкретный пользователь увидит новый сервер сразу. Между «резолвер знает новый IP» и «браузер пользователя реально пошлёт запрос на новый IP» может лежать ещё несколько независимых кешей, на каждый из которых вы не влияете напрямую.
Как готовиться к плановому переключению заранее
Если переключение на резервный сервер плановое (например, заранее запланированное обслуживание основной площадки), у вас есть ресурс, которого не будет при настоящей аварии — время. Его стоит потратить на прогрев кешей коротким TTL до того, как понадобится реальное переключение.
| Когда | Что делать | Зачем |
|---|---|---|
| За срок, равный текущему TTL (например, за сутки, если TTL был 86400) | Снизить TTL A-записи до 60-300 секунд | Дать старому TTL истечь у всех резолверов, которые успели закешировать прежнее значение |
| После истечения старого TTL, но до самого переключения | Проверить через несколько независимых резолверов, что все уже отдают короткий TTL | Убедиться, что кеши действительно прогрелись, а не полагаться на расчётное время |
| В момент планового переключения | Менять A-запись, пока TTL уже короткий | Резолверы, соблюдающие TTL, обновятся в пределах нескольких минут после истечения короткого интервала |
| После подтверждения полного переключения (обычно от нескольких часов до суток наблюдения) | Вернуть TTL к обычному значению | Снизить нагрузку на авторитативные NS в штатном режиме, когда срочность снятия старого сервера уже позади |
Логика простая и при этом контринтуитивная на первый взгляд: снижение TTL само по себе распространяется по тем же законам, что и смена IP — вы не можете «включить» короткий TTL мгновенно для всех резолверов мира, если у них уже закеширован старый (длинный) TTL. Поэтому TTL снижают заранее, ждут ровно старый интервал, и только потом меняют саму запись — тогда переключение реально укладывается в минуты, а не в сутки. Та же механика работает и при полноценном переезде на новый сервер, просто там, в отличие от настоящей аварии, есть время подготовиться без спешки.
Почему аварийный DNS failover не бывает мгновенным
Проблема плановых переключений решается заранее сниженным TTL. Проблема аварий в том, что готовиться заранее просто не к чему — основной сервер падает без предупреждения, и на момент падения TTL записи такой, какой он есть: может быть 300 секунд, а может годами стоявшие 86400.
Даже если TTL был коротким изначально, DNS-failover всё равно не гарантирует переключение за секунды, и вот почему:
- TTL — это верхняя граница для добросовестных резолверов, а не гарантия для всех. Часть резолверов, как разобрано выше, кеширует дольше заявленного — предсказать заранее, какая именно доля и насколько дольше, нельзя.
- Снижение TTL в момент самой аварии не откатывает уже выданные ответы. Резолверы, которые успели закешировать старый ответ с прежним (пусть даже коротким) TTL до аварии, будут держать его до истечения именно этого интервала — новый короткий TTL подействует только на резолверы, которые обратятся за записью уже после вашего изменения.
- Локальные кеши ОС и браузера добавляют задержку сверху, независимо от того, насколько быстро отреагировал резолвер провайдера.
- Отрицательное кеширование и keep-alive соединения продлевают жизнь старому маршруту у части клиентов ещё дольше, чем формально истекший TTL записи.
Это не значит, что DNS-failover бесполезен — он остаётся рабочим и достаточным механизмом для многих сценариев, особенно если TTL был заранее коротким и заявленным честно у большинства резолверов пользователей. Но обещать бизнесу «переключение за 30 секунд» на основе одной только смены A-записи — значит обещать то, что сам протокол DNS не гарантирует.
Практически в момент аварии стоит делать следующее параллельно, а не вместо смены записи:
- Менять A-запись сразу, не дожидаясь ничего — это необходимое, но не достаточное действие.
- Одновременно снижать TTL до минимально разумного значения (60-120 секунд) — это не поможет уже закешированным ответам, но ускорит обновление для всех новых запросов.
- Если старый сервер физически ещё жив (упало приложение, но сеть и ОС отвечают) — поднять на нём временный reverse-proxy на резервный сервер, чтобы часть трафика, которая всё ещё приходит на старый IP, не проваливалась в пустоту, а долетала до рабочей инфраструктуры.
- Мониторить split по логам обоих серверов, а не полагаться на ощущение «переключение прошло» — трафик на старом IP может держаться намного дольше, чем кажется интуитивно.
Альтернативы DNS-failover: anycast и балансировщик перед бэкендами
Если для вашего сервиса секунды простоя действительно критичны и переключение через смену A-записи в принципе не подходит по срокам, стоит закладывать архитектуру, где DNS вообще не находится в цепочке failover.
Anycast — один и тот же IP-адрес анонсируется из нескольких точек присутствия одновременно через BGP, а маршрутизация до ближайшей живой точки происходит на уровне сети, а не DNS. При отказе одной точки анонс IP из неё снимается (route withdrawal), и трафик перетекает на оставшиеся анонсы за время, сравнимое со сходимостью BGP — это не про кеш резолвера и не про TTL вообще, поэтому механизм принципиально быстрее и предсказуемее DNS-failover. Подробнее о том, как это работает, — в статье про anycast, один IP на разные страны. Обратная сторона — anycast требует своего AS-номера и BGP-анонсов (или специализированного провайдера, который это предоставляет как услугу), что заметно сложнее и дороже, чем просто держать резервный сервер про запас.
Балансировщик или reverse-proxy перед несколькими бэкендами — более доступный вариант для большинства проектов. DNS-запись домена в принципе не меняется вообще: она один раз и надолго указывает на балансировщик (HAProxy, nginx upstream с health check и так далее), а сам балансировщик по результатам проверок здоровья перестаёт слать трафик на упавший бэкенд и переключает его на резервный — за время, которое задаётся настройками health check балансировщика (обычно секунды), а не TTL записи и не поведением чужих резолверов. Как выбрать и настроить такую схему, разобрано в материале про HAProxy или nginx для балансировки.
У этой схемы тоже есть цена: сам балансировщик становится узлом, отказ которого кладёт весь сервис, если не сделать резервным и его тоже (например, через плавающий IP между парой узлов). Но по крайней мере DNS и его кеши перестают быть узким местом failover — а именно они, как показано выше, самый неконтролируемый и медленный участок всей цепочки.
Выбор между «просто резервный сервер через смену DNS», anycast и балансировщиком — вопрос допустимого времени простоя и бюджета, а не универсально правильного ответа. Для сервиса, где простой в час пик стоит дорого, DNS-failover в одиночку — рискованная ставка именно из-за непредсказуемости TTL и чужих кешей, разобранной выше.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько по факту продержится трафик на старом сервере, если TTL был 86400 и его не снижали заранее?
Точного числа не назвать — это зависит от того, когда конкретный резолвер в последний раз опрашивал запись, и от того, насколько честно он соблюдает TTL. Реалистичный ориентир — исходный TTL плюс запас на резолверы, которые кешируют дольше заявленного; на практике это может растянуться на сутки и больше даже при формальном TTL в 24 часа.
Поможет ли снизить TTL прямо в момент аварии, когда трафик уже идёт не туда?
Частично. Это ускорит обновление для резолверов, которые ещё не закешировали ответ или обратятся за ним заново после истечения своего текущего TTL. Но резолверы, у которых уже лежит старый ответ с прежним TTL, не пойдут перепроверять его раньше срока — новый короткий TTL на них не подействует, пока не истечёт их уже идущий отсчёт.
Можно ли держать TTL всегда коротким на всякий случай, чтобы не думать об этом заранее?
Можно, и для записей, критичных к оперативному failover, это разумная практика. Плата — небольшое увеличение нагрузки на авторитативные NS-серверы и чуть более частые обращения резолверов за свежим ответом, что для большинства проектов не критично по сравнению с выигрышем в скорости реагирования.
Правда ли, что короткий TTL в 60 секунд гарантирует переключение всех пользователей за минуту?
Нет. Он гарантирует, что добросовестные резолверы, у которых нет ещё не истёкшей закешированной копии, обновятся быстро. Но часть резолверов, как обсуждалось выше, не соблюдает TTL строго, плюс сверху есть независимый кеш ОС и браузера у конечного пользователя — так что минута — это оптимистичный, а не гарантированный сценарий.
В чём принципиальная разница между DNS-failover и anycast с точки зрения скорости?
DNS-failover зависит от того, когда чужой резолвер в очередной раз обратится к вашей записи — это события, которые вы не контролируете и не видите в моменте. Anycast работает на уровне маршрутизации сети (BGP) и не завязан на DNS-кеши вообще: как только точка присутствия перестаёт анонсировать IP, трафик к ней перестаёт идти по сети, независимо от того, что там думает чей-то DNS-резолвер.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →