본문 바로가기
스터디/Spring

[Springboot] CircuitBreaker 적용방법 (1) - Resilience4j

by zoodi 2023. 8. 18.
728x90

목차

     

     

    1.  CircuitBreaker 적용 방법

    circuitbreaker는 라이브러리를 통해 적용이 가능합니다.

    circuitbreaker를 제공하는 라이브러리는 아래와 같이 크게 3가지 종류가있습니다.

     

    구분 Resilience4j Netflix Hystrix Sentinal
    Home https://github.com/resilience4j/resilience4j https://github.com/Netflix/Hystrix https://github.com/alibaba/Sentinel
    라이센스 Apache License 2.0 Apache License 2.0 Apache License 2.0
    특징 Light Weight, dependency 적음
    Java 8 Fuctional Interface로 구현됨
    actuator 통한 모니터링
    RateLimiter, TimeLimiter, BulkAhead 등의 추가 기능 제공
    가장 오래된 검증된 라이브러리
    (더이상 기능 추가 없이 유지보수만 한다고 함)
    dependency 많음
    Annotation 으로 적용 가능함
    near real-time 모니터링
    분산 시스템을 위한 다양한 기능 제공
    모니터링 Dashboard 지원

    (출처: Circuit Breaker Java Library)

     

    • Drive dev에서는 Java Resilience4를 적용하여 개발 완료 및 개발 가이드 제공
    • Netflix Hystrix는 2018년 개발 중단하고 유지보수 상태
      • Resilience4j가 권장되는 상태 
      • SpringBoot 2.4.x 부터는 더 이상 지원하지 않음 
    • Hystrix는 java6 기반, resilience4j는 java8 기반, Hystrix와는 다르게 다른 라이브러리의 의존성이 없어 가벼움
    • Java Resilience4j

    Netfilx Hystrix는 더이상 기능 추가 없이 유지보수만 진행하고 공식 문서에서도 Resilience4j를 사용할 것을 권장하고있습니다.

    따라서 할 일에서는 Resilience4j를 사용하여 circuitbreaker를 적용하였습니다.

    2. Resilience4j 모듈 종류

    resilience4j에서 제공하는 코어 모듈은 위와 같습니다. 코어 모듈들은 모두 resilience4j-core 모듈을 참조합니다.

    resilience4j를 사용하기위한 spring 관련 라이브러리를 spring이 제공하지 않고 resilience4j가 제공해줍니다.

    resilience4j-spring-boot2는 resilience4j-spring을 참조하고, resilience4j-spring은 resilience4j-framework-common을 참조합니다.

    설정 정보에 대한 구성도 동일하게 상위 모듈의 class를 확장해서 쓰는 형태입니다.

    얘를 들어 CircuitBreakerProperties 는 다음과 같이 구성되어있습니다.

     

    >> 자세한 내용은 https://luvstudy.tistory.com/150 참고

    3. Springboot 적용방법

    3.1 환경

    • springboot-2.6.7
    • java8
    • resilience4j-1.7.1
      • v2.0.0 이 가장 최신 stable 버전이나 java17 기준 

    >> https://resilience4j.readme.io/docs

    3.2 gradle 설정

    dependencies {
    	... 
    	// resilience4j springboot dependency
    	implementation 'org.springframework.boot:spring-boot-starter-aop'
    	implementation 'io.github.resilience4j:resilience4j-spring-boot2:${resilience4jVersion}'
    
    	// springboot monitoring dashboard
    	implementation 'org.springframework.boot:spring-boot-starter-actuator'
    	implementation 'io.micrometer:micrometer-registry-prometheus'
    }

    참고: https://resilience4j.readme.io/docs/gradle

     

    Gradle

    Getting started with Gradle

    resilience4j.readme.io

    3.3 application.yml

    resilience4j:
      retry:
        configs:
          default:
            maxRetryAttempts: 5 #최대 재시도 수
            waitDuration: 5000  # 재시도 사이에 고정된 시간 [ms]
        instances:
          retry-test-3000: # retry name
            baseConfig: default # 기본 config 지정 (Ex-retry.configs.{default})
            waitDuration: 3000
      circuitbreaker:
        configs:
          default:  #기본 config name
            slidingWindowType: COUNT_BASED
            slidingWindowSize: 100
            minimumNumberOfCalls: 100 #최소한 호출을 100번 기록해야 실패 비율을 계산할 수 있다.
            permittedNumberOfCallsInHalfOpenState: 10
            waitDurationInOpenState: 30s #서킷 상태가 open에서 half-open으로 변경되기전에 circuit breaker가 기다리는 시간(s)
            recordFailurePredicate: com.hello.circuitbreak.circuitbreaker.DefaultCircuitBreakerRecordFailurePredicate
            registerHealthIndicator: true
        instances:
          contact: # circuitbreaker name
            baseConfig: default  # 기본 config 지정
            failureRateThreshold: 90
            slowCallRateThreshold: 80
            slowCallDurationThreshold: 800ms  #응답 시간이 느린것으로 판단 할 기준 시간(ms)
            recordFailurePredicate: com.hello.circuitbreak.circuitbreaker.DefaultCircuitBreakerRecordFailurePredicate

     

    • retry: 실패한 실행을 짧은 지연 시간을 가진 후 재시도하는 매커니즘. springboot 환경에서 사용하기위해 의존성 추가 필요 → Drive dev에서는 설정하지않음
    • circuit breaker: 실패 횟수가 기준치를 넘은 경우 circuit을 열어 일정 기간동안 해당 메서드를 실행되지 않고 바로 실패하게 해주는 패턴
      • 기본적으로 슬라이딩 윈도우를 사용하여 호출 결과를 저장 및 집계하여 circuit을 열거나 닫음
      • 횟수 기반 슬라이딩 윈도우 (count-based sliding window) : N크기의 circuit array 만들어서 해당 array의 실패율을 이용하여 circuit 상태를 확정한다. 상태 확인하는데 걸리는 시간은 O(1)이며 메모리 소비는 O(N)
      • 시간 기반 슬라이딩 윈도우 (time-based sliding window): N초의 슬라이딩 윈도우라면 N개의 circuit array를 만든다. 그리고 각 버킷에 특정 초에 발생한 호출 결과를 집계 및 저장하고, 이를 초가 지남에 따라 밀어내고 가지는 형식. N초가 지나기 시작하면 가장 오래된 버킷은 제거되고 총 집계는 새롭게 이루어짐. 집계는 실패한 호출 수, 느린 호출 수, 총 호출 수 3가지를 가진다. 
        별도 집계를 하고 결과를 가지고있어 상태 확인은 O(1), 메모리는 부분집계가 O(N), 총 집계가 O(1)이다.
    • instances: 특정 인스턴스를 name으로 구분하여 설정값 커스텀 가능, 어노테이션의 name 값
    • CircuitBreakerRegistry는 설정값을 저장하는 인메모리 저장소라고 생각하면된다. 위 예시 코드에서는 default 설정값 세트를 저장해두고 이 값들을 이용해 contact라는 이름의 서킷 브레이커 인스턴스를 생성한다 라고 이해하면 된다.

    3.4 application.properties

    circuitbreaker.configs.default.slidingWindowType=COUNT_BASED
    circuitbreaker.configs.default.slidingWindowSize=100
    circuitbreaker.configs.default.minimumNumberOfCalls=100
    circuitbreaker.configs.default.waitDurationInOpenState=PT30S
    circuitbreaker.configs.default.permittedNumberOfCallsInHalfOpenState=10
    circuitbreaker.configs.default.recordFailurePredicate=com.hello.circuitbreak.circuitbreaker.DefaultCircuitBreakerRecordFailurePredicate
    
    
    circuitbreaker.instances.contact.waitDurationInOpenState=PT10S
    circuitbreaker.instances.contact.permittedNumberOfCallsInHalfOpenState=4
    circuitbreaker.instances.contact.failureRateThreshold=90
    circuitbreaker.instances.contact.slowCallRateThreshold=70
    circuitbreaker.instances.contact.slowCallDurationThreshold=PT3S
    circuitbreaker.instances.contact.recordFailurePredicate=com.hello.circuitbreak.circuitbreaker.ContactCircuitBreakerRecordFailurePredicate
    
    ...

     

    4. 참고

    https://luvstudy.tistory.com/150

    https://bkjeon1614.tistory.com/711

    728x90

    댓글