1. Обзор
В этом руководстве мы познакомимся с проектом Spring Cloud Circuit Breaker и узнаем, как мы можем его использовать.
Во-первых, мы посмотрим, что предлагает Spring Cloud Circuit Breaker в дополнение к существующим реализациям прерывателя цепи. Далее мы узнаем, как использовать механизм автоматической настройки Spring Boot для интеграции одного или нескольких автоматических выключателей в наше приложение.
Обратите внимание, что у нас есть дополнительная информация о том, что такое автоматический выключатель и как он работает, в статьях Introduction to Hystrix , Spring Cloud Netflix Hystrix и Guide to Resilience4j .
2. Автоматический выключатель весеннего облака
До недавнего времени Spring Cloud предоставлял нам только один способ добавления автоматических выключателей в наши приложения. Это произошло благодаря использованию Netflix Hystrix в рамках проекта Spring Cloud Netflix.
Проект Spring Cloud Netflix на самом деле представляет собой просто библиотеку-оболочку на основе аннотаций вокруг Hystrix. Следовательно, эти две библиотеки тесно связаны. Это означает, что мы не можем переключиться на другую реализацию автоматического выключателя без изменения приложения.
Проект Spring Cloud Circuit Breaker решает эту проблему. Он обеспечивает уровень абстракции для различных реализаций автоматических выключателей. Это подключаемая архитектура. Таким образом, мы можем кодировать предоставленную абстракцию/интерфейс и переключаться на другую реализацию в зависимости от наших потребностей.
В наших примерах мы сосредоточимся только на реализации Resilience4J. Однако эти методы можно использовать и для других плагинов.
3. Автоматическая настройка
Чтобы использовать определенные реализации автоматического выключателя в нашем приложении, нам нужно добавить соответствующий стартер Spring. В нашем случае воспользуемся spring-cloud-starter-circuitbreaker-resilence4j
:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
<version>1.0.2.RELEASE</version>
</dependency>
Механизм автоконфигурации настраивает необходимые bean-компоненты прерывателя цепи, если видит один из стартеров в пути к классам.
Если бы мы хотели отключить автоматическую настройку Resilience4J, мы могли бы установить для свойства spring.cloud.circuitbreaker.resilience4j.enabled
значение false
.
4. Пример простого автоматического выключателя
Давайте создадим веб-приложение с помощью Spring Boot, чтобы мы могли изучить, как работает библиотека Spring Cloud Circuit Breaker.
Мы создадим простой веб-сервис, возвращающий список альбомов. Предположим, необработанный список предоставлен сторонней службой. Для простоты мы будем использовать внешний фиктивный API, предоставленный Jsonplaceholder , для получения списка:
https://jsonplaceholder.typicode.com/albums
4.1. Создать автоматический выключатель
Давайте создадим наш первый автоматический выключатель. Мы начнем с внедрения экземпляра компонента CircuitBreakerFactory
:
@Service
public class AlbumService {
@Autowired
private CircuitBreakerFactory circuitBreakerFactory;
//...
}
Теперь мы можем легко создать автоматический выключатель с помощью метода CircuitBreakerFactory#create
. В качестве аргумента принимает идентификатор автоматического выключателя:
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");
4.2. Оберните задачу в автоматический выключатель
Чтобы обернуть и запустить задачу, защищенную автоматическим выключателем, нам нужно вызвать метод run
, который принимает поставщика
в качестве аргумента.
public String getAlbumList() {
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");
String url = "https://jsonplaceholder.typicode.com/albums";
return circuitBreaker.run(() -> restTemplate.getForObject(url, String.class));
}
Автоматический выключатель запускает наш метод за нас и обеспечивает отказоустойчивость.
Иногда нашей внешней службе может потребоваться слишком много времени, чтобы ответить, вызвать неожиданное исключение или внешнюю службу или хост не существует. В этом случае мы можем предоставить запасной вариант в качестве второго аргумента для метода запуска :
public String getAlbumList() {
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");
String url = "http://localhost:1234/not-real";
return circuitBreaker.run(() -> restTemplate.getForObject(url, String.class),
throwable -> getDefaultAlbumList());
}
Лямбда для отката получает Throwable
в качестве входных данных, описывающих ошибку. Это означает , что мы можем предоставить вызывающему объекту разные результаты отката в зависимости от типа исключения , вызвавшего откат.
В этом случае мы не будем учитывать исключение. Мы просто вернем кешированный список альбомов.
Если внешний вызов завершается исключением и резервный вариант не предоставляется, Spring создает исключение NoFallbackAvailableException
.
4.3. Создайте контроллер
Теперь давайте завершим наш пример и создадим простой контроллер, который вызывает методы службы и представляет результаты через браузер:
@RestController
public class Controller {
@Autowired
private Service service;
@GetMapping("/albums")
public String albums() {
return service.getAlbumList();
}
}
Наконец, давайте вызовем службу REST и посмотрим на результаты:
[GET] http://localhost:8080/albums
5. Глобальная пользовательская конфигурация
Обычно конфигурации по умолчанию недостаточно. По этой причине нам необходимо создавать автоматические выключатели с индивидуальными конфигурациями, основанными на наших вариантах использования.
Чтобы переопределить конфигурацию по умолчанию, нам нужно указать наши собственные bean-компоненты и свойства в классе @Configuration
.
Здесь мы собираемся определить глобальную конфигурацию для всех автоматических выключателей. По этой причине нам необходимо определить bean -компонент Customizer<CircuitBreakerFactory>
. Итак, давайте воспользуемся реализацией Resilience4JCircuitBreakerFactory
.
Во-первых, мы определим классы конфигурации автоматического выключателя и ограничителя времени в соответствии с руководством Resilience4j :
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofMillis(1000))
.slidingWindowSize(2)
.build();
TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(4))
.build();
Затем давайте встроим конфигурацию в bean-компонент Customizer
с помощью метода Resilience4JCircuitBreakerFactory.configureDefault
:
@Configuration
public class Resilience4JConfiguration {
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> globalCustomConfiguration() {
// the circuitBreakerConfig and timeLimiterConfig objects
return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
.timeLimiterConfig(timeLimiterConfig)
.circuitBreakerConfig(circuitBreakerConfig)
.build());
}
}
6. Конкретная пользовательская конфигурация
Конечно, в нашем приложении может быть несколько автоматических выключателей. Поэтому в некоторых случаях нам нужна определенная конфигурация для каждого автоматического выключателя.
Точно так же мы можем определить один или несколько bean-компонентов Customizer
. Затем мы можем предоставить разные конфигурации для каждого из них, используя метод Resilience4JCircuitBreakerFactory.configure
:
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> specificCustomConfiguration1() {
// the circuitBreakerConfig and timeLimiterConfig objects
return factory -> factory.configure(builder -> builder.circuitBreakerConfig(circuitBreakerConfig)
.timeLimiterConfig(timeLimiterConfig).build(), "circuitBreaker");
}
Здесь мы предоставляем второй параметр, идентификатор автоматического выключателя, который мы настраиваем.
Мы также можем настроить несколько автоматических выключателей с одинаковой конфигурацией, предоставив список идентификаторов автоматических выключателей одному и тому же методу:
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> specificCustomConfiguration2() {
// the circuitBreakerConfig and timeLimiterConfig objects
return factory -> factory.configure(builder -> builder.circuitBreakerConfig(circuitBreakerConfig)
.timeLimiterConfig(timeLimiterConfig).build(),
"circuitBreaker1", "circuitBreaker2", "circuitBreaker3");
}
7. Альтернативные реализации
Мы увидели, как использовать реализацию Resilience4j
для создания одного или нескольких автоматических выключателей с помощью Spring Cloud Circuit Breaker.
Однако есть и другие реализации, поддерживаемые Spring Cloud Circuit Breaker, которые мы можем использовать в нашем приложении:
Стоит отметить, что мы можем смешивать и сочетать различные реализации автоматических выключателей в нашем приложении. Мы не ограничиваемся одной библиотекой.
Вышеупомянутые библиотеки имеют больше возможностей, чем мы рассмотрели здесь. Однако Spring Cloud Circuit Breaker является абстракцией только над частью автоматического выключателя. Например, Resilience4j также предоставляет другие модули, такие как RateLimiter
, Bulkhead
, Retry
, в дополнение к модулям CircuitBreaker
и TimeLimiter
, использованным в этой статье.
8. Заключение
В этой статье мы обнаружили проект Spring Cloud Circuit Breaker.
Во-первых, мы узнали, что такое Spring Cloud Circuit Breaker и как он позволяет нам добавлять автоматические выключатели в наше приложение.
Затем мы использовали механизм автоматической настройки Spring Boot, чтобы показать, как определять и интегрировать автоматические выключатели. Кроме того, мы продемонстрировали, как Spring Cloud Circuit Breaker работает через простой сервис REST.
Наконец-то мы научились настраивать все автоматические выключатели как вместе, так и по отдельности.
Как всегда, исходный код этого руководства доступен на GitHub .