Guide rapide du disjoncteur Spring Cloud

1. Vue d'ensemble

Dans ce didacticiel, nous présenterons le projet Spring Cloud Circuit Breaker et découvrirons comment nous pouvons l'utiliser.

Tout d'abord, nous allons voir ce que propose le Spring Cloud Circuit Breaker en plus des implémentations de disjoncteurs existantes. Ensuite, nous allons apprendre à utiliser le mécanisme de configuration automatique de Spring Boot pour intégrer un ou plusieurs disjoncteurs dans notre application.

Notez que nous avons plus d'informations sur ce qu'est un disjoncteur et son fonctionnement dans Introduction à Hystrix, Spring Cloud Netflix Hystrix et Guide to Resilience4j.

2. Disjoncteur Spring Cloud

Jusqu'à récemment, Spring Cloud ne nous fournissait qu'une seule façon d'ajouter des disjoncteurs dans nos applications. C'était grâce à l'utilisation de Netflix Hystrix dans le cadre du projet Spring Cloud Netflix.

Le projet Spring Cloud Netflix n'est en réalité qu'une bibliothèque d'encapsuleurs basée sur des annotations autour d'Hystrix. Par conséquent, ces deux bibliothèques sont étroitement liées. Cela signifie que nous ne pouvons pas passer à une autre implémentation de disjoncteur sans changer l'application.

Le projet Spring Cloud Circuit Breaker résout ce problème. Il fournit une couche d'abstraction à travers différentes implémentations de disjoncteurs. C'est une architecture enfichable. Ainsi, nous pouvons coder par rapport à l'abstraction / interface fournie et passer à une autre implémentation en fonction de nos besoins.

Pour nos exemples, nous nous concentrerons uniquement sur l'implémentation de Resilience4J. Cependant, ces techniques peuvent être utilisées pour d'autres plugins.

3. Configuration automatique

Afin d'utiliser une implémentation de disjoncteur spécifique dans notre application, nous devons ajouter le démarreur à ressort approprié. Dans notre cas, utilisons spring-cloud-starter-circuitbreaker-resilience4j :

 org.springframework.cloud spring-cloud-starter-circuitbreaker-resilience4j 1.0.2.RELEASE 

Le mécanisme de configuration automatique configure les beans de disjoncteur nécessaires s'il voit l'un des démarreurs dans le chemin de classe.

Si nous voulions désactiver la configuration automatique de Resilience4J, nous pourrions définir la propriété spring.cloud.circuitbreaker.resilience4j.enabled sur false .

4. Un exemple de disjoncteur simple

Créons une application Web à l'aide de Spring Boot pour nous permettre d'explorer le fonctionnement de la bibliothèque Spring Cloud Circuit Breaker.

Nous allons créer un service Web simple renvoyant une liste d'albums. Supposons que la liste brute soit fournie par un service tiers. Pour plus de simplicité, nous utiliserons une API factice externe fournie par Jsonplaceholder pour récupérer la liste:

//jsonplaceholder.typicode.com/albums

4.1. Créer un disjoncteur

Créons notre premier disjoncteur. Nous allons commencer par injecter une instance du bean CircuitBreakerFactory :

@Service public class AlbumService { @Autowired private CircuitBreakerFactory circuitBreakerFactory; //... }

Maintenant, nous pouvons facilement créer un disjoncteur à l'aide de la méthode CircuitBreakerFactory # create . Il prend l'identifiant du disjoncteur comme argument:

CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");

4.2. Enveloppez une tâche dans un disjoncteur

Pour encapsuler et exécuter une tâche protégée par le disjoncteur, nous devons appeler la méthode r un qui prend un fournisseur comme argument.

public String getAlbumList() { CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker"); String url = "//jsonplaceholder.typicode.com/albums"; return circuitBreaker.run(() -> restTemplate.getForObject(url, String.class)); }

Le disjoncteur exécute notre méthode pour nous et offre une tolérance aux pannes.

Parfois, notre service externe peut prendre trop de temps pour répondre, lancer une exception inattendue ou le service externe ou l'hôte n'existe pas. Dans ce cas, nous pouvons fournir une solution de secours comme deuxième argument de la méthode run :

public String getAlbumList() { CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker"); String url = "//localhost:1234/not-real"; return circuitBreaker.run(() -> restTemplate.getForObject(url, String.class), throwable -> getDefaultAlbumList()); }

Le lambda pour le repli reçoit le Throwable en tant qu'entrée, décrivant l'erreur. Cela signifie que nous pouvons fournir différents résultats de secours à l'appelant, en fonction du type d'exception qui a déclenché le repli.

Dans ce cas, nous ne prendrons pas en compte l'exception. Nous allons simplement retourner une liste d'albums en cache.

Si l'appel externe se termine par une exception et qu'aucune solution de secours n'est fournie, une exception NoFallbackAvailableException est levée par Spring.

4.3. Construire un contrôleur

Maintenant, terminons notre exemple et créons un contrôleur simple qui appelle les méthodes de service et présente les résultats via un navigateur:

@RestController public class Controller { @Autowired private Service service; @GetMapping("/albums") public String albums() { return service.getAlbumList(); } }

Enfin, appelons le service REST et voyons les résultats:

[GET] //localhost:8080/albums

5. Configuration personnalisée globale

Habituellement, la configuration par défaut ne suffit pas. Pour cette raison, nous devons créer des disjoncteurs avec des configurations personnalisées basées sur nos cas d'utilisation.

Afin de remplacer la configuration par défaut, nous devons spécifier nos propres beans et propriétés dans une classe @Configuration .

Ici, nous allons définir une configuration globale pour tous les disjoncteurs. Pour cette raison, nous devons définir un bean Customizer . Alors , utilisons la Resilience4JCircuitBreakerFactory mise en œuvre.

Tout d'abord, nous allons définir les classes de configuration de disjoncteur et de limiteur de temps selon le didacticiel Resilience4j:

CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom() .failureRateThreshold(50) .waitDurationInOpenState(Duration.ofMillis(1000)) .slidingWindowSize(2) .build(); TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(4)) .build();

Ensuite, intégrons la configuration dans un bean Customizer à l'aide de la méthode Resilience4JCircuitBreakerFactory.configureDefault :

@Configuration public class Resilience4JConfiguration { @Bean public Customizer globalCustomConfiguration() { // the circuitBreakerConfig and timeLimiterConfig objects return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id) .timeLimiterConfig(timeLimiterConfig) .circuitBreakerConfig(circuitBreakerConfig) .build()); } }

6. Configuration personnalisée spécifique

Bien entendu, nous pouvons avoir plusieurs disjoncteurs dans notre application. Par conséquent, dans certains cas, nous avons besoin d'une configuration spécifique pour chaque disjoncteur.

Similarly, we can define one or more Customizer beans. Then, we can provide a different configuration for each one by using the Resilience4JCircuitBreakerFactory.configure method:

@Bean public Customizer specificCustomConfiguration1() { // the circuitBreakerConfig and timeLimiterConfig objects return factory -> factory.configure(builder -> builder.circuitBreakerConfig(circuitBreakerConfig) .timeLimiterConfig(timeLimiterConfig).build(), "circuitBreaker"); }

Here we provide a second parameter, the id of the circuit breaker we're configuring.

We can also set up multiple circuit breakers with the same configuration by providing a list of circuit breaker ids to the same method:

@Bean public Customizer specificCustomConfiguration2() { // the circuitBreakerConfig and timeLimiterConfig objects return factory -> factory.configure(builder -> builder.circuitBreakerConfig(circuitBreakerConfig) .timeLimiterConfig(timeLimiterConfig).build(), "circuitBreaker1", "circuitBreaker2", "circuitBreaker3"); }

7. Alternative Implementations

We've seen how to use the Resilience4j implementation to create one or more circuit breakers with Spring Cloud Circuit Breaker.

However, there are other implementations supported by Spring Cloud Circuit Breaker that we can leverage in our application:

  • Hystrix
  • Sentinel
  • Spring Retry

It's worth mentioning that we can mix and match different circuit breaker implementations in our application. We're not just limited to one library.

The above libraries have more capabilities than we've explored here. However, Spring Cloud Circuit Breaker is an abstraction over only the circuit breaker part. For example, Resilience4j also provides other modules like RateLimiter, Bulkhead, Retry in addition to the CircuitBreaker and TimeLimiter modules used in this article.

8. Conclusion

In this article, we discovered the Spring Cloud Circuit Breaker project.

First, we learned what the Spring Cloud Circuit Breaker is, and how it allows us to add circuit breakers to our application.

Ensuite, nous avons exploité le mécanisme de configuration automatique de Spring Boot afin de montrer comment définir et intégrer des disjoncteurs. De plus, nous avons montré comment le Spring Cloud Circuit Breaker fonctionne via un service REST simple.

Enfin, nous avons appris à configurer tous les disjoncteurs ensemble, ainsi qu'individuellement.

Comme toujours, le code source de ce didacticiel est disponible à l'adresse over sur GitHub.