스프링 서킷 브레이커

greenTea·2023년 12월 18일
0

스프링 서킷 브레이커

기본 개념

서킷 브레이커란?
서킷 브레이커는 문제가 발생할 경우 서비스의 호출을 차단하고 fallback 메소드를 이용할 수 있도록 하는 패턴으로 서비스 호출이 실패하거나 지정된 임계값을 초과할 때, 서킷 브레이커는 OPEN 상태가 되어 후속 호출을 차단하고, 시스템이 회복될 때까지 대기합니다.

  1. 닫힘(Closed) 상태:

    • 서킷 브레이커는 기본적으로 닫힌 상태에서 시작합니다.(정상 상태)
    • 실패율이 정해진 값을 초과하면 서킷 브레이커는 OPEN 상태로 전환됩니다.
  2. 열림(Open) 상태:

    • 서킷 브레이커가 열린 상태가 되면, 모든 요청은 차단되고 즉시 실패로 처리됩니다.
  3. 반열림(Half-Open) 상태:

    • 이 상태에서는 제한된 수의 요청만 허용됩니다.
    • 실패율이 정해진 값을 넘어가면 다시 OPEN 상태로 전환됩니다. 반대의 경우에는 CLOSED로 전환

예시 코드

Controller

@RequiredArgsConstructor
@RestController
public class MyController {

	private final MyService myService;

	@GetMapping("/hello")
	public Mono<String> first(int point) {
		return myService.createPoint(point);
	}
}

단순한 point 값을 받는 컨트롤러입니다.
들어온 point를 service로 넘겨줍니다.

Service

@RequiredArgsConstructor
@Slf4j
@Service
public class MyService {

	private final ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory;

	public Mono<String> createPoint(int point) {
		return doPoint(point)
			.transform(it -> {
				return reactiveCircuitBreakerFactory.create("createPoint")
													.run(it, throwable -> Mono.just("circuit breaker!!!"));
			});
	}

	public Mono<String> doPoint(int point) {

		Mono<String> flux = Mono.just(String.valueOf(point));
		if (point >= 10) {
			return flux.flatMap(i -> Mono.error(new RuntimeException("error")));
		}

		return flux;
	}

}

이 예시에서는 MyService 클래스에서 createPoint()는 들어오는 point에 따라서 에러를 내거나 그대로 값을 반환하는 메소드입니다.
point 값에 따라 성공 또는 실패 응답을 반환합니다.

여기서 reactiveCircuitBreakerFactory.create("createPoint")는 서킷 브레이커 인스턴스를 생성합니다. 이 인스턴스는 doPoint 메소드의 실행을 감시하고, 정의된 임계값에 도달하면 서킷을 OPEN 상태로 전환합니다.

설정

application.yml 파일에서 서킷 브레이커의 동작을 세부적으로 설정할 수 있습니다.

resilience4j:
  circuitbreaker:
    instances:
      createPoint:
        slidingWindowType: COUNT_BASED
        slidingWindowSize: 4
        automatic-transition-from-open-to-half-open-enabled: true
        wait-duration-in-open-state: 60s
        failureRateThreshold: 50
        permittedNumberOfCallsInHalfOpenState: 2
        registerHealthIndicator: true

yml 파일을 통해 circuitbreaker의 설정값을 작성할 수 있습니다.

  • slidingWindowType: 최근 N번의 호출을 기반으로 실패율을 계산합니다.(COUNT_BASED)
  • slidingWindowSize : 요청 개수의 총 사이즈를 설정합니다.
  • failureRateThreshold : 실패율을 설정합니다. 만약 4개중 2개를 실패한 경우 실패율은 50%로 CLOSED 상태로 전환합니다.
  • automatic-transition-from-open-to-half-open-enabled: true로 설정시 OPEN상태에서 일정 시간 후 자동으로 HALF-OPEN 상태로 전환됩니다.
  • wait-duration-in-open-state: OPEN에서 몇 초 후에 HALF-OPEN으로 갈지 설정합니다.
  • permittedNumberOfCallsInHalfOpenState: HALF-OPEN 상태에서 몇개의 요청을 처리 할 것인지를 정할 수 있습니다. (slidingWindowSize와 비슷)

모니터링

스프링 부트 액추에이터를 사용하여 서킷 브레이커의 상태를 모니터링할 수 있습니다. application.yml 파일에 다음 설정을 추가하여 서킷 브레이커의 상태를 확인할 수 있습니다.

management:
  health:
    circuitbreakers:
      enabled: true
  endpoint:
    health:
      show-details: always

이 설정을 통해 /actuator/health 엔드포인트를 호출하면 서킷 브레이커의 상태 정보를 얻을 수 있습니다.

요청

http://localhost:8080/actuator/health를 통해 circuitBreaker의 상태를 확인 할 수 있습니다.

  1. CLOSED 상태

기본적으로 "CLOSED" 상태로 정상적으로 요청을 받을 수 있는 상태입니다.

이제 실패 요청을 slidingwindow 만큼 보내서 의도적으로 fail시키겠습니다.

  1. OPEN 상태

state를 보면 4번의 실패 요청을 통해서 failurRate가 100%를 찍은 것을 볼 수 있습니다. 또한 상태가 OPEN으로 변한 것을 볼 수 있습니다.

  1. HALF-OPEN

yml에서 half-open으로 자동으로 변경되게끔 하였기에 기다린다면 위와 같이 HALF-OPEN 상태가 됩니다.

결론

스프링 클라우드와 Resilience4j를 사용한 서킷 브레이커 구현은 마이크로서비스 아키텍처에서 서비스 간의 안정성과 탄력성을 향상시키는 데 중요한 역할을 합니다. 이러한 패턴을 적용함으로써, 시스템 전체의 안정성을 보장하고, 잠재적인 문제가 전체 시스템에 미치는 영향을 최소화할 수 있습니다.

참고자료

Spring Webflux 완전 정복 : 코루틴부터 리액티브 MSA 프로젝트까지

profile
greenTea입니다.

0개의 댓글