Circuit Breaker

· 4분 읽기

MSA 에서 하나의 서비스 장애가 전체 시스템으로 전파되는 것을 Cascading Failure 라 한다. Circuit Breaker는 이를 방지하는 패턴이다.

Circuit Breaker 는 원래 주식시장에서 주가가 급락할 때 시장에 미치는 충격을 완화하기 위해 매매를 일시적으로 중단하는 ‘비상 브레이크’ 장치로 알려져있다.

엔지니어링에서는 다른 뜻으로 사용된다.

다음과 같이 MSA에서 서비스 A가 서비스 B를 호출하는 상황을 가정해보자.

flowchart LR
    A[Service A] -->|호출| B[Service B]
    B -->|응답 지연/실패| A
    A -.->|스레드/커넥션 고갈| A
    A -.->|연쇄 장애| C[Service C]
    A -.->|연쇄 장애| D[Service D]

서비스 B가 응답하지 않으면 다음과 같은 일들을 예상해볼수 있다.

  1. A의 호출 스레드가 응답을 기다리며 대기 상태에 빠진다

  2. 대기 중인 요청이 쌓이면서 A의 스레드 풀, 커넥션 풀이 고갈된다

  3. A에 의존하는 다른 서비스(C, D)도 연쇄적으로 장애가 발생한다

  4. 사용자가 재시도를 반복하면 상황이 더 악화된다 (retry storm)

Retry Storm 에 대해서는 별도의 글에서 어떤 전략을 사용해야 하는지 다룬다.

Circuit Breaker는 이 체인을 끊는다.

  • 장애 서비스로의 요청을 즉시 차단하여 리소스 고갈을 방지한다

  • 빠른 실패(Fail Fast) 로 응답 시간을 보장한다

  • 장애 서비스에 추가 부하를 주지 않아 회복 시간을 확보해준다

즉 써킷 브레이커는 장애가 전파되는것을 막아주는 긴급 브레이크다.

Circuit Breaker 의 상태

Circuit Breaker는 전기 회로의 차단기처럼 세 가지 상태를 순환한다.

stateDiagram-v2
    [*] --> Closed
    Closed --> Open : 실패율 ≥ 임계값
    Open --> HalfOpen : 대기 시간 경과
    HalfOpen --> Closed : 시험 요청 성공
    HalfOpen --> Open : 시험 요청 실패

Open 이 차단된 상태이고 Closed 가 정상인 상태임에 유의하자!

Closed (정상)

  • 모든 요청이 정상적으로 통과한다

  • 실패 횟수/비율을 슬라이딩 윈도우로 추적한다

  • 실패율이 임계값을 넘으면 Open 으로 전환된다

Open (차단)

  • 모든 요청을 즉시 거부한다 (원격 호출 없이 에러 반환)

  • 장애 서비스를 격리하여 회복 시간을 확보한다

  • 설정된 대기 시간(timeout)이 경과하면 → Half-Open 전환

Half-Open (테스트)

  • 제한된 수의 시험 요청만 통과시킨다

  • 시험 요청이 성공하면 → Closed 전환 (복구 완료됨)

  • 시험 요청이 실패하면 → Open 전환 (아직 복구하면 안됨)

Half-Open은 복구 중인 서비스에 갑작스러운 트래픽 폭주를 방지하는 역할도 한다.

보통은 Sliding Window 알고리즘을 사용하게 된다.

트래픽이 낮은 서비스일수록 최근 N초간의 호출 결과를 집계하는 Time-based 방식이 좋다.

트래픽이 높은 서비스일수록 최근 N건의 호출 결과를 집계하는 Count-based 방식이 좋다.

Istio 와 함께하기

Istio 와 같은 서비스 메시에서 인프라 수준으로 이를 달성하는 방식이 가장 많이 쓰이고, 또 간단하다.

Istio Outlier Detection:

  • Envoy 프록시가 각 서비스 인스턴스의 상태를 자동 추적한다

  • 연속 에러, 레이턴시 등의 메트릭을 분석한다

  • 기준을 초과하는 인스턴스를 로드 밸런싱 풀에서 자동 제외(eject) 한다

  • Panic Mode: 너무 많은 인스턴스가 제외되면 헬스체크를 무시하고 모든 인스턴스로 라우팅한다

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: soobook
spec:
  host: "soobook.io"
  trafficPolicy:    
    outlierDetection:
      consecutive5xxErrors: 7
      baseEjectionTime: 3m
... 

Circuit Breaker, Retry, Bulkhead

이 세 패턴은 상호 배타적이지 않으며, 함께 사용하는 것이 일반적이다.

패턴목적대상 장애적용 위치
Retry일시적 장애를 재시도로 극복네트워크 글리치, DB 락 경합호출자
Circuit Breaker지속적 장애를 감지하고 차단서비스 다운, 장기 응답 불능호출자
Bulkhead리소스 격리로 장애 전파 방지리소스 고갈호출자
flowchart LR
    Request --> BH[Bulkhead<br/>리소스 격리]
    BH --> CB[Circuit Breaker<br/>장애 감지/차단]
    CB --> RT[Retry<br/>재시도]
    RT --> TO[Timeout<br/>시간 제한]
    TO --> Service[Application]

동작 흐름:

  1. Bulkhead가 전용 리소스 풀에서 요청을 처리한다

  2. Circuit Breaker가 열려있으면 즉시 실패한다

  3. Closed 상태면 Retry가 일시적 장애 시 재시도한다

  4. Timeout이 개별 호출의 최대 대기 시간을 제한한다

Rate Limiter와의 차이: Rate Limiter는 수신 요청 속도를 제한하는 피호출자 보호 패턴이고, Circuit Breaker는 발신 요청의 장애를 감지하는 호출자 보호 패턴이다.

References