Перейти к содержанию

Service Discovery

Service Discovery - механизм, которым gateway находит сетевой адрес нужного сервиса через service registry.


Service registry

Service registry - база живых инстансов: имя сервиса -> список адресов.

  • Self-registration - сервис при старте сам регистрируется в registry и шлёт heartbeat. Так работает Eureka-клиент в Spring Cloud
  • Third-party registration - инстансы регистрирует платформа, сервис про registry не знает. Так делает Kubernetes
  • Health check и TTL - инстанс, который не ответил на проверку или не прислал heartbeat, выпадает из registry

Registry - отдельный сервис или часть платформы (см. Технологии). В Kubernetes его роль играют объекты Service и EndpointSlice в API-сервере плюс DNS (CoreDNS).


Технологии

Реестры Как устроен Когда брать
Consul Реестр HashiCorp: health checks, DNS-интерфейс, KV-хранилище, встроенный mesh, несколько дата-центров Сервисы вне Kubernetes или вперемешку: виртуальные машины и Kubernetes
Eureka Реестр из Netflix OSS на Java: self-registration и heartbeat, доступность важнее согласованности (AP) Spring Cloud без Kubernetes, легаси на Netflix OSS
Apache ZooKeeper Сервис координации, discovery на эфемерных узлах (Curator Service Discovery), согласованный (CP) ZooKeeper уже стоит: Dubbo, старые Kafka и Hadoop
etcd Согласованное KV-хранилище на Raft, discovery через ключи с TTL. Хранилище самого Kubernetes Свой discovery поверх KV, если etcd уже стоит
Nacos Реестр и конфиги в одном, от Alibaba Spring Cloud Alibaba, Dubbo
Встроено в платформу Как устроен Когда брать
Kubernetes Service и EndpointSlice плюс CoreDNS, kube-proxy раскидывает запросы по живым подам Дефолт в Kubernetes, отдельный реестр не нужен
Docker Compose, Docker Swarm Встроенный DNS: сервис доступен по имени в общей сети Локальная разработка, небольшие стенды
AWS Cloud Map, ECS Service Connect Managed-реестр и discovery для сервисов в AWS Бэкенд в AWS без Kubernetes
Google Service Directory Managed-реестр сервисов в GCP Бэкенд в GCP

На стороне клиента в Spring Cloud работает абстракция DiscoveryClient с реализациями для Eureka, Consul, ZooKeeper и Kubernetes, а балансирует Spring Cloud LoadBalancer (сменил Netflix Ribbon). В service mesh discovery делает control plane: берёт живые инстансы из реестра платформы и раздаёт их sidecar-прокси.


Client-side и server-side discovery

Client-side - клиент сам спрашивает registry, получает список инстансов и сам выбирает, куда идти: Eureka и Spring Cloud LoadBalancer, Consul. Хопов меньше, клиент идёт прямо в инстанс, но логика discovery живёт в каждом клиенте и в каждом языке.

Server-side - клиент идёт на стабильный адрес, а load balancer или DNS за ним берёт адреса инстансов из registry: Kubernetes Service, AWS ELB, DNS-интерфейс Consul. Клиент простой, но появляется лишний хоп и ещё один компонент. Так же работает API Gateway: маршрут знает имя сервиса, а адрес спрашивает у registry.


Грабли

  • Registry тоже падает. Без репликации и кэша адресов на клиенте он становится single point of failure для всего кластера.
  • Мёртвые записи. Инстанс умер, а в registry ещё «жив». Спасают health checks и TTL, иначе трафик льётся в мёртвый под.