Circuit Breaker

Panda·2024년 2월 22일

Server

목록 보기
2/5

주식에서 부르는 서킷 브레이커만 알고 있었다가
이번에 서킷 브레이커 도입할 예정이라서

개념을 공부해보려고 합니다.

Circuit Breaker 패턴

서비스를 운영하게 되면 장애는 필연적이자 극복해야할 문제입니다.
이러한 장애를 극복하기 위해서 나온 하나의 패턴입니다.

서킷 브레이커의 목적은 장애가 발생했을 때 다른 서비스로까지 장애가 전파되는 것을 막는 역할을 합니다.

서킷 브레이커의 개념은 이름 그대로 실제 회로 차단기에서부터 왔는데요

  • 회로 차단기 구조
    전류가 계속 흐르게되면 과부하 문제가 생길 수 있기때문에
    문제가 생기면 전류가 흐르지않게 하여 해당 문제를 방지할 수 있습니다.

동작 원리

서킷 브레이커 상태

  • Close : 정상 상태
  • Half Open : Open 상태가 발생한 이후 일정 시간이 지난 상황
  • Open : 장애가 발생한 상황

서킷 브레이커 상태 변화

  1. 평소처럼 Close 상태였다가 에러가 발생 (Open으로 상태 전이)
  2. Open 상태 요청을 차단 중이였다가 일정 시간이 흐름 (Half Open으로 상태 전이)
  3. Half Open 상태에서 일부적으로 허용된 요청들에 대해 성공하면 Close를 아니라면 다시 Open 상태로 변경

에러(장애) 판단 기준

  • slow call: 기준 시간보다 오래 걸린 요청
  • failure call: 오류 응답받은 요청

서킷 브레이커 규칙을 만들자

  • 특정 요청이 10번 연속 실패할 경우 API 요청을 차단
  • 특정 요청이 5번 연속 20초 이상 Timeout 발생 할 경우 API 요청을 차단
  • 차단했던 요청이 3번 연속 성공 할 경우 Close 상태로 변화
  • Open 상태에서 30초 이상이 지날 경우 Half Open 상태로 변화

위 규칙처럼 서비스 내 저희가 원하는 서킷 브레이커 규칙을 세울 수 있습니다.

왜 써야할까?

서킷 브레이커 목적에 왜 써야하는지 이유가 나와있지만
로드밸런싱 기능이랑 헷갈린 저를 위해 한번 정리해보았습니다.

장애발생에 대한 개념을 제대로 이해못했었는데
로드밸런싱은 서버가 죽었을 때 알아서 요청을 분배해 주는 기능을
'장애에 대해 처리를 해주고있는데 왜 서킷 브레이커를 사용해야하나?' 라고 생각했습니다...

서버가 죽는 것도 당연히 장애의 일종이긴 하지만
로드밸런서는 서버 요청을 분배하는 것을 해주지 slow call, failure call에 대한 특수 처리까지는 해주지 않습니다.

따라서 제가 이해한 서킷 브레이커 장애 처리 기능은 밑에와 같습니다.

  • 서비스 응답이 느림 [slow call]
  • 특정 API 요청이 계속 실패 [failure call]

Resilience4J

그러면 스프링에서 이러한 서킷 브레이커를 어떻게 구현해 볼 수 있을까요??

Spring Cloud Hystrix라는 프로젝트가 있긴한데 현재 지원 중단이라
해당 프로젝트에서 영감을 받아 개선해서 나온 Resilience4J를 알아볼까 합니다.

서킷 브레이커는 API 호출 결과를 통계를 내고있는데 Sliding Window라고 합니다.
Sliding Window 종류에는

  • Count Based Sliding Window
    N개 요청 횟수를 통계를 집계합니다.

  • Time Based Sliding Window
    N초 동안 일어난 API 호출 결과를 집계합니다.

Spring Gateway에서 fallbackUri 설정

spring.cloud.gateway: 
  routes:
  - id: consumer-circuit-breaker
    uri: lb://consumer 
    predicates: 
    - Path=/cb/**
    filters: 
    - RewritePath=/.*/(?<param>.*), /delay/${param} 
    - name: CircuitBreaker
      args: 
        name: mycb
        # fallback은 Circuit 상태와 상관 없이, fail조건에 해당된 경우 호출됨 
        # 직접 fallback API 구현 가능합니다.
        fallbackUri: forward:/fallback    
    metadata:
      connect-timeout: 2500
      response-timeout: 2500
서킷 브레이커 규칙 설정

resilience4j:
  circuitbreaker:
    default:
      slidingWindowType: COUNT_BASED           # default: COUNT_BASED 
      slidingWindowSize: 10                    # 통계 건수
      minimumNumberOfCalls: 5                  # 최소요청횟수
      failureRateThreshold: 50                 # 실패율
      waitDurationInOpenState: 30000           # 서킷 브레이커 유지 시간
      
# 최근 10개 요청 중 응답속도가 1초 초과한 비율이 50% 이상일때 서킷 브레이커 OPEN
# 5개 요청까지는 서킷 브레이커 OPEN 하지 않습니다.

이 외에도 다양한 설정 값들이 있는데 필요할 때 마다 공식문서 살펴보면 될 것 같습니다.

Resilience4J의 아쉬운점은 자체는 대쉬보드를 지원하지 않아서 시각적으로 확인이 어려운데요.
대신에 metrics 정보들은 제공을 하기 때문에 프로메테우스, 그라파나를 이용하여 대쉬보드 구성 설정은 가능합니다.

느낀 점

조만간 Spring Gateway에서 해당 서킷 브레이커를 구축할 것 같은데
장애 해결하는 방식을 많이 알아가는 것 같아서 좋은 공부였던 것 같습니다.

오히려 서킷 브레이커 잘못 설정했다가 서비스 통신 아예안되는 건 조심하면서 구성을 해야겠네요

참조

profile
실력있는 개발자가 되보자!

0개의 댓글