← Назад к вопросам

Реализацией какого паттерна является Eureka

2.8 Senior🔥 151 комментариев
#REST API и микросервисы#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализацией какого паттерна является Eureka?

Eureka — это реализация паттерна Service Registry (реестр сервисов) от Netflix, используемая в микросервисной архитектуре для динамического обнаружения сервисов.

Service Registry Pattern

Service Registry — это каталог всех доступных сервисов в системе. Вместо захардкодированных IP адресов и портов, сервисы регистрируют себя и клиенты запрашивают адреса из реестра.

Как работает Eureka

┌──────────────────┐
│  Eureka Server   │  (реестр)
│  (Service        │
│   Registry)      │
└──────────────────┘
        ↑    ↓
    регистр. поиск
       ↑       ↓
┌──────────┐  ┌──────────┐
│ Service  │  │ Service  │
│   (A)    │  │   (B)    │
└──────────┘  └──────────┘

Пример: Eureka Server Setup

1. Зависимость:

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

2. Конфигурация Server:

# application.yml
spring:
  application:
    name: eureka-server
server:
  port: 8761

eureka:
  server:
    enable-self-preservation: true
  client:
    register-with-eureka: false  # Сервер не регистрирует сам себя
    fetch-registry: false         # Не нужно читать реестр

3. Java конфиг:

@SpringBootApplication
@EnableEurekaServer  // Активируем Eureka сервер
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

Пример: Eureka Client (Микросервис)

1. Зависимость:

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

2. Конфигурация Client:

# application.yml
spring:
  application:
    name: order-service  # Название, под которым регистрируется сервис

server:
  port: 8081

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka  # Адрес Eureka сервера
  instance:
    prefer-ip-address: true  # Использовать IP вместо hostname
    lease-renewal-interval-in-seconds: 30  # Heartbeat каждые 30 сек

3. Java конфиг:

@SpringBootApplication
@EnableEurekaClient  // Включаем клиент Eureka
@RestController
public class OrderServiceApplication {
    
    @GetMapping("/api/orders")
    public List<Order> getOrders() {
        return List.of(new Order(1, "Order 1"));
    }
    
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

Как сервис находит другой сервис

Вариант 1: Using RestTemplate с Load Balancer

@Service
public class OrderService {
    @Autowired
    private RestTemplate restTemplate;  // Специальный RestTemplate с балансировкой
    
    public List<Item> getItems() {
        // Используем логическое имя сервиса (из Eureka), не IP:port
        String url = "http://inventory-service/api/items";
        
        // RestTemplate автоматически:
        // 1. Запрашивает адреса inventory-service из Eureka
        // 2. Выбирает один из доступных экземпляров
        // 3. Отправляет запрос
        return restTemplate.getForObject(url, List.class);
    }
}

// Конфиг RestTemplate
@Configuration
public class RestTemplateConfig {
    @Bean
    @LoadBalanced  // Включаем load balancing через Eureka
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Вариант 2: Using DiscoveryClient

@Service
public class PaymentService {
    @Autowired
    private DiscoveryClient discoveryClient;
    
    public String callInventoryService() {
        // Получаем список экземпляров сервиса
        List<ServiceInstance> instances = discoveryClient.getInstances("inventory-service");
        
        if (instances.isEmpty()) {
            throw new ServiceUnavailableException("No inventory-service instances available");
        }
        
        // Выбираем первый (или используем балансировщик)
        ServiceInstance instance = instances.get(0);
        String url = instance.getUri() + "/api/items";
        
        // Вызываем
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.getForObject(url, String.class);
    }
}

Вариант 3: Using Feign (самый удобный)

// Feign клиент - декларативный способ
@FeignClient(name = "inventory-service")  // Автоматически ищет в Eureka
public interface InventoryServiceClient {
    @GetMapping("/api/items")
    List<Item> getItems();
    
    @PostMapping("/api/items/reserve")
    boolean reserveItems(@RequestBody List<Long> itemIds);
}

// Использование
@Service
public class OrderService {
    @Autowired
    private InventoryServiceClient inventoryClient;
    
    public List<Item> getAvailableItems() {
        // Не нужно знать адрес! Eureka найдёт сам
        return inventoryClient.getItems();
    }
}

// Конфиг для Feign
@EnableFeignClients
@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

Жизненный цикл регистрации в Eureka

1. Сервис запускается
   ↓
2. Отправляет POST запрос в Eureka: "Я online, вот мой адрес"
   Registration: /eureka/v2/apps/ORDER-SERVICE
   
   Body: {
     instance: {
       instanceId: "order-service:1",
       hostName: "192.168.1.100",
       port: 8081,
       status: "UP"
     }
   }
   
   ↓
3. Eureka сохраняет сервис в реестре и отвечает 204 OK
   ↓
4. Сервис каждые 30 сек отправляет heartbeat (лайфбит)
   Heartbeat: PUT /eureka/v2/apps/ORDER-SERVICE/order-service:1
   
   ↓
5. Если heartbeat не приходит 90+ сек → Eureka помечает как DOWN
   ↓
6. Сервис выключается → отправляет DELETE /eureka/v2/apps/ORDER-SERVICE/order-service:1
   ↓
7. Eureka удаляет из реестра

Проблемы и решения

Проблема 1: Network Partition

// Eureka имеет "Self Preservation Mode"
// Если > 85% инстансов потеряют heartbeat за 15 минут,
// Eureka не удаляет их (может быть сетевая проблема)

eureka:
  server:
    enable-self-preservation: true  # По умолчанию включено
    renewal-percent-threshold: 0.85

Проблема 2: Кэширование в клиентах

// Клиент кэширует список инстансов локально
eureka:
  client:
    registry-fetch-interval-seconds: 30  # Обновлять каждые 30 сек

Проблема 3: Задержка в обнаружении DOWN сервисов

Heartbeat interval: 30 сек
Eviction interval: 60 сек
Client cache update: 30 сек
Итого: до 2 минут, пока все узнают, что сервис DOWN!

Решение: использовать circuit breaker (Hystrix, Resilience4j)

Альтернативы Eureka

  1. Consul (HashiCorp) — более мощный, с health checks
  2. etcd (Kubernetes) — встроен в K8s
  3. ZooKeeper — старый, но надёжный
  4. Nacos (Alibaba) — похож на Eureka, но лучше
  5. Service Mesh (Istio) — управляет сервис дискавери на уровне infra

Когда использовать Eureka

Плюсы:

  • Простая настройка для Spring Boot
  • Встроена в Spring Cloud
  • Хорошо работает в контейнерах
  • Низкие требования к ресурсам

Минусы:

  • Требует отдельного сервера
  • Eventual consistency (не гарантирует немедленное обновление)
  • Может быть SPOF (Single Point of Failure) — нужен кластер
  • Вытесняется Kubernetes и Service Mesh

Итоги

Eureka реализует паттерн Service Registry:

  • Что делает: Ведёт каталог доступных сервисов
  • Зачем: Позволяет микросервисам найти друг друга без захардкодирования адресов
  • Как: Через регистрацию и heartbeat
  • Когда использовать: В микросервисной архитектуре на Spring Cloud
  • Альтернативы: Consul, Kubernetes Service Discovery, Nacos
Реализацией какого паттерна является Eureka | PrepBro