← Kursa Dön
📄 Text · 35 min

Eureka Service Discovery

Mikroservis mimarisinde servisler dinamiktir — yeni instance'lar başlar, eskiler kapanır, IP adresleri değişir. Servislerin birbirini bulması için sabit IP/port kullanmak yerine bir Service Discovery mekanizması kullanılır. Netflix Eureka, bu amaçla en yaygın kullanılan çözümdür. Bu derste Eureka Server kurulumunu, client kaydını ve client-side load balancing'i detaylı inceleyeceğiz.

Service Discovery Nedir?

Geleneksel yapıda servis adresleri konfigürasyon dosyalarında hardcode edilir:

# order-service application.yml
user-service:
  url: http://192.168.1.10:8081  # IP değişirse ne olacak?

Bu yaklaşımın sorunları açıktır: IP adresleri değiştiğinde, yeni instance eklendiğinde veya bir instance kapandığında konfigürasyonun güncellenmesi gerekir. Service Discovery bu sorunu otomatikleştirir.

Eureka iki bileşenden oluşur:

  • Eureka Server — Servis kayıt defteri. Tüm servislerin adreslerini tutar.

  • Eureka Client — Kendini server'a kaydeden ve diğer servisleri sorgulayan uygulama.

Eureka Server Kurulumu

Yeni bir Spring Boot projesi oluşturun:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

Ana sınıf:

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

application.yml:

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false   # kendini kaydetme
    fetch-registry: false          # başkalarını sorgulama
  server:
    enable-self-preservation: true
    eviction-interval-timer-in-ms: 5000

register-with-eureka: false ve fetch-registry: false — Eureka Server'ın kendisi bir servis değildir, sadece kayıt defteridir. Kendini kaydetmesi veya başkalarını sorgulaması gerekmez.

Başlatıldığında http://localhost:8761 adresinde Eureka Dashboard görüntülenir. Bu dashboard, kayıtlı tüm servisleri, instance'ları ve durumlarını gösterir.

Eureka Client (Servis Kaydı)

Her mikroservis Eureka Client olarak çalışır. Dependency:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

application.yml:

spring:
  application:
    name: user-service    # Eureka'daki servis adı

server:
  port: 8081

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true    # hostname yerine IP kullan
    instance-id: ${spring.application.name}:${server.port}

@EnableDiscoveryClient annotasyonu artık Spring Boot 3.x'te otomatik olarak uygulanır — dependency eklenmesi yeterlidir. Ancak açıkça belirtmek istiyorsanız:

@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

Servis Kaydı Yaşam Döngüsü

1. User Service başlar → Eureka Server'a kayıt isteği gönderir
2. Eureka Server kaydı kabul eder → registry'e ekler
3. User Service her 30 saniyede heartbeat gönderir (lease renewal)
4. Eureka Server 90 saniye heartbeat almazsa → instance'ı siler
5. Diğer servisler Eureka'dan user-service adresini sorgular

Client-Side Load Balancing

Birden fazla instance varsa (örneğin user-service 3 instance çalışıyor), isteklerin dengeli dağıtılması gerekir. Spring Cloud LoadBalancer bunu otomatik yapar:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
@Configuration
public class RestClientConfig {

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

@LoadBalanced annotasyonu, RestTemplate'e load balancing özelliği kazandırır. Artık IP adresi yerine servis adını kullanabilirsiniz:

@Service
public class OrderService {

    private final RestTemplate restTemplate;

    public OrderService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public UserDto getUser(Long userId) {
        // "user-service" Eureka'daki servis adı
        // LoadBalancer otomatik olarak mevcut instance'lardan birine yönlendirir
        return restTemplate.getForObject(
            "http://user-service/api/users/{id}",
            UserDto.class, userId);
    }
}

Load balancing stratejileri:

  • Round Robin (varsayılan) — İstekler sırayla her instance'a dağıtılır

  • Random — Rastgele bir instance seçilir

// Özel load balancing stratejisi
@Configuration
public class CustomLoadBalancerConfig {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
            .withDiscoveryClient()
            .withHealthChecks()
            .build(context);
    }
}

Eureka High Availability

Production ortamda tek bir Eureka Server tek hata noktası (SPOF) olur. Çözüm: birden fazla Eureka Server'ın birbirini kaydederek çalışması:

# eureka-server-1 (port 8761)
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8762/eureka/

# eureka-server-2 (port 8762)
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

Client'lar her iki sunucuyu da bilir:

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/

Eureka, mikroservis mimarisinin temel yapı taşıdır. Servislerin birbirini dinamik olarak keşfetmesini ve load balancing ile yüksek erişilebilirlik sağlamasını mümkün kılar.