[TIL] 서킷 브레이커 (Resilience4j)

김건우·2024년 8월 2일

[TIL]

목록 보기
4/25

서킷 브레이커

  • 서킷 브레이커는 마이크로서비스 간의 호출 실패를 감지하고 시스템의 전체적인 안정성을 유지하는 패턴
  • 외부 서비스 호출 실패 시 빠른 실패를 통해 장애를 격리하고, 시스템의 다른 부분에 영향을 주지 않도록 한다.
  • 상태 변화: Closed -> Open -> Half-Open

Resilience4j

  • Resilience4j는 서킷 브레이커 라이브러리로, 서비스 간의 호출 실패를 감지하고 시스템의 안정성을 유지합니다.
  • 다양한 서킷 브레이커 기능을 제공하며, 장애 격리 및 빠른 실패를 통해 복원력을 높입니다.

Resilience4j의 주요 특징

  • 서킷 브레이커 상태: 클로즈드, 오픈, 하프-오픈 상태를 통해 호출 실패를 관리
    • 클로즈드(Closed):
      • 기본 상태로, 모든 요청을 통과시킵니다.
      • 이 상태에서 호출이 실패하면 실패 카운터가 증가합니다.
      • 실패율이 설정된 임계값(예: 50%)을 초과하면 서킷 브레이커가 오픈 상태로 전환됩니다.
      • 예시: 최근 5번의 호출 중 3번이 실패하여 실패율이 60%에 도달하면 오픈 상태로 전환됩니다.
    • 오픈(Open):
      • 서킷 브레이커가 오픈 상태로 전환되면 모든 요청을 즉시 실패로 처리합니다.
      • 이 상태에서 요청이 실패하지 않고 바로 에러 응답을 반환합니다.
      • 설정된 대기 시간이 지난 후, 서킷 브레이커는 하프-오픈 상태로 전환됩니다.
      • 예시: 서킷 브레이커가 오픈 상태로 전환되고 20초 동안 모든 요청이 차단됩니다.
    • 하프-오픈(Half-Open):
      • 오픈 상태에서 대기 시간이 지나면 서킷 브레이커는 하프-오픈 상태로 전환됩니다.
      • 하프-오픈 상태에서는 제한된 수의 요청을 허용하여 시스템이 정상 상태로 복구되었는지 확인합니다.
      • 요청이 성공하면 서킷 브레이커는 클로즈드 상태로 전환됩니다.
      • 요청이 다시 실패하면 서킷 브레이커는 다시 오픈 상태로 전환됩니다.
      • 예시: 하프-오픈 상태에서 3개의 요청을 허용하고, 모두 성공하면 클로즈드 상태로 전환됩니다. 만약 하나라도 실패하면 다시 오픈 상태로 전환됩니다.
  • Fallback: 호출 실패 시 대체 로직을 제공하여 시스템 안정성 확보
  • 모니터링: 서킷 브레이커 상태를 모니터링하고 관리할 수 있는 다양한 도구 제공

설정

dependencies {
    implementation 'io.github.resilience4j:resilience4j-spring-boot3:2.2.0'
    implementation 'org.springframework.boot:spring-boot-starter-aop'
}

다음 io.github.resilience4j dependency를 사용하려면 springboot 3 버전과 aop 를 추가해줘야 한다.


resilience4j:
  circuitbreaker:
    configs:
      default:  # 기본 구성 이름
        registerHealthIndicator: true  # 애플리케이션의 헬스 체크에 서킷 브레이커 상태를 추가하여 모니터링 가능
        # 서킷 브레이커가 동작할 때 사용할 슬라이딩 윈도우의 타입을 설정
        # COUNT_BASED: 마지막 N번의 호출 결과를 기반으로 상태를 결정
        # TIME_BASED: 마지막 N초 동안의 호출 결과를 기반으로 상태를 결정
        slidingWindowType: COUNT_BASED  # 슬라이딩 윈도우의 타입을 호출 수 기반(COUNT_BASED)으로 설정
        # 슬라이딩 윈도우의 크기를 설정
        # COUNT_BASED일 경우: 최근 N번의 호출을 저장
        # TIME_BASED일 경우: 최근 N초 동안의 호출을 저장
        slidingWindowSize: 5  # 슬라이딩 윈도우의 크기를 5번의 호출로 설정
        minimumNumberOfCalls: 5  # 서킷 브레이커가 동작하기 위해 필요한 최소한의 호출 수를 5로 설정
        slowCallRateThreshold: 100  # 느린 호출의 비율이 이 임계값(100%)을 초과하면 서킷 브레이커가 동작
        slowCallDurationThreshold: 60000  # 느린 호출의 기준 시간(밀리초)으로, 60초 이상 걸리면 느린 호출로 간주
        failureRateThreshold: 50  # 실패율이 이 임계값(50%)을 초과하면 서킷 브레이커가 동작
        permittedNumberOfCallsInHalfOpenState: 3  # 서킷 브레이커가 Half-open 상태에서 허용하는 최대 호출 수를 3으로 설정
        # 서킷 브레이커가 Open 상태에서 Half-open 상태로 전환되기 전에 기다리는 시간
        waitDurationInOpenState: 20s  # Open 상태에서 Half-open 상태로 전환되기 전에 대기하는 시간을 20초로 설정

위 처럼 yml 파일에 관련 설정을 추가할 수 있는데 https://resilience4j.readme.io/docs/getting-started-3 에서 제공하는 따라하면서 만들기 같은 튜토리얼을 제공하고있다. 이 설정은 실무에서는 이미 작성되어있을 경우가 대다수이며, 팀원들과의 회의를 통해 정할 부분이라 현재는 어떤게 뭔지 알고만 가는 느낌으로 정리했다.


Fallback 메커니즘

@Service
public class MyService {

    @CircuitBreaker(name = "myService", fallbackMethod = "fallbackMethod")
    public String myMethod() {
        // 외부 서비스 호출
        return externalService.call();
    }

    public String fallbackMethod(Throwable t) {
        return "Fallback response";
    }
}

다음처럼 @CircuitBreaker 어노테이션에서 fallbackMethod 를 지정해주면 해당 메서드에서 exception이 터질 때 자동으로 fallbackMethod가 실행되게 된다.

fallbackMethod 안에는 개발자에게 email, slack, sns 같은 알림을 통해 전송하고, 사용자에게 사용이 불가능함을 알리거나 여러 추가적인 로직을 구성할 수 있다.


Fallback의 장점

  • 시스템의 안정성을 높이고, 장애가 발생해도 사용자에게 일정한 응답을 제공할 수 있다.
  • 장애가 다른 서비스에 전파되는 것을 방지할 수 있다.

Resilience4j Dashboard


dependencies {
    implementation 'io.github.resilience4j:resilience4j-micrometer'
    implementation 'io.micrometer:micrometer-registry-prometheus'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
}

위의 설정을 통해 prometheus 로 데이터를 수집하고 micrometer로 모니터링 할 수 있다. 실제로는 grafana로 확인한다.

management:
  endpoints:
    web:
      exposure:
        include: prometheus
  prometheus:
    metrics:
      export:
        enabled: true

spring actuactor 와 prometheus 를 같이 사용하면 prometheus가 /actuactor 페이지를 보고 메트릭을 수집해서 정리한다.

다음처럼 확인할 수 있는데, 눈으로 확인하기는 어렵기 때문에 grafana 같은 대시보드를 주로 활용하는 것 같다. 잘 확인해보면 circuitbreaker 에 대한 정보도 확인할 수 있다.


Resilience4j와 Spring Cloud 연동

  • Resilience4j는 Spring Cloud Netflix 패키지의 일부로, Eureka와 Ribbon 등 다른 Spring Cloud 구성 요소와 쉽게 통합할 수 있다.
  • Spring Cloud의 서비스 디스커버리와 로드 밸런싱을 활용하여 더욱 안정적인 마이크로서비스 아키텍처를 구축할 수 있다.

실습

productId 가 111 일 때, exception을 터트리고 fallbackMethod 가 호출하는 flow로 이루어져 있다.

설정한 실패율 50% 넘어서 Current failure rate : 60.0 이 되는 순간 CircuitBreaker의 상태가 OPEN 으로 변해 동작하는 상태가 된다.

그 후 모든 요청에 대해서 실패처리를 해버리고 HALF_OPEN 상태로 변경되는데, 여기서 또 exception이 터진다면 OPEN 상태로 가고, 정상적으로 처리가 가능하다면 CLOSED 상태로 CiruitBreaker가 동작하지 않는 상태가 된다.


마무리

만약 5개의 외부서비스를 호출하는 메서드에서 오류가 터진다고 했을 때, 서킷 브레이커가 없다면 오류가 계속 전파되어 어디서 시작된 오류인지 확인하기 어려울 수 있다.

하지만, 서킷 브레이커가 fail-fast 함으로써 장애가 나더라도 전파를 최소화하고, 오류를 빠르게 받아올 수 있다는 것을 확인했다.

MSA 아키텍처에서는 더더욱 오류 전파를 최소화 해야하기에 중요한 기술이다.

profile
공부 정리용

0개의 댓글