앞으로 구현할 CircuitBreaker 개요입니다.
CircuitBreaker는 장애가 발생하는 서비스에 반복적인 호출이 되지 못하도록 차단하는 기능을 합니다. 대신에 다른 기능을 수행하게 하여 장애를 회피합니다.
현상
어떤 현상인지 확인해보겠습니다. 사용자는 자신이 주문한 상품을 조회하려는 상황입니다. 그런데 Order 서비스에 문제가 발생한 상황입니다.
Postman에서는 아래와 같이 500이 나타나고 있습니다.
애플리케이션에서 보니, 'UnknownHostException'이 발생했습니다.
요약
Resilliance4J Dependency 추가
CircuitBreaker Config 수정
CircuitBreaker 추가
소스코드
User Service에서 Order Service를 호출하고 있습니다. 문제가 발생하면 User Service에서 응답을 주어야 하기 때문에 CircuitBreaker는 User Service에 추가합니다.
pom.xml에 Dependency를 추가합니다.
<!-- resilience4j -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
CircuitBreaker의 Configuration을 수정할 수 있습니다. config 패키지를 만들고, Resilience4JConfig.java를 만들어 줍니다.
/**
* Resilience4J의 Circuit Breaker Config를 수정
*/
@Configuration
public class Resilience4JConfig {
// Customize하기 원하는 것을 <>에 넣어는다.
// UserServiceImpl에서 CircuitBreakerFactory를 수정해서 사용하기 위해서 아래와 같이 수정
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> globalCustomConfiguration() {
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(4) // CircuitBreaker를 열지 결정하는 Threshold. default 50
.waitDurationInOpenState(Duration.ofMillis(1000)) // CircuitBreaker를 open한 상태로 유지하는 지속 시간. default 60s
.slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED) // CircuitBreaker가 닫힐 때 통화 결과를 기록하는데 사용되는 슬라이딩 창의 유형. 카운트 기반 또는 시간 기반
.slidingWindowSize(2) // CircuitBreaker가 닫힐 때 호출 결과를 기록하는데 사용되는 슬라이딩 창의 크기. default 100
.build();
// TimeLimiter는 future supplier의 time limit를 정하는 API
TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(4)) // default 1s
.build();
// factory를 반환할 것인데 -> 그 factory의 설정은 이렇다.
return factory -> factory.configureDefault(id ->
new Resilience4JConfigBuilder(id)
.timeLimiterConfig(timeLimiterConfig)
.circuitBreakerConfig(circuitBreakerConfig)
.build());
}
}
Order Service를 호출하는 곳을 갑니다. 서비스 로직은 UserServiceImpl.java에서 수행되고 있습니다. 아래 내용을 추가합니다.
/* CircuitBreaker */
CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");
List<ResponseOrder> ordersList = circuitBreaker.run(() -> orderServiceClient.getOrders(userId),
throwable -> new ArrayList<>()); // run(호출 메소드, 에러나면 대처)
테스트
Order Service가 꺼져있는 상태에서 Postman으로 테스트를 해보겠습니다. 위에서는 500을 받았는데, 이제는 200과 빈 리스트를 받았습니다.
Order Service를 켜고 테스트 해보니, 아래와 같이 정상적으로 나오네요.
다시 꺼보니 아래와 같이 나옵니다.
끝.
'IT > Spring Cloud' 카테고리의 다른 글
모니터링 - Micrometer (0) | 2022.02.04 |
---|---|
Zipkin - 분산 추적 (0) | 2022.01.30 |
Apache Kafka 활용 (1) (0) | 2022.01.23 |
데이터 동기화 - Kafka 설정 (0) | 2022.01.08 |
Microservice간 통신 - FeignClient 방식 (0) | 2022.01.07 |