Dlaczego Spring Cloud Circuit Breaker jest ważny?
W architekturze microservices aplikacje są ze sobą ściśle powiązane przez wywołania HTTP. Gdy jedna usługa zaczyna działać wolno lub zawodzi, może to spowodować kaskadową awarię całego systemu. Circuit Breaker działa jak bezpiecznik elektryczny – gdy wykryje problemy, „otwiera obwód” i zapobiega dalszym wywołaniom do uszkodzonej usługi, dając jej czas na regenerację.
Z perspektywy biznesowej oznacza to większą stabilność aplikacji, lepsze doświadczenie użytkownika i mniej nocnych telefonów od operations team.
Co się nauczysz:
- Jak działa wzorzec Circuit Breaker w microservices
- Konfigurację Spring Cloud Circuit Breaker z Hystrix
- Implementację fallback methods dla awaryjnych scenariuszy
- Monitorowanie i dashboardy dla Circuit Breaker
- Najlepsze praktyki w środowisku produkcyjnym
Wymagania wstępne:
- Znajomość Spring Boot (6+ miesięcy)
- Podstawy REST API i HTTP
- Pojęcie o architekturze microservices
- Java 8+ i Maven
Czym jest Circuit Breaker?
Circuit Breaker ma三 stany:
– **CLOSED** – normalne działanie, wywołania przechodzą
– **OPEN** – obwód otwarty, wszystkie wywołania są odrzucane
– **HALF-OPEN** – testowy stan, przepuszcza ograniczoną liczbę wywołań
Konfiguracja Spring Cloud Circuit Breaker
Najpierw dodaj dependency do pom.xml:
org.springframework.cloud spring-cloud-starter-netflix-hystrix org.springframework.cloud spring-cloud-starter-netflix-hystrix-dashboard
Włącz Circuit Breaker w głównej klasie aplikacji:
@SpringBootApplication @EnableCircuitBreaker @EnableHystrixDashboard public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
Implementacja Circuit Breaker
Oto przykład serwisu który wywołuje zewnętrzny API z Circuit Breaker:
@Service public class PaymentService { @Autowired private RestTemplate restTemplate; @HystrixCommand( fallbackMethod = "getPaymentFallback", commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000"), @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"), @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000") } ) public PaymentResult processPayment(PaymentRequest request) { String url = "http://payment-service/api/payments"; return restTemplate.postForObject(url, request, PaymentResult.class); } // Fallback method - wywołana gdy Circuit Breaker jest OPEN public PaymentResult getPaymentFallback(PaymentRequest request) { return PaymentResult.builder() .status("DEFERRED") .message("Payment service temporarily unavailable. Transaction queued for later processing.") .transactionId(UUID.randomUUID().toString()) .build(); } }
Konfiguracja parametrów Circuit Breaker
Kluczowe parametry Hystrix w application.yml:
hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 3000 circuitBreaker: requestVolumeThreshold: 10 # Min liczba requestów w oknie errorThresholdPercentage: 50 # Procent błędów powodujący otwarcie sleepWindowInMilliseconds: 10000 # Czas oczekiwania w stanie OPEN metrics: rollingStats: timeInMilliseconds: 20000 # Okno czasowe dla statystyk
Parametr | Opis | Domyślna wartość |
---|---|---|
requestVolumeThreshold | Min. liczba requestów w oknie czasowym | 20 |
errorThresholdPercentage | Procent błędów powodujący otwarcie | 50% |
sleepWindowInMilliseconds | Czas w stanie OPEN | 5000ms |
timeoutInMilliseconds | Timeout dla pojedynczego wywołania | 1000ms |
Monitorowanie z Hystrix Dashboard
Hystrix Dashboard pozwala monitorować stan Circuit Breaker w czasie rzeczywistym:
@RestController public class HystrixStreamController { @RequestMapping("/health") public String health() { return "OK"; } }
Konfiguracja w application.yml:
management: endpoints: web: exposure: include: hystrix.stream endpoint: hystrix: stream: enabled: true
Dashboard będzie dostępny pod: http://localhost:8080/hystrix
Najlepsze praktyki
### Fallback strategies:
1. **Cache fallback** – zwróć dane z local cache
2. **Default values** – ustaw rozsądne wartości domyślne
3. **Queue for later** – odłóż żądanie do kolejki
4. **Alternative service** – użyj backup service
@Service public class UserService { @Autowired private UserCache userCache; @HystrixCommand(fallbackMethod = "getUserFromCache") public User getUser(Long userId) { return restTemplate.getForObject("/api/users/" + userId, User.class); } public User getUserFromCache(Long userId) { User cachedUser = userCache.get(userId); if (cachedUser != null) { return cachedUser; } // Zwróć podstawowe informacje gdy brak cache return User.builder() .id(userId) .name("User " + userId) .status("UNKNOWN_STATUS") .build(); } }
Testing Circuit Breaker
Test jednostkowy Circuit Breaker z mockowanym service:
@RunWith(SpringRunner.class) @SpringBootTest public class PaymentServiceTest { @Autowired private PaymentService paymentService; @MockBean private RestTemplate restTemplate; @Test public void shouldCallFallbackWhenServiceFails() { // Given PaymentRequest request = new PaymentRequest("123", 100.0); when(restTemplate.postForObject(anyString(), any(), eq(PaymentResult.class))) .thenThrow(new RuntimeException("Service unavailable")); // When PaymentResult result = paymentService.processPayment(request); // Then assertThat(result.getStatus()).isEqualTo("DEFERRED"); assertThat(result.getMessage()).contains("temporarily unavailable"); } }
Circuit Breaker otwiera się gdy procent błędów w oknie czasowym przekroczy próg (domyślnie 50%) i liczba requestów przekroczy minimum (domyślnie 20 wywołań).
Tak, Hystrix obsługuje wywołania asynchroniczne przez @HystrixCommand z commandKey i obsługę CompletableFuture.
Bulkhead pattern izoluje różne wywołania używając oddzielnych thread pools, aby awaria jednego service nie wpływała na inne.
Użyj commandKey w @HystrixCommand i skonfiguruj osobne właściwości dla każdego klucza w application.yml.
Hystrix dodaje ~1-2ms overhead per wywołanie, ale zapobiega kaskadowym awariom które kosztowałyby znacznie więcej.
Użyj Hystrix Dashboard, logi aplikacji i metryki. Sprawdź czy parametry (thresholds, timeouts) są odpowiednio skonfigurowane.
Przydatne zasoby:
- Spring Cloud Circuit Breaker Documentation
- Netflix Hystrix GitHub
- Martin Fowler – Circuit Breaker Pattern
- Resilience4j Documentation
🚀 Zadanie dla Ciebie
Stwórz prostą aplikację z dwoma microservices: OrderService i PaymentService. Zaimplementuj Circuit Breaker w OrderService który wywołuje PaymentService. Przetestuj różne scenariusze awarii i zobacz jak działa fallback. Skonfiguruj Hystrix Dashboard i obserwuj metryki w czasie rzeczywistym.
Masz pytania o implementację Circuit Breaker w Twoim projekcie? Podziel się swoimi doświadczeniami w komentarzach!