Вопрос 8 · Раздел 17

В чём разница между client-side и server-side discovery

least-connections, по зонам доступности). При server-side discovery это решение принимает LB, и клиент не может на него повлиять.

Версии по языкам: English Russian Ukrainian

🟢 Junior Level

Client-side discovery:

Сервис A сам спрашивает Registry и вызывает Сервис B
Сервис A → Registry: "Где сервис B?" → 10.0.0.5:8080 → вызов

Server-side discovery:

Сервис A вызывает Load Balancer, а LB сам находит Сервис B
Сервис A → Load Balancer → Registry → Сервис B

Разница: кто делает запрос к Registry — клиент или сервер (LB).


🟡 Middle Level

Client-side

// Сервис A сам ищет сервис B
ServiceRegistry registry = new ConsulRegistry("consul:8500");
ServiceInstance instance = registry.getInstance("service-b");

HttpClient client = HttpClient.newBuilder()
    .connectTimeout(Duration.ofSeconds(5))
    .build();

HttpResponse<String> response = client.send(
    HttpRequest.newBuilder(URI.create("http://" + instance.getAddress() + "/api"))
        .GET().build(),
    BodyHandlers.ofString()
);

Плюсы:

  • Больше контроля: сервис сам решает, какой инстанс выбрать (round-robin, least-connections, по зонам доступности). При server-side discovery это решение принимает LB, и клиент не может на него повлиять.
  • Нет дополнительного hop через LB

Минусы:

  • Нужно реализовать discovery logic в каждом сервисе
  • Зависимость от Registry SDK

Server-side

Сервис A → Load Balancer (Nginx/HAProxy) → Service B

# Nginx config
# В production Nginx Plus или consul-template динамически обновляют upstreams.
# Статические IP — упрощение для примера.
upstream service_b {
    server 10.0.0.5:8080;
    server 10.0.0.6:8080;
}

Плюсы:

  • Проще для клиентов
  • LB берёт на себя discovery и balancing

Минусы:

  • Дополнительный hop (latency)
  • LB — single point of failure

Типичные ошибки

  1. Client-side: кэширование без TTL:
    Сервис A закэшировал IP сервиса B
    Сервис B переехал на новый IP
    Сервис A стучится на старый IP
    

🔴 Senior Level

Архитектурные Trade-offs

Client-side Server-side
No single point of failure LB может упасть
Сложнее реализовать Проще
Меньше latency +1 hop
Гибкость (retry, circuit breaker) Меньше контроля

Production Experience

Kubernetes (server-side):

K8s Services → kube-proxy → Endpoints
Сервис A → my-service:8080 → kube-proxy → Pod B

Netflix Ribbon (client-side): ⚠️ Netflix Ribbon устарел (в maintenance mode с 2018). В современных проектах используйте Spring Cloud LoadBalancer или K8s Service.

@LoadBalanced
@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

// Ribbon сам делает discovery + load balancing
restTemplate.getForObject("http://service-b/api", String.class);

Best Practices

✅ Client-side: caching с TTL
✅ Server-side: multiple LB для HA
✅ Health checks в обоих случаях
✅ Fallback при недоступности Registry

❌ Без caching (too many Registry calls)
❌ Без fallback при недоступности LB

🎯 Шпаргалка для интервью

Обязательно знать:

  • Client-side: сервис сам спрашивает Registry и выбирает инстанс (round-robin, least-connections)
  • Server-side: LB берёт discovery и balancing на себя (Nginx, K8s Service)
  • Client-side: нет extra hop, но нужно реализовать логику в каждом сервисе
  • Server-side: проще для клиентов, но +1 hop и LB — потенциальный SPOF
  • Netflix Ribbon устарел (maintenance mode с 2018) — используйте Spring Cloud LoadBalancer
  • Client-side caching ОБЯЗАТЕЛЕН с TTL, иначе stale IP
  • K8s использует server-side: kube-proxy → Endpoints

Частые уточняющие вопросы:

  • Когда выбрать client-side? Нужна гибкость (retry, circuit breaker), минимальная latency.
  • Когда выбрать server-side? Проще, когда команда не хочет писать discovery logic.
  • Что будет без TTL в кэше? Сервис переехал на новый IP — клиент стучится на старый.
  • K8s это какой тип? Server-side: Service → DNS → kube-proxy → Pod.

Красные флаги (НЕ говорить):

  • “Netflix Ribbon — лучший выбор” — устарел, используйте Spring Cloud LoadBalancer
  • “Caching не нужен, Registry быстрый” — лишняя нагрузка на Registry при каждом вызове
  • “Server-side всегда лучше” — зависит от требований к гибкости
  • “LB никогда не падает” — нужен HA (multiple LB)

Связанные темы:

  • [[7. Что такое Service Discovery и зачем он нужен]]
  • [[9. Что такое API Gateway и какие задачи он решает]]
  • [[12. Как реализовать горизонтальное масштабирование микросервисов]]
  • [[26. Какие инструменты используются для оркестрации микросервисов]]
  • [[16. В чём разница между синхронной и асинхронной коммуникацией]]