CircuitBreaker Pattern 이란

devswansong·2024년 9월 7일

CircuitBreaker Pattern 이란

CircuitBreaker 는 쉽게 말해 분산 시스템에서 서비스 간 통신의 안정성을 높이기 위한 디자인 패턴입니다.


CircuitBreaker 가 필요한 상황

마이크로서비스 아키텍처가 널리 사용되는 현대의 시스템 환경에서, 서비스 간 의존성으로 인한 문제가 발생할 수 있습니다.

예를 들어, Payment Server 가 Bank Server 에 요청을 보내지만 Bank Server 에 문제가 발생하여 정상적은 응답을 받기 어려운 상황이라 가정해보겠습니다.
이 경우 Payment Server 는 응답을 받지 못하고, 이를 해결하기 위해 재시도(Retry) 메커니즘을 사용할 수 있습니다. Payment Server 는 정상적인 응답을 받을 때까지 장시간 대기하며 계속해서 요청을 보낼 수 있습니다. 그러나 이러한 행동은 오히려 Bank Server 의 부하를 가중시키고, 문제를 더욱 심화시킬 수 있습니다. Bank Server 는 쌓이는 요청을 제대로 처리하지 못한 채 과부하 상태에 빠지게 되어, 결과적으로 문제의 근본적인 해결이 더욱 어려워집니다.

이러한 상황은 DB, Redis, Kafka 와 같은 외부 시스템과의 통신에서도 발생할 수 있습니다. 이들 외부 시스템에 문제가 발생했을 때, 지속적인 요청은 시스템의 회복을 방해할 수 있습니다.

이러한 문제를 해결하기 위해 CircuitBreaker Pattern 이 사용됩니다.


CircuitBreaker 의 장점

  • 비정상 응답 반환이 예상될 때 비정상 시스템에 요청없이 빠르게 비정상 응답을 반환해 전체적인 처리시간을 향상시킵니다.
  • 비정상 응답 뿐만 아니라 기본값이나 fallback 정책에 따라 유연한 대처가 가능합니다.
  • 비정상 시스템에 회복을 위한 리소스 보장을 할 수 있습니다.
  • 이러한 중간에서 끊어주는 역할로 예외의 전파를 막아줄 수 있습니다.
  • CircuitBreaker 의 상태는 모니터링 분석에 유리합니다.

CircuitBreaker 의 메커니즘

상태

  • CLOSED : CircuitBreaker 가 닫혀 정상적으로 요청할 수 있음을 나타냅니다.
  • OPEN : CircuitBreaker 가 작동하여 접근을 차단합니다.
  • HALF_OPEN : 일부 요청만을 허용해 CLOSED, OPEN 상태를 결정합니다.

내부 동작

Resilience4j CircuitBreaker 의 컨셉을 참고했습니다.

sliding window

상태 판단을 위한 정보(지표) 수집 방식으로 sliding window 를 사용합니다. 구체적으론 두 방식으로 나뉩니다.

  • Count-based sliding window :
    최근 호출된 N 개의 호출 결과를 집계하여 상태를 판단합니다.
    순환 배열로 구현되며 새로운 결과가 추가될 때마다 총 집계를 최신화합니다.
    스냅샷 검색 시간은 O(1)로 일정하며 메모리 사용량은 O(N) 입니다.

  • Time-based sliding window :
    특정 시간 범위 내의 호출 결과를 집계하여 상태를 판단합니다.
    N 개의 부분 집계(버킷)로 구성된 순환 배열로 구현되며 각 버킷은 1초 동안의 모든 호출 결과를 집계합니다.
    가장 오래된 버킷이 제거될 때, 해당 버킷의 부분 집계를 총 집계에서 뺍니다(Subtract-on-Evict).
    스냅샷 검색 시간은 O(1)로 일정하며, 메모리 사용량은 O(N)입니다.

Failure rate and slow call rate thresholds

상태 판단 근거와 관련된 내용입니다.

이 상태는 failure rateconfigurable threshold(failureRateThreshold) 값보다 크거나 같을 때 CLOSED 에서 OPEN 으로 변경합니다. (설정한 실패율 값 이상의 실패율이 측정되면 CircuitBreaker 가 발동됩니다. 상태 OPEN)

기본적으로 대부분의 예외는 실패로 다루며 제외대상을 정할 수도 있습니다.

실패율 말고도 slow call (느린 응답) 이 configurable threshold(callRateThreshold) 값보다 크거나 같을 때 CLOSED 에서 OPEN 으로 변경합니다.

따라서 sliding window 자료구조엔 실패한 호출 수, 느린 호출 수, 총 호출 수, 총 호출 시간 같은 값들을 저장해야합니다.

(원문 : A partial aggregation consists of 3 integers in order to count the number of failed calls, the number of slow calls and total number of calls. And one long which stores total duration of all calls.)

이렇게 OPEN 상태가 된 경우 대기시간이 지난 뒤 HALF_OPEN 상태가 되어 일부 요청을 허용한 뒤 총 집계를 비교하여 Threshold 보다 적어진다면 CLOSED 상태로 변경됩니다.


Opensource

Hystrix

Netflix 에서 공개한 Latency, Fault Tolerance(내성) 문제를 해결하기 위한 오픈소스 라이브러리.

현재는 추가적인 개발이 없으며 resilience4j 를 사용하길 권장하고 있습니다. 하지만 Hystrix wiki 에서 제공하는 flow chart 가 좋아보여 가져왔습니다.

사진 출처

자세한 사용 정보는 다음 글을 참고해주세요.
G마켓 테크 블로그

Resilience4j

Latency, Fault Tolerance 를 위한 오픈소스 라이브러리입니다. (최신 Release, on Jun 29, 2023)
CircuitBreaker 뿐만 아니라 Bulkhead, Ratelimiter 같은 다양한 기능들을 제공합니다.

세부적인 동작방식은 위쪽 메커니즘 부분에서 나왔지만 Resilience4j 에선 OPEN, CLOSED, HALF_OPEN 상태 말고도 DISABLED, FORCED_OPEN 이란 추가 상태가 존재합니다.

  • DISABLED : 모든 요청을 허용합니다.
  • FORCED_OPEN : 모든 요청을 거부합니다.
    • 공통점 : 지표로써 수집되지 않으며 상태에서 벗어나기 위해선 상태전환을 트리거하던가 CircuitBreaker 를 초기화해야합니다.

Resilience4j 의 CircuitBreaker 가 어떻게 thread-safe 를 유지하는지는 공식문서를 참고해주세요.

사용 정보는 다음 글을 참고해주세요.
올리브영 테크 블로그





분산환경에서 취약한 Latency, Fault 문제를 해결하는 방식은 CircuitBreaker 뿐만 아니라 Bulkhead, Ratelimiter, Retry, Fallback 같은 개념들이 있습니다. 이러한 개념들도 조금씩 정리해나가면 좋을 것 같습니다.




참고한 자료

https://github.com/Netflix/Hystrix/wiki/
https://resilience4j.readme.io/docs/circuitbreaker
https://dip-mazumder.medium.com/best-practices-for-error-handling-a-guide-to-circuit-breaker-patterns-41d45ffc02ac
https://dev.gmarket.com/40

profile
unagi.zoso == ziggy stardust == devswansong

0개의 댓글