🌐 Netflix Eureka Cheatsheet Completo 🌐

Netflix Eureka es un servicio de descubrimiento de servicios basado en REST que permite a los microservicios registrarse en una ubicación central y luego descubrir otros servicios para comunicarse con ellos. Es parte del ecosistema de Spring Cloud y un componente clave en la construcción de arquitecturas de microservicios resilientes.


1. 🌟 Conceptos Clave


2. 🛠️ Configuración Inicial (Spring Boot)

2.1. Configuración del Eureka Server (Registro de Servicios)

  1. Añadir dependencias en pom.xml:

    <dependencies>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>3.2.0</version>
            <relativePath/>
        </parent>
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        &lt;!-- Spring Cloud BOM (para gestionar versiones de Spring Cloud) -->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>2023.0.0</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    </dependencies>
  2. Habilitar Eureka Server en la clase principal:

    // src/main/java/com/example/eurekaserver/EurekaServerApplication.java
    package com.example.eurekaserver;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; // Habilita el servidor
    
    @SpringBootApplication
    @EnableEurekaServer // Anotación clave para habilitar el servidor Eureka
    public class EurekaServerApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerApplication.class, args);
        }
    }
  3. Configurar application.yml (para el servidor Eureka):

    # src/main/resources/application.yml
    server:
      port: 8761 # Puerto por defecto de Eureka Server
    
    eureka:
      instance:
        hostname: localhost # Nombre del host donde se ejecuta este servidor
      client:
        register-with-eureka: false # El servidor Eureka NO se registra a sí mismo
        fetch-registry: false       # El servidor Eureka NO intenta buscar otros servicios
        service-url:
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # URL para que los clientes se conecten
    • Iniciar la aplicación. Accede a la UI de Eureka en http://localhost:8761.

2.2. Configuración del Eureka Client (Registro de Microservicios)

  1. Añadir dependencias en pom.xml (en el microservicio):

    <dependencies>
        <parent>...</parent> &lt;!-- Tu parent de Spring Boot -->
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        &lt;!-- Spring Cloud BOM -->
        <dependencyManagement>...</dependencyManagement>
    </dependencies>
  2. Habilitar Eureka Client en la clase principal (opcional a partir de Spring Boot 2.x):

    • Spring Boot habilita el cliente automáticamente si está en el classpath.
    • @EnableDiscoveryClient o @EnableEurekaClient (deprecated) ya no son estrictamente necesarios.
    // src/main/java/com/example/myservice/MyServiceApplication.java
    package com.example.myservice;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    // @EnableDiscoveryClient // Opcional, pero puede ser útil para claridad
    // @EnableEurekaClient // Específico de Eureka, si no quieres usar el genérico @EnableDiscoveryClient
    
    @SpringBootApplication
    public class MyServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(MyServiceApplication.class, args);
        }
    }
  3. Configurar application.yml (para el microservicio cliente):

    # src/main/resources/application.yml
    spring:
      application:
        name: my-product-service # ¡CRÍTICO! El nombre del servicio que se registrará en Eureka
    
    server:
      port: 8080 # Puerto de este microservicio
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/ # URL del Eureka Server
        register-with-eureka: true # Este cliente se registra en Eureka (default: true)
        fetch-registry: true       # Este cliente obtiene el registro de Eureka (default: true)
      instance:
        hostname: localhost
        instance-id: ${spring.application.name}:${instanceId:${random.value}} # ID único de la instancia (útil para múltiples instancias)
        lease-renewal-interval-in-seconds: 10 # Frecuencia de envío de heartbeats (default: 30)
        lease-expiration-duration-in-seconds: 30 # Tiempo para que el servidor considere inactiva una instancia si no hay heartbeat (default: 90)
        # Prefer-ip-address: true # Para registrar la IP en lugar del hostname (útil en entornos de Docker/Kubernetes)
    • Iniciar la aplicación. Deberías verla registrada en la UI del Eureka Server.

3. 🚀 Descubrimiento de Servicios (Consumo)

Una vez que los servicios están registrados, otros microservicios pueden descubrir y llamar a sus instancias.

3.1. Usando DiscoveryClient (Manualmente)

// src/main/java/com/example/myservice/DiscoveryService.java
package com.example.myservice;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DiscoveryService {

    private final DiscoveryClient discoveryClient; // Inyecta DiscoveryClient

    public DiscoveryService(DiscoveryClient discoveryClient) {
        this.discoveryClient = discoveryClient;
    }

    public String getProductServiceBaseUrl() {
        List<ServiceInstance> instances = discoveryClient.getInstances("my-product-service"); // Nombre del servicio
        if (instances != null && !instances.isEmpty()) {
            ServiceInstance serviceInstance = instances.get(0); // Tomar la primera instancia disponible
            return serviceInstance.getUri().toString(); // Obtener la URI base
        }
        return null;
    }
}

3.2. Usando RestTemplate con @LoadBalanced (Cliente HTTP)

// src/main/java/com/example/myservice/AppConfig.java
package com.example.myservice;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class AppConfig {
    @Bean
    @LoadBalanced // Anotación clave para habilitar Ribbon/LoadBalancer con Eureka
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
// src/main/java/com/example/myservice/ProductServiceClient.java
package com.example.myservice;

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class ProductServiceClient {

    private final RestTemplate restTemplate;

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

    public String getProductDetails(String productId) {
        // Usa el nombre del servicio registrado en Eureka, NO el hostname:port
        String url = "http://my-product-service/api/products/" + productId;
        return restTemplate.getForObject(url, String.class);
    }
}

3.3. Usando WebClient con @LoadBalanced (Cliente HTTP Reactivo)

// src/main/java/com/example/myservice/AppConfig.java
package com.example.myservice;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class AppConfig {
    @Bean
    @LoadBalanced
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}
// src/main/java/com/example/myservice/ProductServiceClient.java
package com.example.myservice;

import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Service
public class ProductServiceClient {

    private final WebClient.Builder webClientBuilder;

    public ProductServiceClient(@LoadBalanced WebClient.Builder webClientBuilder) { // Inyecta el builder LoadBalanced
        this.webClientBuilder = webClientBuilder;
    }

    public Mono<String> getProductDetails(String productId) {
        // Usa el nombre del servicio registrado en Eureka
        return webClientBuilder.build().get()
                .uri("http://my-product-service/api/products/{id}", productId) // WebClient usa el nombre del servicio
                .retrieve()
                .bodyToMono(String.class);
    }
}

3.4. Usando FeignClient (Declarativo - Recomendado para REST)

  1. Añadir dependencia en pom.xml:
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
  2. Habilitar Feign en la clase principal (del cliente Feign):
    // src/main/java/com/example/myservice/MyServiceApplication.java
    import org.springframework.cloud.openfeign.EnableFeignClients; // Habilita Feign
    
    @SpringBootApplication
    @EnableFeignClients // Anotación clave
    public class MyServiceApplication { /* ... */ }
  3. Definir la interfaz Feign Client:
    // src/main/java/com/example/myservice/client/ProductFeignClient.java
    package com.example.myservice.client;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    // 'my-product-service' es el nombre del servicio registrado en Eureka
    @FeignClient(name = "my-product-service")
    public interface ProductFeignClient {
    
        @GetMapping("/api/products/{id}")
        String getProductById(@PathVariable("id") String id); // Los nombres de los parámetros deben coincidir
    }
  4. Inyectar y usar Feign Client:
    // src/main/java/com/example/myservice/ProductConsumerService.java
    package com.example.myservice;
    
    import com.example.myservice.client.ProductFeignClient;
    import org.springframework.stereotype.Service;
    
    @Service
    public class ProductConsumerService {
    
        private final ProductFeignClient productFeignClient;
    
        public ProductConsumerService(ProductFeignClient productFeignClient) {
            this.productFeignClient = productFeignClient;
        }
    
        public String getProductInfo(String productId) {
            return productFeignClient.getProductById(productId);
        }
    }

4. 🌐 Alta Disponibilidad y Resiliencia (Eureka Cluster)

# application.yml para Eureka Server A
server:
  port: 8761
eureka:
  instance:
    hostname: eureka-server-a
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-server-b:8762/eureka/ # Se registra con el peer B

# application.yml para Eureka Server B
server:
  port: 8762
eureka:
  instance:
    hostname: eureka-server-b
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-server-a:8761/eureka/ # Se registra con el peer A

# application.yml para un cliente (apunta a ambos)
eureka:
  client:
    service-url:
      defaultZone: http://eureka-server-a:8761/eureka/,http://eureka-server-b:8762/eureka/

5. 💡 Buenas Prácticas y Consejos


Este cheatsheet te proporciona una referencia completa de Netflix Eureka, cubriendo sus conceptos esenciales, cómo configurarlo como servidor y cliente, las diferentes formas de consumir servicios, la alta disponibilidad y las mejores prácticas para implementar un descubrimiento de servicios robusto en arquitecturas de microservicios.