Introduction
Resilience4j est une bibliothèque légère et modulaire qui implémente les patterns de résilience essentiels pour les applications distribuées. Dans un écosystème de microservices, les appels réseau peuvent échouer à tout moment. Grâce à des mécanismes comme le circuit breaker, le retry ou le bulkhead, Resilience4j permet de rendre votre application plus robuste sans alourdir le code. Ce tutoriel vous guide pas à pas pour l'intégrer dans Spring Boot, de l'installation à l'utilisation concrète de deux patterns majeurs.
Prérequis
- Java 17 ou supérieur
- Spring Boot 3.2+
- Maven ou Gradle
- Connaissances de base en Spring Boot et REST
Ajouter la dépendance Maven
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
<version>2.2.0</version>
</dependency>Cette dépendance active l'intégration native de Resilience4j avec Spring Boot 3. Elle inclut automatiquement les annotations et la configuration via application.yml.
Configuration de base
Créez un fichier application.yml pour définir vos patterns. Chaque pattern possède son propre identifiant et peut être activé indépendamment.
Configurer Circuit Breaker et Retry
resilience4j:
circuitbreaker:
instances:
paymentService:
slidingWindowSize: 10
failureRateThreshold: 50
waitDurationInOpenState: 30s
permittedNumberOfCallsInHalfOpenState: 3
retry:
instances:
paymentService:
maxAttempts: 3
waitDuration: 500msCe fichier configure un circuit breaker qui s'ouvre après 50% d'échecs sur 10 appels et un mécanisme de retry avec 3 tentatives espacées de 500 ms.
Créer le service avec annotations
package com.example.demo.service;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.retry.annotation.Retry;
import org.springframework.stereotype.Service;
@Service
public class PaymentService {
@CircuitBreaker(name = "paymentService", fallbackMethod = "fallbackPayment")
@Retry(name = "paymentService")
public String processPayment(String orderId) {
// Simulation d'un appel externe
if (Math.random() < 0.7) {
throw new RuntimeException("Service indisponible");
}
return "Paiement validé pour " + orderId;
}
public String fallbackPayment(String orderId, Exception ex) {
return "Paiement différé - mode dégradé pour " + orderId;
}
}Les annotations @CircuitBreaker et @Retry sont appliquées directement sur la méthode. Le fallbackMethod est appelé automatiquement quand le circuit est ouvert.
Exposer via un contrôleur REST
package com.example.demo.controller;
import com.example.demo.service.PaymentService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/payments")
public class PaymentController {
private final PaymentService paymentService;
public PaymentController(PaymentService paymentService) {
this.paymentService = paymentService;
}
@GetMapping("/{orderId}")
public String pay(@PathVariable String orderId) {
return paymentService.processPayment(orderId);
}
}Le contrôleur appelle simplement le service. Toute la logique de résilience est gérée par Resilience4j sans code supplémentaire.
Démarrer et tester l'application
./mvnw spring-boot:runLancez l'application puis appelez http://localhost:8080/payments/123 plusieurs fois pour observer le circuit breaker s'ouvrir et le fallback s'activer.
Bonnes pratiques
- Nommez vos instances de façon descriptive (ex: paymentService plutôt que cb1)
- Toujours définir un fallbackMethod pertinent
- Surveillez les métriques via Actuator et Prometheus
- Testez les scénarios de défaillance en environnement de staging
- Commencez avec des seuils conservateurs puis ajustez selon les observations
Erreurs courantes à éviter
- Oublier d'activer l'annotation @EnableCircuitBreaker (inutile avec Spring Boot 3)
- Utiliser le même nom d'instance pour des services différents
- Ne pas gérer les exceptions dans le fallback
- Configurer des seuils trop agressifs dès le départ
Pour aller plus loin
Découvrez nos formations avancées sur la résilience des systèmes distribués : https://learni-group.com/formations