목차
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
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. 참고
'스터디 > Spring' 카테고리의 다른 글
[Spring] @JsonProperty와 @SerializedName (0) | 2023.08.19 |
---|---|
[Springboot] CircuitBreaker 적용방법(2) - 코드 적용 (0) | 2023.08.18 |
[Springboot] CircuitBreaker란 뜻 의미 (0) | 2023.08.17 |
[Springboot] @Scheduled cron 사용하는 방법 (0) | 2023.08.12 |
[Spring] Spring 프로젝트에서 리소스 파일 읽기 (Java8) (0) | 2023.08.11 |
댓글