Cloud и инфраструктура

·5 мин чтения·Обновлено

Service Discovery: почему сервисы не должны знать адреса друг друга заранее

Новый экземпляр сервиса уже работает, а часть клиентов продолжает обращаться к старому. Разбираемся, как меняются адреса и почему исправного реестра для восстановления недостаточно.

Сервис проверки наличия оборудования перенесли на новый сервер. Проверка доступности успешна, адрес в реестре обновлён. Но менеджеры всё ещё получают ошибки: одно приложение запомнило прежний адрес, другое держит старое соединение. Оба продолжают обращаться туда, где сервиса уже нет.

Service Discovery помогает находить текущие экземпляры по устойчивому имени. Важно не только зарегистрировать новый адрес, но и довести изменение до тех, кто им пользуется. Именно на этом пути автоматизация часто заканчивается раньше, чем исчезает ручная работа.

Имя остаётся, исполнители меняются

Клиентскому приложению нужен сервис наличия, а не конкретная машина. Оно обращается к логическому имени. Дальше возможны разные варианты: клиент получает список адресов и выбирает экземпляр либо обращается к постоянной точке входа, за которой выбор делает инфраструктура.

Например, обычный Service в Kubernetes предоставляет устойчивый адрес для группы меняющихся экземпляров. DNS может возвращать этот адрес, а не IP каждого приложения. Для headless Service поведение другое: клиент получает адреса выбранных Pod. Различие описано в документации DNS Kubernetes. Одного слова «используем DNS» недостаточно, чтобы понять маршрут.

Обнаружение и балансировка связаны, но решают разные задачи. Первое определяет, куда вообще можно обратиться; второе — кому направить конкретную работу. Поддержку списка могут выполнять платформа, реестр или сами приложения. Чем больше выбора передано клиенту, тем больше правил обновления и отказа ему придётся реализовать.

Сначала убедиться, что запись относится к нужному сервису

У записи есть происхождение: кто зарегистрировал адрес, к какому окружению он относится и как подтверждается актуальность. Ошибочный фильтр способен включить тестовый экземпляр в рабочий список. Забытое имя после переезда — оставить клиентам адрес чужой машины.

Поэтому права на регистрацию и изменение записей важны не меньше доступности реестра. Имена окружений должны различаться предсказуемо, а сведения об экземплярах обновляться по понятному жизненному циклу. Возможности регистрации и DNS-запросов можно посмотреть на примере Consul.

Найденный адрес не подтверждает полномочия. Клиенту по-прежнему нужно установить личность другой стороны и иметь право на операцию. Сотрудник не должен получать доступ к закрытым сведениям только потому, что его приложение нашло внутреннее имя.

Присутствие в списке и готовность обслуживать — разные состояния

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

Не всякую внешнюю проблему стоит превращать в исчезновение всех экземпляров из списка. Если общий поставщик временно недоступен, перезапуск приложений его не восстановит. Нужно решить, какую часть работы они всё ещё способны выполнять. Разницу между готовностью и перезапуском подробнее разбирают Health Checks.

Платформа также может иметь специальные исключения. В Kubernetes сведения о доступных адресах содержат состояния готовности и завершения, а некоторые настройки разрешают публиковать ещё не готовые экземпляры. Поэтому нужно проверять реальную конфигурацию, а не предполагать, что любой опубликованный адрес безопасен. Подробности есть в описании EndpointSlice.

Удалить адрес из реестра мало

Между обновлением записи и последним обращением к старому экземпляру есть несколько задержек. Сведения должны распространиться, кэш клиента — обновиться, а уже открытые соединения могут продолжать жить. Изменение DNS не закрывает их автоматически.

Сокращение срока кэширования помогает только той части пути, которая действительно соблюдает это правило. Оно также увеличивает обращения к службе имён. Нужно проверить настройки библиотек и пулов соединений, а не назначать универсально короткий срок и считать переезд мгновенным.

При плановом выводе экземпляра сначала прекращают направлять ему новую работу, затем дают завершить согласованные операции. У внезапного отказа такого запаса времени нет. Клиенту понадобятся ограниченное ожидание и безопасная обработка ошибки. Новый адрес не отменяет неопределённости: предыдущий запрос мог выполнить действие и потерять ответ. Повторять его следует с учётом идемпотентности.

Устойчивое имя не обеспечивает совместимость версий. При обновлении список некоторое время может содержать старые и новые экземпляры. Если они по-разному понимают контракт, корректная маршрутизация лишь распределит ошибки между ними. Нужно обеспечить совместную работу версий или явно разделить несовместимые интерфейсы. Само присутствие правильного адреса не подтверждает, что клиент способен использовать размещённую там программу.

Что происходит, когда недоступен сам механизм поиска

Работающий клиент может некоторое время пользоваться уже известными адресами, пока новый экземпляр приложения не способен найти вообще ничего. Поэтому проверить только существующие соединения недостаточно. Нужно отдельно испытать запуск потребителя и обновление его списка.

Использовать последние известные адреса иногда допустимо, но срок и условия должны быть определены. Устаревший адрес может вести в никуда, а разрешение обращаться к прежней стороне уже могло быть отозвано. Бесконечный кэш и бесконечные повторные запросы создают разные проблемы, но ни один вариант не является универсальной защитой.

Для расследования нужны логическое имя, выбранный адрес, время обновления и причина ошибки. Удалось ли разрешить имя? Установилось ли соединение? Отказал ли сам сервис? Без этого разговор опять сведётся к «сеть иногда не работает», хотя сбой мог находиться в проверке доступа или конфигурации.

Переезд, который действительно закончился

Полезный тест — заменить экземпляр, пока обычное клиентское приложение продолжает работу. Проверить появление нового адреса, вывод старого, судьбу незавершённого запроса и запуск нового потребителя. Затем временно ограничить поиск и посмотреть, соответствует ли поведение договорённости.

Если платформенный Service или существующий балансировщик уже решает задачу, отдельный реестр может не понадобиться. Окупаемость здесь видна в исчезнувших ручных перенастройках и предсказуемом времени замены. Успешное обновление записи в панели — только промежуточный результат.