Resilience4j 라이브러리를 사용하여 서킷 브레이커를 적용하는 방법에 대해 알아보자.
Resilience4j는 함수형 프로그래밍으로 설계된 경량 장애 허용 라이브러리로, 서킷 브레이커 패턴을 위해 사용된다. 서킷 브레이커 라이브러리에는 Hystrix도 있는데, Hystrix와 달리 Resilience4j는 다른 라이브러리의 의존성이 없어 가볍기 때문에 Resilience4j를 사용하였다. 참고로 Resilience4j는 CircuitBreaker이외에도 TimeLimiter, Retry등과 같은 다양한 장애 대응 패턴을 제공한다.
implementation 'io.github.resilience4j:resilience4j-spring-boot3:2.2.0'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'io.github.resilience4j:resilience4j-circuitbreaker:2.2.0'
// implementation 'io.github.resilience4j:resilience4j-timelimiter:2.2.0'
// implementation 'io.github.resilience4j:resilience4j-retry:2.2.0'
timelimiter와 retry도 필요하다면 추가해서 사용하면 된다.
resilience4j:
circuitbreaker:
configs:
default:
registerHealthIndicator: true
slidingWindowType: TIME_BASED
slidingWindowSize: 10
minimumNumberOfCalls: 10
slowCallRateThreshold: 100
slowCallDurationThreshold: 60000
failureRateThreshold: 50
permittedNumberOfCallsInHalfOpenState: 10
waitDurationInOpenState: 10s
instances:
searchProductCircuitBreaker:
baseConfig: default
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include:
- "*"
health:
circuitbreakers:
enabled: true
@CircuitBreaker(name = "searchProductCircuitBreaker", fallbackMethod = "fallback")
public String searchProduct(String query, int display) {
String text = URLEncoder.encode(query, StandardCharsets.UTF_8);
String apiURL = "https://openapi.naver.com/v1/search/shop.json?query=" + text + "&display=" + display;
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(apiURL))
.header("X-Naver-Client-Id", clientId)
.header("X-Naver-Client-Secret", clientSecret)
.GET()
.build();
...
}
public String fallback(String query, int display, Throwable t) {
return "Fallback! exception type: " + t.getClass() + ", message: " + t.getMessage();
}
@CircuitBreaker
어노테이션을 작성하여 application.yml에서 선언한 "searchProductCircuitBreaker" 인스턴스 명을 삽입한다.요청 실패 비율이 임계치를 넘어가면 다음과 같이 에러 메시지가 뜨면서 서킷 브레이커가 OPEN 상태가 된다.
{domain}/actuator/health 엔드포인트를 통해 서킷 브레이커의 상태를 확인할 수 있다.
{domain}/actuator/circuitbreakerevents에서는 각각의 요청에 대한 상세한 로그를 볼 수 있다.
서킷 브레이커를 적용할 때 application.yml 파일에서 show-details: always
로 설정했음에도 불구하고 서킷 브레이커의 세부사항들이 보이지 않는 문제가 발생했었다. 알고 보니 resilience4j의 버전 문제였다. 만약 같은 오류가 발생했다면 공식 문서에서 안정화된 최신 버전을 사용해보길 바란다.