[Перевод] Понимание кругового DNS

Для OpenFreeMap я использую серверы за Round Robin DNS. В этой статье я пытаюсь понять, как браузеры и CDN выбирают, какой из них использовать.

Что такое циклический DNS?

Обычно, когда вы обслуживаете веб-сайт с помощью VPS, например Digital Ocean или Hetzner, вы добавляете одну запись A в панель управления вашего DNS-провайдера.

ab83070796148c21d9e199e2d9718f41.png

Это означает, что rr-direct.hyperknot.com будет обслуживать данные с 5.223.46.55.

В Round Robin DNS вы указываете несколько серверов для одного и того же поддомена, например, так.

aa009134034afdb463d0c3ff90d52c76.png

Это позволяет распределить нагрузку между несколькими серверами, а также автоматически определять, какие серверы отключены, и выбирать те, которые находятся в сети.

Это удивительно простое и элегантное решение, которое позволяет избежать использования балансировщиков нагрузки. Оно также бесплатно, и вы можете сделать это на любом провайдере DNS, в то время как решения балансировки нагрузки могут быть очень дорогими (даже на Cloudflare, который в остальном имеет очень разумную цену).

Как это работает в теории?

Я был одержим тем, как это работает. Я имею в виду, на поверхности все элегантно, но как браузер решает, к какому серверу подключаться?

Теоретически существует RFC 8305 под названием Happy Eyeballs (также ссылающийся на RFC 6724 ) о том, как клиент должен сортировать адреса перед подключением.

Конечно, это выше моего уровня знаний, но этот раздел  кажется наиболее близким к ответу на мой вопрос:

Если клиент сохраняет состояние и имеет историю ожидаемого времени приема-передачи (RTT) для маршрутов доступа к каждому адресу, ему СЛЕДУЕТ добавить правило выбора адреса назначения между правилами 8 и 9, которое отдает предпочтение адресам с меньшим временем RTT.

Итак, в моем понимании, это в основном:

  • Проверка того, находятся ли серверы в сети/офлайн

  • Сортировать онлайн-по времени пинга

На практике

Давайте посмотрим, как это работает на практике.

Я создал 3 VPS по всему миру: один в США, один в ЕС и один в Сингапуре. Я сделал 3 проксированных и 3 непроксированных A-записи в Cloudflare.

6be192861f42f2cf3793865ab5842a35.png

Они запускают nginx с такой конфигурацией:

server { server_name rr-direct.hyperknot.com rr-cf.hyperknot.com; # this is basically a wildcard block # so /a/b/c will return the same color.png file location / { root /data; rewrite ^ /color.png break; } location /server { alias /etc/hostname; default_type text/plain; } }

Поэтому они предоставляют color.png, который представляет собой PNG-файл красного, зеленого и синего цвета размером 1 пиксель, а также свое имя хоста test-eu/us/sg.

Поведение клиента, когда серверы находятся в сети

Я создал тестовую HTML-страницу , которая заполняет сетку 10×10 случайными изображениями.

Цвета сервера следующие:

  • США — зеленый

  • ЕС — синий

  • СГ — красный

Важно: Я тестирую из Европы; сервер ЕС гораздо ближе ко мне, чем сервер США или, тем более, сервер Сингапура. Я должен видеть синие квадратики!

Хром

Chrome выбирает несколько случайным образом между всеми местоположениями, но однажды выбранный, он придерживается его. Он переоценивает выбор через несколько часов. В этом случае он застрял с SG на несколько часов, хотя это, безусловно, самый медленный сервер для меня.

746ca40f50a2239e54b21f578f0f8e54.png

Также, интересное поведение Chrome было, когда не использовался HTTP/2: он иногда мог выбирать случайным образом между двумя серверами, создавая шаблон, подобный этому. Здесь он выбирает между EU и US случайным образом.

a99817e4c1d2778d62ff34d02ec5d321.png

Firefox

Ведет себя аналогично Chrome, выбирает случайное местоположение при запуске и затем придерживается его. Если я перезапускаю браузер, он выбирает другое случайное местоположение.

3a55d8518b2b865ef48b8a63a3976d41.png

Сафари

К моему величайшему удивлению, Safari всегда правильно выбирает ближайший сервер. Даже если он на некоторое время отключается, после нескольких обновлений он всегда снова находит сервер ЕС!

25c31092e119d860fb26e729b34db2d1.png

Curl тоже работает правильно. В первый раз может не сработать, но если запустить команду дважды, то она всегда исправит на ближайший сервер.

Если у вас несколько VPS по всему миру, попробуйте выполнить эту команду через ssh и посмотрите, какой из них будет выбран:

curl https://rr-direct.hyperknot.com/server test-us curl https://rr-direct.hyperknot.com/server test-eu

Клаудфлер

Cloudflare выбирает случайное местоположение на основе вашего клиентского IP-адреса и затем придерживается его. (Оно ведет себя как client_ip_hash modulo server_num или что-то подобное.)

Как вы видели на изображениях, правый прямоугольник всегда зеленый. На моем домашнем IP, что бы я ни делал, Cloudflare переходит на сервер в США. Curl показывает то же самое.

curl https://rr-cf.hyperknot.com/server test-us

Теперь, если я подключаюсь к своей мобильной точке доступа, она всегда подключается к серверу ЕС.

Если я зайду в несколько VPS и запущу ту же команду curl, я смогу увидеть это поведение по всему миру. Каждый VPS подключается к совершенно случайному месту по всему миру, но всегда к одному и тому же.

curl https://rr-cf.hyperknot.com/server test-sg

Поведение клиента при частично отключенных серверах

Так что же происходит, когда один из серверов офлайн? Допустим, я останавливаю сервер в США:

service nginx stop

Хром

130ac297ee7e7e83920a4dd3d9c53e3f.png

Firefox

3c60934aef2fdad572f6c8b8c70089f2.png

Сафари

51bc191e87242c9e99d2e5c515d3b9ff.png

curl https://rr-direct.hyperknot.com/server test-eu

Как видите, все клиенты правильно его определяют и выбирают альтернативный сервер.

На самом деле, они делают этот откат настолько хорошо, что если я выключу сервер во время загрузки, они исправятся в течение < 1 секунды! Вот анимация версии 50x50 той же сетки в Safari:

Клаудфлер

А что насчет Cloudflare? Как вы можете видеть на скриншотах выше, Cloudflare не обнаруживает офлайн-сервер. Он продолжает обращаться к серверу, который он определил для вашего IP, независимо от того, онлайн он или офлайн.

Если сервер офлайн, вы обслуживаетесь офлайн. В curl он возвращает:

curl https://rr-cf.hyperknot.com/server error code: 521

Я пытался понять, что это за поведение, и я очень подозреваю, что это ошибка в их сети. Одна ссылка, которую я нашел в их документации  , это эта часть:

На основании этой документации, а также здравого смысла, я считаю, что Cloudflare должен вести себя так же, как браузеры и curl.

Список пожеланий Cloudflare

  1. Как минимум должны быть обнаружены серверы, отключенные от сети.

  2. Более того, было бы очень здорово, если бы выбирался сервер с наименьшей задержкой, как в Safari!

Я имею в виду, что в настоящее время, если у вас есть один сервер в США и один в Новой Зеландии, ровно 50% ваших пользователей в США будут обслуживаться из Новой Зеландии, что не имеет смысла. Кроме того, для пользователей Safari это на самом деле медленнее по сравнению с отсутствием использования Cloudflare!

Habrahabr.ru прочитано 11924 раза