Я помогаю реализовать CloudFront CDN для источника видео NGINX HLS. Если вы не знакомы, HLS в браузере просто использует XHR или выборку для постоянного запроса файлов .m3u8 и .ts через HTTP и отображения их в элементе видео. Я воспроизвел проблему, которую описываю, с помощью простых вызовов AJAX с интервалом, поэтому проблема не связана с HLS. Я хотел бы иметь возможность переключать трафик между CDN и прямым источником с минимальным воздействием на пользователей. Я построил это и могу переключаться между CloudFront и прямым источником, изменив DNS в Route 53. Запись DNS имеет TTL 1 минуту.
Однако, когда я это делаю, иногда IP-адрес, используемый браузером, не меняется — даже спустя много времени после DNS TTL. Кэш DNS на уровне ОС и браузера показывает ожидаемый IP-адрес, но браузер (как показано в Инструменты разработчика -> Сеть) показывает, что он все еще использует «старый» IP-адрес. Это может продолжаться в течение нескольких часов после DNS TTL. Даже обновление страницы не заставит ее получить новый IP для домена. До сих пор я нашел только chrome://net-internals/#sockets -> Flush Socket Pools или полное закрытие всех экземпляров браузера, заставляющее браузер получить новый IP-адрес для домена.
Итак, я совершенно уверен, что проблема в том, что Chrome (также проверенный FireFox, вероятно, все браузеры) поддерживает соединение и не ищет DNS снова, пока соединение не будет закрыто, независимо от DNS TTL, особенно с чем-то вроде HLS видео или непрерывный опрос ajax, когда соединение используется каждые несколько секунд. Я могу несколько контролировать это, устанавливая заголовки Connection:close или Keep-Alive:timeout=5s в источнике. Однако я не могу управлять ими в CloudFront даже с помощью пользовательской функции. Более того, если я включаю HTTP2 в источнике и/или CloudFront, эти заголовки не разрешаются и не используются, но я все равно вижу подобное поведение.
Я также могу вернуть ошибочный запрос HTTP 421 из источника и заставить клиентов, попадающих в источник, обновиться. Однако это не работает из CloudFront — использование функции CloudFront для изменения кода ответа вызывает ошибку, а 421, возвращаемый из источника в Cloudfront, вызывает ошибку и не запускает обновление клиентов.
Учитывая все это, как я могу гарантировать, что изменения DNS вступят в силу в браузере в пределах TTL записи DNS? Есть ли какие-либо настройки заголовка или CloudFront, которые я могу использовать? Я могу управлять некоторыми клиентами, так что есть ли какой-нибудь javascript, заголовок запроса или трюк XHR, чтобы заставить браузер получить и использовать новый TTL?