spring cloud resilience4j

Sean·2025년 6월 4일

msa 환경에서 장애에 강한 시스템 만들기 위해 사용하는 라이브러리
장애 상황에서 죽지 않고 버틸 수 있도록.

예시 상황 : A-> B-> C 요청. 그런데 B가 느리거나 죽으면 A도 영향 받아 느려지거나 멈춤 가능. (전이된 장애 Failure propagation)

주요 기능

1. Circuit Breaker

  • 실패가 일정 횟수 이상 발생시, 더이상 요청 안보내고 실패 처리.
  • 실패 감지후, 일정 시간 지나면 재요청 보내 회복 여부 확인.

상태 흐름

CLOSED -> OPEN -> HALF_OPEN -> CLOSED
  • CLOSED : 정상상태. 실패 발생시 내부 카운터 증가.
  • OPEN : 실패율이 임계치 넘으면 차단. 일정 시간동안 요청 차단.
  • HALF_OPEN : 다시 시도해보는 상태. 일부 요청만 허용. 성공하면 CLOSED로 전환.
  1. 정상 상태 : CLOSED
  2. API 요청
  3. 호출 실패가 설정값 넘기면 OPEN 상태로 변경
  4. OPEN 상태 : 재요청 들어와도 요청 수항 X. 설정한 응답값 리턴.
  5. OPEN 유지 시간 지나면 HALF_OPEN 상태로 변경
  6. HALF_OPEN : 다시 외부 API 호출
  7. 정상 응답시 CLOSED 상태로 변경. 장애시 OPEN으로 변경.

설정 예시

resilience4j.circuitbreaker.instances.myService:
  failureRateThreshold: 50 # 실패율 50% 이상이면 OPEN
  waitDurationInOpenState: 10s # OPEN 상태 유지 시간
  slidingWindowSize: 10 # 최근 10개 요청 기준
  minimunNumberOfCalls: 3 # 3개 이상일 시 OPEN

해석 : 최근 10건 중, 실패율 50% 이상 3회 초과 발생시 OPEN.

  • 이외에도 여러 옵션 존재.

Resilience4j는 SlidingWindow 요청 결과 저장소를 이용한다.
두가지 유형 -> 회수 기반, 시간 기반
회수 기반 : 요청의 회수에 따라 Window 크기 결정
시간 기반 : 특정 초들의 집합을 기준으로 Window 크기 결정. ex) 1초에 1개

slidingwindow 크기가 10이므로, 11번째의 요청 올 시 2~11번째 결과까지만 판단.

fallback메서드

Circuit Breaker 정의 시 Fallback 메서드 지정 가능.

  • Circuit 상태 상관 없이 fail 조건 해당하면 호출됨.

서비스 호출 실패시, 대체 응답을 제공하여 사용자에게 안정적 서비스 제공.
장애 발생 시 -> 대체 로직 실행, 로컬 캐시, 백업 서비스 등 활용하여 실패 처리.

@Service
public class MyService {

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

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

역할 :

  • 에러 발생에 대체 응답 제공함으로서, 에러가 다른 서비스로 전파됨을 방지.
  • 특정 서비스 호출에서 발생한 에러를 한 곳에서 처리하므로, 에러 효과적 관리 가능.

장점 :

  • API 호출 실패해도 애플리케이션 지속적으로 응답 가능. (서비스 연속성 유지)
  • 복잡한 예외처리를 fallbackMethod로 대체할 수 있어, 예외처리 단순화
  • 실패 응답 커스텀으로 인해, 사용자에게 유용한 응답 제공 가능.

2. Rate Limiter

너무 많은 요청 보내지 않도록 초당 요청 수 제한.
DDos 방지나 과부하 방지 목적.

설정 예시

resilience4j.ratelimiter.instances.myService:
  limitForPeriod: 5 # cyle 동안 최대 5번
  limitRefreshPeriod: 10s # cycle 주기. 주기 끝나면 호출가능횟수 리셋
  timeoutDuration: 1s # 접근 허가 얻기 위한 대기 시간

해석 : 10초 동안 5개의 요청 허가

3. Retry

호출 실패 시, 자동으로 재시도. 일시적 장애(네트워크 끊김)에 유용.

설정 예시

resilience4j.retry.instances.myService:
  maxAttempts: 3 # 총 3번 시도
  waitDuration: 2s # 2초 간격 재시도
  retryExceptions:
    - java.io.IOException
  • 이외에도 여러 옵션 존재.

4. Time Limiter

외부 서비스가 느려 일정 시간 넘으면 실패 처리.
비동기 작업과 함께 자주 사용.

설정 예시

resilience4j.timelimiter.instances.myService:
  timeoutDuration: 3s # 3초 이상이면 timeout 처리

5. Bulkhead

외부 서비스 호출을 스레드 풀 or 큐로 격리하여 리소스 과도한 사용 못하게 함.

두가지 방식 :
1. Semaphore로 동시 호출 제한하는 SemaphoreBulkhead 방식
2. 고정된 thread pool 이용하는 FixedThreadPoolBulkhead 방식

설정 예시

resilience4j.bulkhead.instances.myService:
  maxConcurrentCalls: 5 # 최대 동시에 5개만 처리
  maxWaitDuration: 0 # maxConcurrentCalls를 모두 사용하고 있을 때 대기할 수 있는 시간.


Resilience4j 동작 순서

Bulkhead -> TimeLimiter -> RateLimiter -> CircuitBreaker -> Retry
비동기 작업과 함께 사용.


이미지 :

CircuitBreaker, resilience4j, https://resilience4j.readme.io/docs/circuitbreaker

profile
저스트두잇

0개의 댓글