Для OpenFreeMap я использую серверы за Round Robin DNS. В этой статье я пытаюсь понять, как браузеры и CDN выбирают, какой из них использовать.
Что такое циклический DNS?
Обычно, когда вы обслуживаете веб-сайт с помощью
Это означает, что rr-direct.hyperknot.com будет обслуживать данные с 5.223.46.55.
В Round Robin DNS вы указываете несколько серверов для одного и того же поддомена, например, так.
Это позволяет распределить нагрузку между несколькими серверами, а также автоматически определять, какие серверы отключены, и выбирать те, которые находятся в сети.
Это удивительно простое и элегантное решение, которое позволяет избежать использования балансировщиков нагрузки. Оно также бесплатно, и вы можете сделать это на любом провайдере DNS, в то время как решения балансировки нагрузки могут быть очень дорогими (даже на Cloudflare, который в остальном имеет очень разумную цену).
Как это работает в теории?
Я был одержим тем, как это работает. Я имею в виду, на поверхности все элегантно, но как браузер решает, к какому серверу подключаться?
Теоретически существует RFC 8305 под названием Happy Eyeballs (также ссылающийся на RFC 6724 ) о том, как клиент должен сортировать адреса перед подключением.
Конечно, это выше моего уровня знаний, но этот раздел кажется наиболее близким к ответу на мой вопрос:
Если клиент сохраняет состояние и имеет историю ожидаемого времени приема-передачи (RTT) для маршрутов доступа к каждому адресу, ему СЛЕДУЕТ добавить правило выбора адреса назначения между правилами 8 и 9, которое отдает предпочтение адресам с меньшим временем RTT.
Итак, в моем понимании, это в основном:
-
Проверка того, находятся ли серверы в сети/офлайн
-
Сортировать онлайн-по времени пинга
На практике
Давайте посмотрим, как это работает на практике.
Я создал 3
Они запускают 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-страницу , которая заполняет сетку 10x10 случайными изображениями.
Цвета сервера следующие:
-
США - зеленый
-
ЕС - синий
-
СГ - красный
Важно: Я тестирую из Европы; сервер ЕС гораздо ближе ко мне, чем сервер США или, тем более, сервер Сингапура. Я должен видеть синие квадратики!
Хром
Chrome выбирает несколько случайным образом между всеми местоположениями, но однажды выбранный, он придерживается его. Он переоценивает выбор через несколько часов. В этом случае он застрял с SG на несколько часов, хотя это, безусловно, самый медленный сервер для меня.
Также, интересное поведение Chrome было, когда не использовался HTTP/2: он иногда мог выбирать случайным образом между двумя серверами, создавая шаблон, подобный этому. Здесь он выбирает между EU и US случайным образом.
Firefox
Ведет себя аналогично Chrome, выбирает случайное местоположение при запуске и затем придерживается его. Если я перезапускаю браузер, он выбирает другое случайное местоположение.
Сафари
К моему величайшему удивлению, Safari всегда правильно выбирает ближайший сервер. Даже если он на некоторое время отключается, после нескольких обновлений он всегда снова находит сервер ЕС!
Curl тоже работает правильно. В первый раз может не сработать, но если запустить команду дважды, то она всегда исправит на ближайший сервер.
Если у вас несколько
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
Теперь, если я подключаюсь к своей мобильной точке доступа, она всегда подключается к серверу ЕС.
Если я зайду в несколько
curl https://rr-cf.hyperknot.com/server
test-sg
Поведение клиента при частично отключенных серверах
Так что же происходит, когда один из серверов офлайн? Допустим, я останавливаю сервер в США:
service nginx stop
Хром
Firefox
Сафари
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
-
Как минимум должны быть обнаружены серверы, отключенные от сети.
-
Более того, было бы очень здорово, если бы выбирался сервер с наименьшей задержкой, как в Safari!
Я имею в виду, что в настоящее время, если у вас есть один сервер в США и один в Новой Зеландии, ровно 50% ваших пользователей в США будут обслуживаться из Новой Зеландии, что не имеет смысла. Кроме того, для пользователей Safari это на самом деле медленнее по сравнению с отсутствием использования Cloudflare!
Автор: Rockis