Spring cloud circuit breaker 알아보기

🔥Log·2025년 3월 18일
0

스프링

목록 보기
20/21

⚡️ Circuit breaker


Circuit breaker는 "회로 차단기"를 의미하는 영단이다. (a.k.a 두꺼비집)
회로 차단기는 예상치를 뛰어넘는 전압이 들어오는 경우 연결을 끊어버리는 안전 장치이다.

서버 애플리케이션에서도 Circuit breaker라는 기술이 있는데, 실제 회로 차단기와 마찬가지로 서버에 위험 상황이 발생했을 때, 클라이언트와 서버와의 연결을 차단해서 클라이언트가 장애를 겪지 않도록 해주는 역할을 한다.

🍃 Spring cloud circuit breaker

위와 같은 기능을 Spring 진영에서 만든 라이브러리가 있다. 추상화에 미친 Spring 답게 Spring cloud circuit breaker는 Circuit breaker 기능을 추상화한 라이브러리이고, Resilience4J가 대표적인 구현체 중 하나이다.

🧐 Circuit breaker의 상태

Circuit breaker는 3가지의 상태가 있는데, 아래와 같은 의미들을 가진다.

상태의미
Closed연결이 닫혀 있는 정상적인 연결 상태
Half openOpen 상태에서 Closed로 회복하기 전, 일부의 트래픽만을 받아들이는 상태
Open장애가 발생하여 Circuit breaker가 동작하면서 연결이 끊어져 있는 상태


✏️ Spring circuit breaker의 주요 기능


1) Circuit break

가장 핵심이 되는 기능으로, 특정 서버에서 장애가 발생했을 때, 요청을 빠르게 실패시키고 장애가 확산되지 않도록 차단하는 기능을 한다.

실패율이 특정 임계치를 초과하면 Open 상태로 전환되면서 추가적인 요청은 Fallback 응답을 받게 된다.

이후에 일정 시간 후 Half-Open 상태에서 일부 요청을 허용하며 회복 여부를 확인하고, 점진적으로 Closed 상태로 전환하게 된다.

2) Fallback 처리

@CircuitBreaker(name = "myService", fallbackMethod = "fallbackMethod")
public String callService() {
    return restTemplate.getForObject("http://hello.com/api", String.class);
}

public String fallbackMethod(Exception ex) {
    return "Fallback response";
}

위와 같은 예제 코드가 있고, callService가 클라이언트에게 응답을 하는 메서드라고 가정했을 때, Circuit breaker에 설정된 실패율이 임계치를 넘으면 해당 기능은 Open상태가 되고, callService의 내부 로직이 도는 것이 아니라, fallbackMethod가 그 응답을 대체하게 된다.

💡 실패율

여기서 "실패율"은 slidingWindow 중, 얼마 만큼의 처리가 실패했는지를 의미한다.

💡 slidingWindow

Resilience4j Circuit Breaker에서 장애율을 계산할 때 사용하는 메커니즘으로, 최근 N개의 요청을 기준으로 실패율을 계산하는 방식이다.
이 값을 기반으로 서킷 브레이커가 Open(차단) 상태로 전환할지 여부를 결정한다.

3) Retry

일시적인 네트워크 장애나 일시적인 서버 오류도 발생할 수 있으므로, 바로 실패 처리하지 않고 설정된 값만큼 다시 요청을 보내는 기능이다.

4) TimeLimiter

설정된 시간만큼 응답이 돌아오지 않으면, 타임아웃으로 처리하는 기능을 의미한다.



🧙‍♂️ Spring circuit breaker 사용하기


1) 설정

implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'

Gradle을 기준으로 위 라이브러리를 추가하면, Circuit breaker를 사용할 준비가 된 것이다.

2) yaml 설정

resilience4j:
  circuitbreaker:
    instances:
      myService:  # Circuit Breaker의 이름
        slidingWindowType: COUNT_BASED  # 실패율 계산 방식 (COUNT_BASED or TIME_BASED)
        slidingWindowSize: 10  # 최근 10개의 요청을 기준으로 실패율 계산
        failureRateThreshold: 50  # 50% 이상 실패하면 OPEN 상태로 변경
        waitDurationInOpenState: 5000ms  # OPEN 상태 지속 시간 (5초)
        permittedNumberOfCallsInHalfOpenState: 3  # HALF-OPEN에서 허용할 요청 개수
  timelimiter:
    instances:
      myService:
        timeoutDuration: 3s  # 3초 이상 걸리면 요청 실패로 간주
  retry:
    instances:
      myService:
        maxAttempts: 3  # 최대 3번 재시도
        waitDuration: 200ms  # 재시도 간격 200ms

Spring circuit breaker는 yaml 파일 또는 Spring bean을 생성함으로써 설정해줄 수 있다. 위 예시는 yaml 파일을 통해서 설정하는 방법에 대한 예시이다.

3) 예시

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;

import java.util.concurrent.CompletableFuture;

@RestController
@RequestMapping("/api")
public class AsyncController {

    @CircuitBreaker(name = "myService", fallbackMethod = "fallbackResponse")
    @TimeLimiter(name = "myService")
    @GetMapping("/async-data")
    public CompletableFuture<String> getAsyncData() {
        return CompletableFuture.supplyAsync(() -> {
            // 외부 API 호출 (3초 이상 걸리면 Timeout 발생)
            return "실제 데이터";
        });
    }

    public CompletableFuture<String> fallbackResponse(Exception e) {
        return CompletableFuture.completedFuture("Fallback: 서비스 장애 발생!");
    }
}

Spring circuit breaker는 위와 같이 어노테이션을 통해서 API들에 적용할 수 있다. 위에서 사용한 어노테이션과 함께 아래와 같은 어노테이션들도 존재한다.

  • @CircuitBreaker: 서킷 브레이커 적용
  • @Retry: 실패 시 재시도
  • @RateLimiter: 호출 속도 제한
  • @TimeLimiter: 시간 초과 제한


🙏 참고


0개의 댓글

관련 채용 정보