본문 바로가기
스터디/Spring

[Springboot] CircuitBreaker 적용방법(2) - 코드 적용

by zoodi 2023. 8. 18.
728x90

목차

  1. 1. CircuitBreaker 코드 적용하기
  2. 방법 1) 코드 적용 방식
  3. 방법 2) 어노테이션 방식

 

지난번 CircuitBreaker 적용방법(1)에 이어서 포스팅하겠습니다.

 

 

1. CircuitBreaker 코드 적용하기

방법 1) 코드 적용 방식

  • 연동 로직에 직접 CircuitBreaker를 적용하려면 먼저 적용대상 CircuitBreaker를 CircuitBreakerRegistry를 통해 구해야한다.
  • 연동 로직에 CircuitBreaker를 decorate 하도록 직접 코드를 적용한다.
  • 연동 대상 서버 API 호출 공통 로직에 적용 시 모든 API에 동일한 설정 적용이 가능하다.
  • https://resilience4j.readme.io/docs/examples

1) Create a CircuitBreakerRegistry

// Create a custom configuration for a CircuitBreaker
CircuitBreakerConfig defaultCircuitBreakerConfig = CircuitBreakerConfig.custom()
    .failureRateThreshold(50)
    .waitDurationInOpenState(Duration.ofMillis(1000))
    .permittedNumberOfCallsInHalfOpenState(2)
    .slidingWindowSize(2)
    .recordExceptions(IOException.class, TimeoutException.class)
    .ignoreExceptions(BusinessException.class, OtherBusinessException.class)
    .build();

// Create a CircuitBreakerRegistry with a custom global configuration
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(defaultCircuitBreakerConfig); // default config로 CircuitBreakerRegistry 생성

 

2) Create a CircuitBreaker

 

CircuitBreaker circuitBreaker = circuitBreakerRegistry
  .circuitBreaker("name");

 

3) Recover from an exception
CircuitBreaker가 failure로 기록하고 난 후 예외 recover 처리진행

// Given
CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("testName");

// When I decorate my function and invoke the decorated function
Supplier<String> checkedSupplier =
  CircuitBreaker.decorateSupplier(circuitBreaker, () -> {
	//기존 로직 작성
    throw new RuntimeException("BAM!");
  });

//fallback 처리
Try<String> result = Try.ofSupplier(checkedSupplier)
  .recover(throwable -> "Hello Recovery");

// Then the function should be a success, 
// because the exception could be recovered
assertThat(result.isSuccess()).isTrue();
// and the result must match the result of the recovery function.
assertThat(result.get()).isEqualTo("Hello Recovery");

 

반대로 예외 recover 진행 후 CircuitBreaker가 failure로 기록하게하고 싶다면 아래와 같이 수행

 

Supplier<String> supplier = () -> {
			//기존 로직 작성
            throw new RuntimeException("BAM!");
        };

//fallback 처리
Supplier<String> supplierWithRecovery = SupplierUtils
  .recover(supplier, (exception) -> "Hello Recovery");


String result = circuitBreaker.executeSupplier(supplierWithRecovery);

assertThat(result).isEqualTo("Hello Recovery");

방법 2) 어노테이션 방식

  • 연동 API 메소드 각각에 @CircuitBreaker 어노테이션을 적용하는 방식
  • 오류 발생시 호출될 fallback 메소드 지정이 가능하다.
  • 연동 대상 서버 API별 메소드 단위로 다른 설정의 circuitbreaker 적용하기 유용
  • https://resilience4j.readme.io/docs/getting-started-3
 

Getting Started

Getting started with resilience4j-spring-boot2 or resilience4j-spring-boot3

resilience4j.readme.io

@Service
@Slf4j
public class CircuitBreakerService {

	@CircuitBreaker(name = Resilience4jCode.CIRCUIT_TEST, fallbackMethod = "getCircuitBreakerFallback")
	public String getHello() {
		runtimeException();
		return "hello world!";
	}

	@Retry(name = Resilience4jCode.RETRY_TEST, fallbackMethod = "getRetryFallback")
	public String getRetry() {
		log.info("====== getRetry Request !! =======");
		runtimeException();
		return "hello world!";
	}

	private void runtimeException() {
		throw new RuntimeException("failed");
	}
	private String getCircuitBreakerFallback(Throwable t) {
		return "getCircuitBreakerFallback! exception type: " + t.getClass() + "message: " + t.getMessage();
	}

	private String getRetryFallback(Throwable t) {
		return "getRetryFallback! exception type: " + t.getClass() + "message: " + t.getMessage();
	}
}

 

참고: resilience4j grafana: https://resilience4j.readme.io/docs/grafana-1

728x90

댓글