JavaRush/Курсы/Модуль 5. Spring/Лекция 235: Практика: настройка Circuit Breaker для микро...

Лекция 235: Практика: настройка Circuit Breaker для микросервисов

Открыта

Мы уже обсудили, что такое Circuit Breaker, почему он важен для микросервисов, и как использовать библиотеку Resilience4j для его реализации. В этой лекции мы перейдём от теории к практике и разберём, как интегрировать Circuit Breaker в реальное приложение, а также настроим его работу.


Постановка задачи

Представьте, что у нас есть микросервис order-service, который обращается к другому микросервису inventory-service для проверки доступности товаров на складе. Иногда inventory-service может испытывать проблемы: быть недоступным или отвечать слишком долго. Наша цель — настроить Circuit Breaker в order-service, чтобы он корректно обрабатывал такие ситуации.


Подготовка проекта

Мы будем работать со Spring Boot-приложением. Если вы ещё не создали проект, воспользуйтесь Spring Initializr, чтобы сгенерировать заготовку. Убедитесь, что проект использует Java 17 (или выше), а также добавьте зависимости:

  • Spring Web для обработки запросов.
  • Resilience4j для нашего Circuit Breaker.
  • Spring Boot Actuator для мониторинга (пригодится позже).

Пример настройки зависимости в pom.xml для Maven:

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Resilience4j -->
    <dependency>
        <groupId>io.github.resilience4j</groupId>
        <artifactId>resilience4j-spring-boot2</artifactId>
    </dependency>

    <!-- Spring Boot Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

Если вы используете Gradle — вот как выглядят нужные зависомости:

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'io.github.resilience4j:resilience4j-spring-boot2'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
}

После добавления зависимостей не забудьте обновить проект!


Реализация Circuit Breaker

Шаг 1: Создание REST-клиента

Для взаимодействия с inventory-service создадим RestTemplate. Вот пример создания REST-клиента в @Configuration-классе:

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

@Configuration
public class RestTemplateConfig {

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

Шаг 2: Сервис для взаимодействия с inventory-service

Теперь добавим сервис, который использует RestTemplate для отправки HTTP-запросов:

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

@Service
public class InventoryService {

    private final RestTemplate restTemplate;

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

    public String checkInventory(String productId) {
        String inventoryUrl = "http://inventory-service/api/inventory/" + productId;
        return restTemplate.getForObject(inventoryUrl, String.class);
    }
}

Шаг 3: Добавление Circuit Breaker

Теперь мы добавим Circuit Breaker в наш InventoryService с использованием Resilience4j. Spring Boot позволяет сделать это с минимальными усилиями благодаря аннотации @CircuitBreaker.

Вот обновлённый код:

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class InventoryService {

    private final RestTemplate restTemplate;

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

    @CircuitBreaker(name = "inventoryService", fallbackMethod = "fallbackCheckInventory")
    public String checkInventory(String productId) {
        String inventoryUrl = "http://inventory-service/api/inventory/" + productId;
        return restTemplate.getForObject(inventoryUrl, String.class);
    }

    // Метод для обработки отказов
    public String fallbackCheckInventory(String productId, Throwable throwable) {
        return "Inventory service is currently unavailable. Please try again later.";
    }
}

Шаг 4: Настройка параметров Circuit Breaker

Для настройки Resilience4j мы используем application.yml или application.properties. Создайте соответствующую конфигурацию:

resilience4j:
  circuitbreaker:
    instances:
      inventoryService:
        failureRateThreshold: 50
        waitDurationInOpenState: 10s
        minimumNumberOfCalls: 5
        slidingWindowSize: 10

Эти параметры означают:

  • failureRateThreshold: порог отказов (в процентах), после которого Circuit Breaker перейдёт в состояние Open.
  • waitDurationInOpenState: время, которое Circuit Breaker находится в состоянии Open, перед попыткой снова перейти в Half-Open.
  • minimumNumberOfCalls: минимальное количество вызовов для вычисления отказов.
  • slidingWindowSize: размер окна для подсчёта метрик.

Тестирование Circuit Breaker

Шаг 1: Простой контроллер

Для тестирования нашей реализации добавим контроллер:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {

    private final InventoryService inventoryService;

    public OrderController(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    }

    @GetMapping("/order")
    public String placeOrder(@RequestParam String productId) {
        return inventoryService.checkInventory(productId);
    }
}

Шаг 2: Проверка работы

  1. Запустите приложение.
  2. Вызовите API /order?productId=123 через Postman или CURL.
  3. Имитируйте отказ inventory-service (например, укажите несуществующий URL). Проверьте, что Circuit Breaker переходит в состояние Open и выдаёт ответ из метода Fallback.

Анализ и оптимизация

Чтобы убедиться, что Circuit Breaker работает так, как мы ожидаем, можно подключить мониторинг через Actuator. Добавьте в application.yml:

management:
  endpoints:
    web:
      exposure:
        include: resilience4j.circuitbreakers

Теперь откройте URL /actuator/resilience4j/circuitbreakers и увидите текущие состояния Circuit Breaker.


Заключительный штрих

Ура! Мы настроили Circuit Breaker для нашего микросервиса, интегрировали его с Resilience4j и протестировали его работу. Благодаря этому наша система стала более отказоустойчивой и готовой к реальным нагрузкам. В следующей лекции мы рассмотрим, как добавить Retry и Timeout для ещё большей стабильности. А пока можете гордиться своей первой "переключалкой цепей"!

Комментарии
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
У этой страницы еще нет ни одного комментария