마이크로서비스 아키텍처의 4가지 복원력 패턴
마이크로서비스 아키텍처의 4가지 복원력 패턴
시스템 안정성을 위한 필수 전략
클라우드 기반 마이크로서비스 환경에서 원격 서비스의 성능 저하는 단순한 문제가 아닙니다. 이러한 문제는 감지하기 어려울 뿐만 아니라, 전체 애플리케이션 생태계에 연쇄 효과를 일으킬 수 있습니다. 보호 장치가 없다면, 단일 서비스의 성능 저하가 여러 애플리케이션을 빠르게 마비시킬 수 있습니다.
특히 마이크로서비스 아키텍처는 수많은 세밀한 분산 서비스로 구성되어 있고, 사용자의 트랜잭션을 완료하기 위해 다양한 인프라 구성 요소가 관여하기 때문에 이러한 유형의 장애에 취약합니다.
복원력 패턴은 마이크로서비스 아키텍처에서 가장 중요한 측면 중 하나입니다. 이러한 패턴들은 시스템이 장애 상황에서도 안정적으로 동작할 수 있도록 보장하며, 사용자에게 일관된 경험을 제공하는 핵심 요소입니다.
이 문서에서는 다음과 같은 주요 복원력 패턴을 살펴봅니다.
- 클라이언트 측 로드 밸런싱 (Client-side Load Balancing): 여러 서비스 인스턴스에 요청을 분산하고 장애가 발생한 인스턴스는 제외합니다.
- 서킷 브레이커 (Circuit Breaker): 반복되는 오류를 감지하고 추가적인 호출을 차단하여 시스템 전체의 장애 전파를 막습니다.
- 폴백 처리 (Fallback): 주 기능이 실패했을 때 대체 경로를 실행하여 사용자에게 최소한의 기능을 제공합니다.
- 벌크헤드 (Bulkhead): 시스템 리소스를 격리하여 특정 서비스의 장애가 다른 서비스에 영향을 주지 않도록 합니다.
클라이언트 측 복원력 패턴이란?
클라이언트 측 복원력 소프트웨어 패턴은 **원격 리소스(다른 마이크로서비스 호출이나 데이터베이스 조회)**의 클라이언트가 오류나 성능 저하로 인해 원격 리소스가 실패할 때 크래시되지 않도록 보호하는 데 중점을 둡니다.
- 이러한 패턴은 클라이언트가 빠르게 실패하도록 하여 데이터베이스 연결이나 스레드 풀과 같은 귀중한 리소스를 소모하지 않게 합니다.
- 또한 성능이 저하된 원격 서비스의 문제가 클라이언트의 소비자들에게 **“upstream”**로 확산되는 것을 방지합니다.
1. 클라이언트 측 로드 밸런싱 (Client-side Load Balancing)
개념과 목적
- 클라이언트 측 로드 밸런싱은 클라이언트가 서비스 디스커버리 에이전트(예: Netflix Eureka)에서 서비스의 모든 개별 인스턴스를 조회하고, 해당 서비스 인스턴스의 물리적 위치를 캐싱하는 패턴입니다.
- 서비스 소비자가 서비스 인스턴스를 호출해야 할 때, 클라이언트 측 로드 밸런서는 유지하는 서비스 위치 풀에서 위치를 반환합니다.
- 클라이언트 측 로드 밸런서가 서비스 클라이언트와 서비스 소비자 사이에 위치하기 때문에, 로드 밸런서는 서비스 인스턴스가 오류를 발생시키거나 성능이 저하되는지 감지할 수 있습니다.
동작 방식
클라이언트 측 로드 밸런서가 문제를 감지하면, 해당 서비스 인스턴스를 사용 가능한 서비스 위치 풀에서 제거하고 향후 호출이 해당 서비스 인스턴스에 도달하지 않도록 방지합니다.
- 서비스 인스턴스 목록을 서비스 디스커버리에서 조회 및 캐싱
- 요청 시, 인스턴스 풀에서 정상 인스턴스를 선택해 호출
- 장애 인스턴스는 풀에서 제거하여 추가 장애 확산 방지
2. 서킷 브레이커 (Circuit Breaker)
분산 환경에서 원격 서비스 호출은 일시적 혹은 장기적인 장애를 겪을 수 있습니다. 단순한 재시도 메커니즘은 일시적인 오류에는 효과적이지만, 서비스가 완전히 다운된 상황에서는 오히려 시스템에 부담을 가중시키고 리소스를 낭비하게 만듭니다. 예를 들어, 전자상거래 사이트의 결제 서비스가 중단되었을 때 무작정 재시도를 반복하는 대신, 장애를 신속하게 인지하고 추가적인 호출을 막는 전략적인 접근이 필요합니다. 서킷 브레이커 패턴은 바로 이러한 문제를 해결하기 위해 등장했습니다.
개념과 목적
- 서킷 브레이커 패턴은 전기 회로 차단기를 모델로 하여, 장애가 감지되면 연결을 끊어 시스템 전체의 손상을 방지합니다.
- 소프트웨어에서는 원격 서비스 호출을 모니터링하다가, 호출이 너무 오래 걸리거나 실패가 누적되면 자동으로 차단합니다.
동작 방식
Circuit Breaker는 원격 접속 실패 횟수가 특정 임계값에 도달하면 정의된 시간 동안 더이상 동작하지 않도록 한다. 해당 시간 동안 오프라인 서버에 대한 모든 요청은 실패하고, 해당 시간이 지나면 제한된 수의 요청이 통과하도록 허용하고, 해당 요청이 성공하면 원래 상태로 복구한다.
서킷 브레이커는 세 가지 상태를 가집니다:
서킷 브레이커는 3가지 상태를 가집니다:
| 상태 | 설명 |
|---|---|
| Closed | 정상 상태, 모든 요청이 원격 서비스로 전달됨 |
| Open | 장애 감지, 모든 요청이 즉시 실패 |
| Half-Open | 복구 시도, 일부 요청만 허용하여 정상 여부 확인 |
- 실패 횟수 카운트(Close 상태): Close상태일 때는 정상 작동으로 요청을 통과 시킨다. 이때 마이크로서비스 요청에 대한 실패가 카운트 된다.
- 실패 횟수 > 임계값(Open 상태): 실패 횟수가 임계값을 초과하면 회로가 Open 상태가 되어 요청이 서비스에 도달하지 못하도록 차단되며, 실패 응답을 반환한다. 이후 서버가 정상적으로 복구되면 Half open 상태로 변경된다.
- 제한된 요청 테스트 및 성공 확인 (Half open 상태): 이 상태에서는 제한된 수의 요청을 통과시키고 응답에 성공하면 Close 상태로 돌아간다. 이때 요청이 실패하면 다시 Open 상태로 돌아간다.
주요 이점
- 빠른 실패 (Fail Fast)
- 원격 서비스가 성능 저하를 겪을 때 애플리케이션이 빠르게 실패하여 일반적으로 전체 애플리케이션을 종료시키는 리소스 고갈 문제를 방지합니다.
- 우아한 실패 (Fail Gracefully)
- 타임아웃과 빠른 실패를 통해 우아하게 실패하거나 사용자의 의도를 수행하기 위한 대안 메커니즘을 찾을 수 있는 능력을 제공합니다.
- 원활한 복구 (Recover Seamlessly)
- 서킷 브레이커 패턴이 중재자 역할을 하면서 요청된 리소스가 다시 온라인 상태가 되었는지 주기적으로 확인하고 인간의 개입 없이 접근을 다시 활성화할 수 있습니다.
사용 시나리오 및 고려사항
| 구분 | 내용 |
|---|---|
| 사용 시나리오 | - 실패 가능성이 높은 원격 서비스(특히 외부 API)를 호출해야 할 때. - 일시적인 네트워크 문제나 서비스 과부하로 인해 반복적인 실패가 예상될 때. - 특정 기능의 실패가 전체 시스템의 장애로 이어지는 것을 막고 싶을 때. |
| 고려사항 | - 서킷을 열고 닫는 임계값(실패율, 대기 시간 등) 설정이 매우 중요합니다. 너무 민감하면 정상적인 상황에서도 회로가 열릴 수 있고, 너무 둔감하면 장애 전파를 막지 못할 수 있습니다. - 비즈니스적으로 중요한 예외(예: 유효성 검사 실패)는 실패로 간주하지 않도록 ignoreExceptions 설정을 활용해야 합니다. |
Resilience4j 적용
Resilience4j에서는 @CircuitBreaker 애노테이션으로 간단히 구현합니다. **name**으로 application.yml에 정의된 설정을 불러오고, **fallbackMethod**를 지정해 장애 시 대체 로직을 실행합니다.
@CircuitBreaker(name = "coreApi", fallbackMethod = "fallback")
public Mono<String> findUser(String id) {
return webClient.get()
.uri("/api/{id}", id) // baseUrl은 WebClient 생성 시 설정했다고 가정
.retrieve()
.bodyToMono(String.class);
}
private Mono<String> fallback(String id, Throwable t) {
return Mono.just("fallback-user");
}
옵션 가이드
Resilience4j의 “서킷 브레이커”는 다양한 옵션을 제공하여 세밀한 제어가 가능합니다. 서킷 브레이커에서 사용되는 주요 옵션은 다음과 같습니다.
| 옵션 | 설명 | 기본/주의 | 튜닝 팁 |
|---|---|---|---|
| slidingWindowType / slidingWindowSize | 실패·느린호출 비율을 집계하는 창의 방식/크기. COUNT_BASED는 최근 N건, TIME_BASED는 기간 기반. | 창이 너무 작으면 노이즈에 민감. | 트래픽 변동이 크면 TIME_BASED 고려, 적정 창 크기로 스파이크 흡수. |
| minimumNumberOfCalls | 이 수에 도달하기 전엔 상태 전환/실패율 계산을 하지 않음. | 너무 작으면 조기 오탐, 너무 크면 반응이 둔감. | 저트래픽 엔드포인트는 낮추고, 고트래픽은 높여 안정화. |
| failureRateThreshold | 실패율(%)이 임계 이상이면 Open 전환. | 비즈니스 실패를 실패로 기록하는지 확인. | 폴백이 충분하면 임계값을 낮춰 빠른 차단. |
| slowCallDurationThreshold | 호출이 이 시간을 초과하면 ‘느린 호출’로 간주. ‘느린 호출’도 실패로 처리하려면 slowCallRateThreshold와 함께 사용. | API 타임아웃보다 짧게 설정해야 의미가 있음. | 외부 서비스의 SLO/SLA를 기준으로 설정. |
| slowCallRateThreshold | 느린 호출 비율(%)이 임계 이상이면 Open 전환. | 느린 호출을 실패로 보지 않으면 비활성화. | 피크 시간대 과도한 Open 방지를 위해 상향. |
| waitDurationInOpenState | Open 유지 시간. 만료 후 Half-Open 시도. | 너무 짧으면 플래핑, 너무 길면 가용성 저하. | 평균 복구 시간(MTTR)에 맞춰 조정. |
| permittedNumberOfCallsInHalfOpenState | Half-Open에서 허용되는 시험 호출 수. | 너무 적으면 통계 부족. | 중요도·트래픽 따라 5~20 권장. |
| automaticTransitionFromOpenToHalfOpenEnabled | 시간 경과 시 Half-Open 자동 전환. | 꺼두면 수동 트리거 필요. | 일반적으로 활성화 권장. |
| recordException / ignoreException | 실패로 기록할/무시할 예외 지정(프레디케이트 지원). | 과도하면 과차단/미차단. | 비즈니스 예외는 무시, 네트워크/서버 오류만 기록. |
3. 폴백 처리 (Fallback Processing)
개념과 목적
- 폴백 패턴은 원격 서비스 호출이 실패할 때 예외를 발생시키는 대신, 대안 코드 경로를 실행하여 다른 방법으로 작업을 시도합니다.
- 예를 들어, 다른 데이터 소스에서 데이터를 조회하거나, 요청을 큐에 넣어 나중에 처리할 수 있습니다.
실제 예시
예를 들어, 사용자의 행동을 모니터링하고 구매할 수 있는 다른 아이템에 대한 추천을 제공하는 전자상거래 사이트가 있다고 가정해보겠습니다.
- 일반적으로 사용자의 과거 행동을 분석하고 해당 특정 사용자에게 맞춤화된 추천 목록을 반환하는 마이크로서비스를 호출합니다.
- 그러나 선호도 서비스가 실패하면, 폴백은 모든 사용자 구매를 기반으로 한 더 일반적인 선호도 목록을 검색하는 것일 수 있습니다. 이 데이터는 완전히 다른 서비스와 데이터 소스에서 올 수 있습니다.
폴백 전략의 유형
- 캐시된 데이터 사용: 이전에 성공적으로 가져온 데이터를 사용
- 기본값 반환: 미리 정의된 기본 응답 제공
- 대체 서비스 호출: 동일한 기능을 제공하는 다른 서비스 사용
- 비동기 처리: 요청을 큐에 넣고 나중에 처리
사용 시나리오 및 고려사항
| 구분 | 내용 |
|---|---|
| 사용 시나리오 | - 서킷 브레이커가 열렸거나, 요청이 타임아웃되는 등 명백한 실패 상황에서 사용자에게 빈 화면이나 오류 메시지 대신 의미 있는 응답을 제공하고 싶을 때. - 핵심 기능은 아니지만 사용자 경험을 해치지 않기 위해 기본 데이터(예: 캐시된 데이터, 기본 추천 목록)라도 제공해야 할 경우. |
| 고려사항 | - 폴백 응답은 가능한 한 정적이고 가벼워야 합니다. 폴백 로직이 또 다른 원격 서비스를 호출하는 등 복잡해지면 폴백 자체가 또 다른 실패 지점이 될 수 있습니다. - 폴백 데이터가 실제 데이터와 차이가 있을 수 있음을 사용자에게 인지시켜야 할 수도 있습니다. |
Resilience4j 적용
서비스가 다운되었을 때, 사용자에게 빈 화면 대신 미리 준비된 ‘인기 상품 목록’이라도 보여주는 코드 예시를 살펴봅니다. 아래 코드처럼 @CircuitBreaker의 fallbackMethod를 사용해, 주 로직 실패 시 fallbackRecommendations가 대신 호출되도록 할 수 있습니다. 이 메서드는 비즈니스 요구사항에 맞는 어떤 대체 응답이든 반환할 수 있습니다.
@CircuitBreaker(name = "recommendation", fallbackMethod = "fallbackRecommendations")
public List<String> getRecommendations(String userId) { /* ... */ }
private List<String> fallbackRecommendations(String userId, Throwable t) {
return List.of("top-1", "top-2");
}
옵션 가이드
Resilience4j의 “재시도”는 다양한 옵션을 제공하여 세밀한 제어가 가능합니다. 재시도에서 사용되는 주요 옵션은 다음과 같습니다.
| 옵션 | 설명 | 기본/주의 | 튜닝 팁 |
|---|---|---|---|
| maxAttempts | 최대 시도 횟수(원 호출 포함). | 높으면 장애 확산·리소스 고갈 위험. | 외부 의존성의 일시 장애 비율 고려해 2~3으로 시작. |
| waitDuration | 재시도 간 고정 대기 시간. | 너무 짧으면 재시도 스톰, 너무 길면 지연 증가. | 회복 시간 분포에 맞춰 조정. |
| retryExceptions / ignoreExceptions | 재시도 대상/비대상 예외. | 비즈니스 검증 실패는 재시도 금지. | 타임아웃, 5xx만 선별. |
| exponentialBackoffMultiplier | 시도마다 대기 시간을 지수적으로 증가. | 과도하면 지연 증가. | 버스트 완화용 1.5~2.0 권장. |
| randomizedWaitFactor | 대기 시간에 지터(랜덤) 부여. | 0이면 동시 재시도 동기화 발생. | 0.1~0.3 설정해 동시성 스파이크 방지. |
4. 벌크헤드 (Bulkheads)
개념과 목적
- 벌크헤드 패턴은 선박의 방수 격벽에서 유래한 개념으로, 시스템 내 리소스를 격리하여 하나의 장애가 전체 시스템으로 확산되는 것을 방지합니다.
선박은 완전히 격리되고 방수된 벌크헤드라는 구획으로 나뉩니다. 선체가 관통되더라도 하나의 벌크헤드가 물을 관통이 발생한 선박의 해당 영역에 국한시키고 전체 선박이 물로 가득 차서 침몰하는 것을 방지합니다.
- 동일한 개념을 여러 원격 리소스와 상호작용해야 하는 서비스에 적용할 수 있습니다. 벌크헤드 패턴을 사용할 때, 원격 리소스에 대한 호출을 자체 스레드 풀로 분리하여 하나의 느린 원격 리소스 호출 문제가 전체 애플리케이션을 마비시킬 위험을 줄입니다.
- 마이크로서비스 환경에서 벌크헤드 패턴은 리소스 격리를 통해 시스템의 안정성을 보장합니다. 하나의 서비스나 외부 의존성이 문제를 일으킬 때, 그 영향이 전체 시스템으로 확산되는 것을 방지하는 것이 핵심 목적입니다.
동작 방식
- 리소스 분리: 각 외부 의존성에 대해 독립적인 스레드 풀 생성
- 격리된 실행: 각 서비스 호출이 해당 전용 스레드 풀에서 실행
- 장애 격리: 하나의 서비스 문제가 다른 서비스에 영향을 주지 않음
- 부분적 가용성: 일부 서비스가 실패해도 다른 기능은 계속 제공
스레드 풀이 서비스의 벌크헤드 역할을 하고 각 원격 리소스는 격리되고 스레드 풀에 할당됩니다. 하나의 서비스가 느리게 응답하면 해당 유형의 서비스 호출에 대한 스레드 풀이 포화 상태가 되어 요청 처리를 중단할 수 있습니다. 서비스를 스레드 풀에 할당하면 병목 현상을 우회하여 다른 서비스가 포화 상태가 되지 않도록 할 수 있습니다.
시각적 이해: 벌크헤드 적용 전후 비교
벌크헤드 패턴의 효과를 이해하기 위해 다음 두 가지 시나리오를 비교해볼 수 있습니다.
적용 전: 공유 스레드 풀 하나의 서비스(C)에 장애가 발생하면, 해당 서비스를 호출하는 스레드들이 모두 대기 상태에 빠져 전체 스레드 풀을 고갈시킵니다. 결국 다른 정상 서비스(A, B)에 대한 요청도 처리할 수 없게 됩니다.
[애플리케이션 스레드 풀 (공유)]
Thread 1 -> Service A (정상)
Thread 2 -> Service B (정상)
Thread 3 -> Service C (장애 발생, 응답 없음)
Thread 4 -> Service C (장애 발생, 응답 없음)
...
Thread N -> Service C (장애 발생, 응답 없음)
==> 모든 스레드가 C를 기다리며 고갈, A와 B로의 신규 요청 처리 불가
적용 후: 격리된 스레드 풀 (벌크헤드) 각 서비스 호출을 위한 별도의 스레드 풀을 할당합니다. 서비스 C의 스레드 풀이 고갈되더라도, 서비스 A와 B의 스레드 풀은 영향을 받지 않으므로 정상적으로 서비스를 계속할 수 있습니다.
[Service A 풀] [Service B 풀] [Service C 풀 (고갈)]
Thread A1 Thread B1 Thread C1 (대기)
Thread A2 Thread B2 Thread C2 (대기)
... ... ...
==> Service C는 실패하지만, Service A와 B는 정상 작동
벌크헤드 구현
마이크로서비스 기반 애플리케이션에서는 특정 작업을 완료하기 위해 여러 마이크로서비스를 호출해야 하는 경우가 많습니다. 벌크헤드 패턴을 사용하지 않으면, 이러한 호출들은 컨테이너 전체의 요청 처리를 위해 예약된 동일한 스레드에서 실행됩니다.
문제 상황: 높은 부하에서 하나의 서비스가 느려지면, 모든 스레드가 해당 서비스 응답을 기다리게 되고, 결국 컨테이너가 크래시될 수 있습니다.
벌크헤드 패턴은 원격 리소스 호출을 자체 스레드 풀로 격리시켜서, 단일 서비스의 문제가 컨테이너를 크래시시키지 않도록 보장합니다. 벌크헤드 패턴은 주로 두 가지 방식으로 구현됩니다. 이러한 구현을 사용하여 동시 실행 수를 제한할 수 있습니다:
세마포어 벌크헤드 (Semaphore Bulkhead)
- 세마포어 격리 접근 방식을 사용하여 서비스에 대한 동시 요청 수를 제한합니다. 한계에 도달하면 요청 거부를 시작합니다.
스레드 풀 벌크헤드 (Thread Pool Bulkhead)
- 경계가 있는 큐와 고정된 스레드 풀을 사용합니다. 이 접근 방식은 풀과 큐가 모두 가득 찰 때만 요청을 거부합니다.
벌크헤드의 이점
- 격리 (Isolation): 하나의 서비스 문제가 다른 서비스에 영향을 주지 않음
- 리소스 보호 (Resource Protection): 스레드 풀과 연결 풀을 보호
- 부분적 가용성 (Partial Availability): 일부 서비스가 실패해도 다른 서비스는 계속 작동
사용 시나리오 및 고려사항
| 구분 | 내용 |
|---|---|
| 사용 시나리오 | - 서로 다른 성능 특성이나 중요도를 가진 여러 외부 서비스를 동시에 호출해야 할 때. - 특정 외부 서비스의 장애가 다른 서비스 호출에 영향을 미치는 것을 원천적으로 차단하고 싶을 때. - 시스템의 각 부분을 독립적으로 보호하여 부분적인 장애가 전체 시스템의 중단으로 이어지지 않도록 해야 할 때. |
| 고려사항 | -스레드 풀 벌크헤드는 스레드를 추가로 생성하고 관리해야 하므로 리소스 오버헤드가 있습니다. 시스템의 전체 스레드 수를 고려하여 신중하게 적용해야 합니다. - 세마포어 벌크헤드는 오버헤드가 적지만, 호출 스레드를 격리하는 것이 아니므로 장시간 실행되는 요청에는 효과적이지 않을 수 있습니다. 타임아웃과 함께 사용하는 것이 좋습니다. |
Resilience4j 적용
Resilience4j는 앞서 설명한 세마포어와 스레드풀 두 가지 방식의 벌크헤드를 모두 지원합니다. @Bulkhead 애노테이션을 사용해 간단히 적용할 수 있으며, type 속성으로 구현 방식을 선택할 수 있습니다. 지정하지 않을 경우 기본값은 SEMAPHORE입니다.
예를 들어, 재고 확인처럼 빠른 응답과 실패가 중요한 동기식 호출에는 세마포어 방식을, 결제 처리와 같이 시간이 걸리는 비동기 작업에는 스레드풀 방식을 적용하는 것이 효과적입니다.
@Bulkhead(name = "inventoryApi")
public String reserveItem(String sku) { /* ... */ }
@Bulkhead(name = "paymentApi", type = Bulkhead.Type.THREADPOOL)
CompletableFuture<String> pay(String orderId) { /* ... */ }
옵션 가이드 (벌크헤드)
Resilience4j의 “벌크헤드”는 다양한 옵션을 제공하여 세밀한 제어가 가능합니다. 벌크헤드에서 사용되는 주요 옵션은 다음과 같습니다.
| 타입 | 옵션 | 설명 | 기본/주의 | 튜닝 팁 |
|---|---|---|---|---|
| 세마포어 | maxConcurrentCalls | 동시에 허용할 호출 수. | 낮으면 429/거부 증가, 높으면 포화·병목. | 의존성 처리량·지연 기반으로 용량 캡 계산. |
| 세마포어 | maxWaitDuration | 세마포어 대기 최대 시간(0이면 즉시 거부). | 대기가 길면 호출자 대기열 증가. | 사용자 API는 0~수십 ms로 빠른 실패 권장. |
| 스레드풀 | coreThreadPoolSize / maxThreadPoolSize | 코어/최대 스레드풀 크기. 평상시 core, 부하 시 max까지 스레드가 동적으로 관리됨. | 스레드풀이 너무 많으면 리소스 소모 및 컨텍스트 스위칭 비용 증가. | 코어=평균 처리량, 맥스=순간적인 트래픽 스파이크를 감당할 수준으로 설정. |
| 스레드풀 | queueCapacity | 큐 크기. 포화 시 거부. | 큐가 크면 지연만 증가, 복구 지연. | 백프레셔 위해 적정 큐(수십~수백) 유지. |
Resilience4j 통합 구성 (Spring Boot)
Spring Boot에서 Resilience4j를 구성하는 흐름은 다음과 같습니다.
(1) 의존성 추가로 자동 구성과 AOP 프록시를 활성화하고,
(2) application.yml에서 이름 있는 인스턴스를 선언하며,
(3) 코드에서 애노테이션이나 프로그래매틱 API로 해당 인스턴스를 사용합니다.
아래 예시는 Spring Boot에서 Resilience4j 적용을 위한 최소 통합 템플릿입니다.
- 의존성 (Gradle)
dependencies {
implementation 'io.github.resilience4j:resilience4j-spring-boot3'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
- 통합 application.yml (예시)
resilience4j:
circuitbreaker:
instances:
coreApi:
slidingWindowType: COUNT_BASED
slidingWindowSize: 20
failureRateThreshold: 50
waitDurationInOpenState: 30s
permittedNumberOfCallsInHalfOpenState: 5
automaticTransitionFromOpenToHalfOpenEnabled: true
retry:
instances:
coreApi:
maxAttempts: 3
waitDuration: 200ms
retryExceptions:
- org.springframework.web.client.HttpServerErrorException
bulkhead:
instances:
inventoryApi:
maxConcurrentCalls: 20
maxWaitDuration: 0
thread-pool-bulkhead:
instances:
paymentApi:
coreThreadPoolSize: 5
maxThreadPoolSize: 10
queueCapacity: 20
timelimiter:
instances:
coreApi:
timeoutDuration: 2s
ratelimiter:
instances:
coreApi:
limitForPeriod: 50
limitRefreshPeriod: 1s
timeoutDuration: 0
참고 자료
- Newman, S. (2021). Spring Microservices in Action, Second Edition. Manning Publications.
- Circuit Breaker
- Circuit Breaker Pattern (Design Patterns for Microservices)
- Using the circuit breaker pattern with AWS Step Functions and Amazon DynamoDB
- Error Handling in Microservices: A Guide to Circuit Breaker Pattern
- Spring Cloud Circuit Breaker Guide