공부/Spring

[Spring Cloud] 서킷 브레이커 (Resilience4j)

린구 2024. 8. 5. 14:34
반응형

 

📌 서킷 브레이커

`서킷 브레이커`란 MSA 간 호출 실패를 감지하고 시스템의 전체적인 안정성을 유지하는 패턴이다.

외부 서비스 호출 실패 시 장애를 격리하고, 시스템의 다른 부분에 영향을 주지 않도록 한다.

상태 변화는 Closed -> Open -> Half Open 순으로 변화한다.

 

📌 Resilience4j

`Resilience4j`는 서킷 브레이커 라이브러리이다.

다양한 서킷 브레이커 기능을 제공한다!

`Fallback` 메서드를 통해 호출 실패 시 대체 로직을 제공하여 시스템 안정성을 확보한다.

또한 서킷 브레이커 상태를 모니터링하고 관리할 수 있는 다양한 모니터링 도구를 제공한다.

 

`Resilience4j`를 사용하려면 gradle 의존성을 추가해야 한다.

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

그리고 `application.yml` 파일에서 관련 설정을 추가하거나 변경할 수 있다.

 

📌 Fallback 메커니즘

`Fallback` 메서드 정의 통해 외부 서비스 호출이 실패했을 시 대체 로직을 수행할 수 있다.

@Service
public class MyService {

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

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

이런 식으로 `fallbackMethod`에 실패 시 실행할 메서드 이름을 설정하면 된다.

이를 통해 장애가 발생해도 사용자에게 일정한 응답을 제공하고 다른 서비스에 장애가 전파되는 것을 막을 수 있다.

 

spring:
  application:
    name: my-service
  cloud:
    circuitbreaker:
      resilience4j:
        enabled: true

`Resilience4j`는 `Spring Cloud` 패키지의 일부로 다른 구성 요소와 쉽게 통합할 수 있다.

 

📌 서킷 브레이커 실습

이번 실습은 상품을 조회할 때 상품 아이디 111을 조회 시 에러를 발생시켜 `fallbackMethod`가 실행되는지 확인한다.

spring:
  application:
    name: sample

server:
  port: 19090

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초로 설정

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

`application.yml`

실패율이 50 프로가 넘어가면 서킷 브레이커가 동작한다.

서킷브레이커가 Open 상태가 되면 기존 메서드 대신 `Fallback` 메서드가 실행된다.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class ProductService {

    private final Logger log = LoggerFactory.getLogger(getClass());
    private final CircuitBreakerRegistry circuitBreakerRegistry;

    @CircuitBreaker(name = "productService", fallbackMethod = "fallbackGetProductDetails")
    public Product getProductDetails(String productId) {
        if ("111".equals(productId)) {
            throw new RuntimeException("Empty response body");
        }
        return new Product(
            productId,
            "Sample Product"
        );
    }

    public Product fallbackGetProductDetails(String productId, Throwable t) {
        return new Product(
            productId,
            "Fallback Product"
        );
    }
}

`fallbackGetProductDetails`는 `getProductDetails` 메서드가 실패할 때 호출된다. 해당 메서드는 안전한 대체 로직을 제공한다.

 

/products/111 을 3번 호출하면 서킷브레이커의 상태가 변경되는 것과 정상적으로 `Fallback` 메서드로 지정된 메서드가 실행되는 것을 알 수 있다.

 

 

반응형