소개
서킷브레이커는 CLOSED, OPEN, HALF_OPEN 이라는 3개의 일반적인 상태들과 DISABLED, FORCED_OPEN이라는 2개의 특별한 상태들로 구성되어 있습니다.
출처 : Resilience4j 공식문서
서킷브레이커는 요청의 결과를 저장하고 집계하는데에 슬라이딩 윈도우를 사용합니다.
횟수 기반의 슬라이딩 윈도우와 시간 기반의 슬라이딩 윈도우 사이에서 선택할 수 있습니다.
횟수 기반의 슬라이딩 윈도우는 마지막 N개의 요청에 대한 결과를 집계합니다.
시간 기반의 슬라이딩 윈도우는 마지막 N초의 요청에 대한 결과를 집계합니다.
횟수 기반의 슬라이딩 윈도우
횟수 기반의 슬라이딩 윈도우는 N개 측정치의 원형 배열로 구현되어 있습니다.
만약 횟수 윈도우 사이즈가 10이면, 원형 배열은 항상 10개의 측정치만 갖고 있습니다.
슬라이딩 윈도우는 계속적으로 총 집계 결과를 업데이트합니다.
총 집계 결과는 새로운 요청의 결과가 기록됐을 때 업데이트 됩니다.
가장 오래된 측정치가 제거되면, 해당 측정값이 전체 집계에서 빼지고 버킷이 재설정됩니다. (제거시 빼기)
스냅샷은 미리 집계되어있고 윈도우 사이즈에 독립적이어서 스냅샷을 가져오는데 시간은 O(1)이 걸립니다.
이것의 공간 요구사항(메모리 소비)은 O(n)이 되어야 합니다.
시간 기반의 슬라이딩 윈도우
시간 기반의 슬라이딩 윈도우는 N개의 부분적 집계들(버킷들)의 원형 배열로 이루어져 있습니다.
만약 시간 윈도우의 사이즈가 10이면, 원형 배열은 항상 10개의 부분적 집계들(버킷들)만 갖고 있습니다.
각 버킷은 특정 에포크 초 동안 발생하는 모든 호출들의 결과를 집계합니다. (부분적 집계).
원형 배열의 가장 앞에 있는 버킷은 현재 에포크 초에 발생하는 요청의 결과들을 저장합니다.
다른 부분적 집계들은 이전 초 동안의 요청 결과들을 저장합니다.
슬라이딩 윈도우는 요청 결과들을 개별적으로 저장하지 않고 점진적으로 부분 집계들과 전체 집계를 업데이트합니다.
전체 집계는 새로운 요청 결과가 기록될 때 점진적으로 업데이트 됩니다.
가장 오래된 버킷이 제거되면, 해당 버킷의 부분적 총 집계는 총 집계에서 빼지고 해당 버킷은 초기화 됩니다. (제거시 빼기)
스냅샷은 미리 집계되어있고 시간 윈도우 사이즈에 독립적이기 때문에 스냅샷을 가져오는데는 O(1)이 걸립니다.
이것의 공간 요구사항 (메모리 소비)는 요청 결과들이 개별적으로 저장되지 않기 때문에 O(n)에 가까워야 합니다.
오직 N개의 부분적 집계들과 1개의 총 집계만 생성됩니다.
부분 집계는 3개의 정수로 구성됩니다. 실패한 요청수, 느린 요청수, 총 요청수를 세기 위함입니다.
그리고 모든 요청들의 총 응답시간을 기록하는 하나의 long값이 있습니다.
실패율 그리고 느린 요청 비율 임계값들
설정된 임계치보다 실패율이 같거나 크면 서킷브레이커의 상태는 CLOSED에서 OPEN으로 바뀝니다.
예를들어 기록된 요청들의 50% 초과가 실패했다고 가정해 보겠습니다.
기본적으로 모든 예외들은 실패로 카운트됩니다.
실패로 카운트할 예외들의 목록을 지정할 수 있습니다.
모든 다른 예외들은 성공으로 카운트됩니다.
예외들은 또한 무시되어 실패 또는 성공 그 어느것으로도 카운트되지 않을 수도 있습니다.
설정된 임계치보다 느린 요청들의 비율이 같거나 크면 서킷브레이커의 상태는 CLOSED에서 OPEN으로 바뀝니다.
예를들어 기록된 요청들의 50% 초과가 5초보다 길게 걸린 경우, 이 상태 전환은 외부 시스템이 실제 응답 불가 상태가 되기 전에 외부 시스템의 부하를 줄이는데 도움을 줍니다.
최소 요청수가 기록되어야 실패율과 느린 요청의 비율이 계산됩니다.
만약 최소로 요청해야 하는 요청의 수가 10이면, 실패율이 계산되기 전에 적어도 10개의 요청들이 기록되어야 합니다. 만약 9개의 요청들만 평가되었다면, 9개의 요청들이 모두 실패했더라도 서킷브레이커는 OPEN상태로 전환되지 않습니다.
서킷브레이커는 OPEN 상태일 때, CallNotPermittedException 예외로 요청을 거절합니다.
대기 시간이 지난 후에, 서킷 브레이커의 상태는 OPEN에서 HALF_OPEN으로 전환되고, 요청 대상 시스템이 요청을 소화할 수 있는지 없는지 확인하기 위해 설정된 수 만큼 요청을 허가합니다.
이 허가된 요청들이 모두 완료될 때 까지 이후의 요청들은 CallNotPermittedException 예외로 거절됩니다.
만약 설정된 임계치보다 실패율 또는 느린 응답률이 같거나 크면, 상태는 다시 OPEN으로 전환됩니다.
만약 설정된 임계치보다 실패율 또는 느린 응답률이 적으면, 상태는 CLOSED로 전환됩니다.
서킷브레이커는 2개의 추가적인 특별한 상태들을 지원하는데, DISABLED(항상 접근을 허가함)과 FORCED_OPEN(항상 접근을 거부함)입니다.
이 두 상태에서는 상태 전환과 별개로 서킷 브레이커 이벤트가 발현되지 않고 메트릭도 기록되지 않습니다.
이 두 상태들로부터 벗어나는 방법은 오직 서킷 브레이커를 리셋해서 상태를 전환시키는 것 뿐입니다.
서킷 브레이커는 쓰레드 세이프 합니다.
•
서킷브레이커의 상태는 원자적참조로 저장됩니다.
•
서킷브레이커는 사이드이펙트가 없이 원자적으로 상태를 업데이트 합니다.
•
슬라이딩 윈도우로부터 요청들을 기록하고 스냅샷을 읽는것은 동기적입니다.
이것은 한 번에 오직 하나의 쓰레드만 상태나 슬라이딩 윈도우를 업데이트 할 수 있고 원자성이 보장됨을 의미합니다.
하지만 서킷브레이커는 함수 호출을 동기화하지 않습니다. 이것은 함수 호출은 그 자체로 크리티컬한 부분이 아님을 의미합니다. 그렇지 않으면 서킷브레이커는 큰 성능저하와 병목현상이 발생합니다. 느린 함수 요청은 전체적인 퍼포먼스와 처리량에 큰 부정적 영향을 끼칩니다.
슬라이딩 윈도우 사이즈가 15더라도, 상태가 닫혀있다면, 만약 20개의 동시적인 쓰레들이 함수 실행을 위해 허가를 요청하면 모든 쓰레드들은 함수를 요청할 수 있습니다.
슬라이딩 윈도우는 오직 15개의 요청들만이 동시에 실행될 수 있음을 의미하지 않습니다.
만약 동시에 실행되는 쓰레드들의 수를 제한하고 싶다면, Bulkhead를 사용하십시오.
Bulkhead와 서킷브레이커는 함께 사용할 수 있습니다.
쓰레드가 1개일 때 :
출처 : Resilience4j 공식문서
쓰레드가 3개일 때 :
설정값
커스텀 설정 대상 | 설정 요소 | 기본값 | 설명 |
failureRateThreshold | 50 | 실패율 임계치를 퍼센테이지로 설정합니다. 실패율이 이 설정값보다 같거나 크면, 서킷브레이커는 OPEN상태로 전환됩니다. | |
slowCallRateThreshold | 100 | 임계값을 퍼센테이지로 설정합니다. 응답속도가 slowCallDurationThreshold 설정값보다 크면, 서킷브레이커는 그 요청을 느린 요청으로 간주합니다. 만약 느린 요청 비율이 이 설정값보다 같거나 크면, 서킷브레이커는 OPEN상태로 전환됩니다. | |
O | slowCallDurationThreshold | 60000 [ms] | 느린 요청으로 간주할 응답 시간 임계치입니다. 이 값보다 느린 응답은 느린 응답으로 간주됩니다. |
permittedNumberOfCallsInHalfOpenState | 10 | OPEN 상태에서 요청 대상 시스템이 정상화 되었는지 아닌지 확인하기 위해 허가할 요청의 수 입니다. | |
maxWaitDurationInHalfOpenState | 0 [ms] | HALF_OPEN 상태에서 OPEN상태로 전환하기 전에 대기할 최대 시간을 설정합니다. 값 0은 서킷브레이커가 HALF_OPEN 상태에서 모든 허가된 요청들이 성공되기 전까지 무한히 기다림을 의미합니다. | |
slidingWindowType | COUNT_BASED | 서킷브레이커가 CLOSED 상태일 때 요청의 결과를 기록하기 위한 슬라이딩 윈도우의 타입을 지정합니다. 슬라이딩 윈도우는 횟수 기반 또는 시간 기반으로 설정할 수 있습니다. 만약 슬라이딩 윈도우가 횟수 기반이라면, 마지막 slidingWindowSize 설정 개의 요청들이 기록되고 집계됩니다. 만약 슬라이딩 윈도우가 시간 기반이라면, 마지막 slidingWindowSize 초의 요청들이 기록되고 집계됩니다. | |
slidingWindowSize | 100 | 서킷브레이커가 CLOSED 상태일 때, 요청의 결과를 기록하는 슬라이딩 윈도우의 사이즈를 설정합니다. | |
minimumNumberOfCalls | 100 | 서킷브레이커가 실패율이나 느린 요청률을 계산하기 전에 필요한 최소한의 요청 수 입니다. 만약 이 값이 10이라면, 실패율이 계산되기 전에 10개의 요청이 기록되어야 합니다. 만약 오직 9개의 요청들만 기록되었고 9개의 요청들이 모두 실패라면, 서킷브레이커는 OPEN상태로 전환되지 않습니다. | |
waitDurationInOpenState | 60000 [ms] | OPEN에서 HALF_OPEN상태로 전환되기 전에 기다려야 하는 시간을 의미합니다. | |
automaticTransitionFromOpenToHalfOpenEnabled | false | 이 설정이 true로 설정된다면 서킷브레이커가 자동으로 OPEN에서 HALF_OPEN 상태로 전환되며 이 전환을 위해 어떤 요청도 필요하지 않음을 의미합니다. 한 개의 쓰레드는 waitDurationInOpenState 이 지난 OPEN 상태의 서킷 브레이커를 HALF_OPEN 상태로 전환하기 위해 생성되고 모든 서킷브레이커 인스턴스들을 모니터링합니다. 반면에, 만약 이 설정을 false로 설정한다면 waitDurationInOpenState 이 지나더라도 요청이 생겼을 때만 HALF_OPEN으로 전환됩니다. true 설정의 장점은 모든 서킷브레이커 인스턴스들의 상태를 모니터링할 쓰레드가 필요 없다는 점 입니다. | |
recordExceptions | empty | 실패로 간주할 예외들의 목록 입니다. 등록된 예외와 동일한 예외가 발생하거나 등록된 예외를 상속받은 예외가 발생하면, ignoreExceptions 설정으로 명시적으로 무시하지 않는 한 실패로 카운트 됩니다. 만약 이 목록을 설정하면, 다른 모든 예외들은 ignoreExceptions 설정으로 명시적으로 무시하지 않는 한 성공으로 간주됩니다. | |
ignoreExceptions | empty | 실패나 성공 둘 중 어느것으로도 기록되지 않을 예외들의 목록입니다. 등록된 예외와 동일한 예외가 발생하거나 등록된 예외를 상속받은 예외가 발생하면 recordExceptions 에 등록된 예외더라도 실패나 성공으로 간주되지 않습니다. | |
recordFailurePredicate | throwable -> true. By default all exceptions are recorded as failures. | 예외가 실패로 간주되어야 하는지 설정하는 Predicate입니다. 예외가 실패로 간주되려면 Predicate은 true를 반환해야 합니다. ignoreExceptions 에 등록되어 명시적으로 무시되지 않는 한 예외가 성공으로 간주되려면 Predicate이 false를 반환해야 합니다. | |
ignoreExceptionPredicate | throwable -> false. By default no exception is ignored. | 예외가 실패 또는 성공 그 어느것으로도 간주되지 않도록 하기위한 Predicate 입니다. 만약 예외가 무시되어야 하면 이 Predicate은 true를 반환해야 합니다. 만약 예외가 실패로 간주되려면 이 Predicate은 false를 반환해야 합니다. |