MSA 혹은 외부 API를 이용하는 서버의 경우, 외부 API나 DB의 오류로 인해 본 서버에 과부하가 걸리거나 이로인해 오류가 발생 할 수 있다. 즉, 연쇄적인 서비스 오류를 막고자 하는것이 서킷 브레이커 이다.
- 외부 API나 DB가 비정상 동작시 -> 들어온 요청에 바로 결과를 리턴한다 (외부 API 또는 DB에 접근 하지 않음)
- Fallback을 통해 빠르게 응답을 리턴한다. (예 : DB 접속이 안되면, 캐시에서 조회해보고, 안되면 오류메세지 리턴)
- 일정 시간이 지난 후, 몇몇 요청에 한해서는 실제 API나 DB에 다시 접속 해 본다. (Half open)
- 만일 결과가 정상적으로 온다면, 점차 서비스를 정상화 시킨다.
- 결과가 정상적으로 오지 않는다면, 다시 대기 후 추후 Half Open을 다시 한다.
이를 Springboot 에서 편리하게 이용하기 위해 Resilience4j 를 이용한다.
Build.gradle 추가
implementation "io.github.resilience4j:resilience4j-spring-boot3:2.3.0"
application.yaml 추가
- 서비스에서 @CircuitBraker 어노테이션을 이용하면서 사용한 이름별로 설정이 가능하다.
resilience4j:
circuitbreaker:
configs:
default:
registerHealthIndicator: true
slidingWindowType: COUNT_BASED
slidingWindowSize: 10
minimumNumberOfCalls: 5
failureRateThreshold: 50
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
instances:
서비스에서_사용할_이름:
baseConfig: default
- 서비스에서 @CircuitBraker 어노테이션 사용시 이용할 이름을 지정해 줘야 한다.
- slidingWindowType
- COUNT_BASED : 최근 요청 횟수 기준
- TIME_BASED : 최근 시간(초) 기준
- slidingWindowSize : 최근 몇번 요청을 기준으로 판단 할 것인지
- minimumNumberOfCalls : 최소 이 횟수 요청 전까지는 서킷브레이커가 열리지 않음.
- failureRateThreshold : 여기에 설정한 실패율 이상일 경우 서킷브레이커 동작
- waitDurationInOpenState : 서킷브레이커가 Open된 상태에서 최소 이 시간동안은 완전히 차단함.
- permittedNomberOfCallsHalfOpenState : Half open 상태에서 테스트용으로 요청할 횟수
- automaticTransitionFromOpenToHalfOpenEnabled : Open -> Half open 자동전환 여부 (true 설정 필수)
서비스에서 사용 예
@Service
@RequiredArgsConstructor
@Slf4j
public class ExternalApiService {
private final WebClient externalApiWebClient;
/**
* 외부 API 호출
* - CircuitBreaker 적용
*/
@CircuitBreaker(
name = "external-api",
fallbackMethod = "getDataFallback"
)
public ExternalDto getExternalData(Long id) {
return externalApiWebClient.get()
.uri("/v1/data/{id}", id)
.retrieve()
.bodyToMono(ExternalResponse.class)
// WebClient 자체 타임아웃
.timeout(Duration.ofSeconds(2))
// 외부 → 내부 변환
.map(ExternalDto::from)
// MVC 환경
.block();
}
/**
* CircuitBreaker OPEN 또는 예외 발생 시 호출되는 fallback
*/
private ExternalDto getDataFallback(Long id, Throwable ex) {
log.warn("CircuitBreaker fallback 실행 (id={})", id, ex);
// 대체 응답 (빈 객체 / 캐시 / 기본값)
return ExternalDto.empty();
}
}
- name 에 사용한 external-api 는 application.yaml 설정에 포함되어 있어야 한다. (instances 하위)
- fallBack 설정을 해주어야 한다. fallBackMethod 에서 지정한 이름과 실제 메서드 이름이 같아야 한다.
'Backend > SpringBoot' 카테고리의 다른 글
| Cache 를 Actuator에서 확인하기 (Caffein 예) (0) | 2026.01.05 |
|---|---|
| Local Cache, Caffein (0) | 2026.01.05 |
| MVC 환경에서 WebClient (0) | 2026.01.05 |
| Task Decorator (@Async 에서 MDC, SecurityContextHolder 정보 활용) (0) | 2026.01.02 |
| @Async 설정 및 사용 (0) | 2026.01.02 |