CircuitBreaker 예제

2021. 7. 31. 23:32SpringBoot Monitoring/SpringBoot Resilience4j

반응형

Resilience4j의 CircuitBreaker에서 Count-based sliding window 예제를 통하여 어떻게 동작하는지 알아보도록 하겠습니다.

 

예제 프로그램은 order-service에서 payment-service 호출 시 CircuitBreaker의 상태 변화를 알아보도록 하겠습니다.

 

소스는 아래 사이트에서 받으실 수 있습니다.

https://github.com/roopy1210/spring-boot-resilience4j

 

GitHub - roopy1210/spring-boot-resilience4j

Contribute to roopy1210/spring-boot-resilience4j development by creating an account on GitHub.

github.com

 

Count-based sliding window

아래 설정 파일은 Count-based sliding window에 대한 설정이다.

 

[application.yml]

spring:
  application.name: order-service
  output.ansi.enabled: always

server:
  port: 7070

management.endpoints.web.exposure.include: '*'
management.endpoint.health.show-details: always

# Spring actuator 에 circuitbreaker 정보를 표시하기 위한 설정
management.health.circuitbreakers.enabled: true

#--------------------------------------------------------------------------------
# CircuitBreaker COUNT_BASED Configuration
#--------------------------------------------------------------------------------
# 1. STATUS: OPEN 으로 변경되는 경우
#    - minimumNumberOfCells = 6 이고 failureRateThreshold = 50% 이상인경우 
#      이므로 payment-service호출을 6번 중에 4번실패하는 경우
#    - minimumNumberOfCalls 이 slidingWindowSize 보다 큰 경우 slidingWindowSize 
#       기준으로 실패율이 계산된다.
#
# 2. STATUS: HALF_OPEN 으로 변경되는 경우
#    - waitDurationInOpenState 가 30초로 설정 되어있기 때문에 OPEN 상태에서 30초
#      후 HALF_OPEN 으로 변경
#
# 3. STATUS: CLOSED 으로 변경되는 경우
#    - permittedNumberOfCallsInHalfOpenState = 5 로 설정 되어 있기 때문에 
#      HALF_OPEN 상태에서 payment-service 가 성공/실패 상관 없이 5번 
#      호출 되는 경우
# -------------------------------------------------------------------------------
resilience4j:
  circuitbreaker:
    instances:
      orderService:
      	registerHealthIndicator: true
      	slidingWindowSize: 10
     	permittedNumberOfCallsInHalfOpenState: 5
      	slidingWindowType: COUNT_BASED
      	minimumNumberOfCalls: 6
      	failureRateThreshold: 50
      	waitDurationInOpenState: 30s
      	automaticTransitionFromOpenToHalfOpenEnabled: true
      	eventConsumerBufferSize: 10

instance 아래 orderService는 @CircuitBreaker(name = "orderService", fallbackMethod = "orderFallback")의 name의 이름을 적어주면 된다.

 

01. 다이어그램 설명 및 테스트 결과

 

CircuitBreaker 상태변화 다이어그램

 

① CLOSED → OPEN 상태로 변하는 경우

위의 다이어그램을 보면 failure rate above a threshold  인 경우 OPEN으로 변경된다고 정의되어 있다.

application.yml의 failureRateThreshold: 50으로 설정되어있기 때문에 50% 이상인 경우 OPEN 상태로 변경

 

설정에서 minimumNumberOfCalls: 6으로 설정되어 있는데 이 의미는 만약 order-service에서 payment-service를 5번 호출하였다고 하면 상태변화에는 아무런 영향을 끼치지 않습니다. 6번째 호출될 때 그 시점에 성공/실패 횟수를 계산하여서 비율을 계산하게 됩니다.

 

그리고 miimumNumberOfCalls의 값이 slidingWindowSize 보다 크다면 횟수 체크는 slidingWindowSize의 설정 값을 따라가게 됩니다.

 

그러면 order-service에서 payment-service를 총 6번 호출하였고 3번은 성공 3번은 실패하였다고 할 때 비율은 3/6 * 100 = 50% 가 되므로 CircuitBreaker의 상태는 OPEN으로 변할 것입니다.

 

[테스트 결과]

 

테스트를 위해서 처음에는 order-service 서버만 실행 후 payment-service 를 3번 호출한다.

actuator health 모니터링 결과

위의 그림은 actuator 모니터링 결과를 보면 state 상태가 CLOSED 인 것을 확인할 수 있다.

 

grafana를 통하여서 확인해보아도 마찬가지로 CLOSED 상태인 것을 확인할 수 있다.

 

두번째로 payment-service 서버 실행 후 payment-service를 3번 호출한다.

actuator health 모니터링 결과

결과를 보면 상태가 OEPN 상태로 변한 것을 확인할 수 있다.

결과의 failureRate가 failureRateThreshold를 50%로 설정하였기 때문에 상태가 바뀐 것이다.

grafana 모니터링 화면을 확인해도 OPEN 상태로 변한 것을 확인할 수 있다.

 

② OPEN → HALF_OPEN 상태로 변하는 경우 

위의 다이어그램을 보면 after wait duration 인 경우 OPEN으로 변경된다고 정의되어 있다. 

application.yml의  waitDurationInOpenState: 30s으로 설정되어 있는데 이 의미는 OPEN 상태에서 30초가 지나면 HALF_OPEN 상태로 변한다는 의미이다. 단 automaticTransitionFromOpenToHalfOpenEnabled: true 설정이 되어 있어야 한다.

 

[테스트 결과]

 

OPEN 상태에서 30초 지난 후 HALF_OPEN 상태로 변경

HALF_OPNE 상태

모든 값은 초기화되고 상태는 HALF_OPEN 상태인 것을 확인할 수 있다.

grafana 모니터링 화면을 확인해도 HALF_OPEN 상태로 변한 것을 확인할 수 있다.

 

③ HALF_OPEN → CLOSED 또는 HALF_OPEN → OPEN 상태로 변하는 경우

위의 다이어그램을 보면 failure rate below a threshold 인 경우 CLOSED로 변경된다고 정의되어 있다. 

① 번과 동일하게 비율 계산은 같으나 단 50% 실패율이 50% 이하인 경우 CLOSED로 변경되고 그 반대인 50% 이상인 경우 다시 HALF_OPEN 상태로 변경된다.

 

실패율 계산식

실패율 = 실패횟수/slidingWindowSize or minimumNumberOfCalls* 100

분모 값이 slidingWindowSize < minimumNumberOfCalls경우이면 slidingWindowSize 반대이면 minimumNumberOfCalls 값을 사용한다.

 

Time-based sliding window

 

[application.yml]

#---------------------------------------------------------------
# CircuitBreaker TIME_BASED Configuration
#---------------------------------------------------------------
# 1. STATUS: OPEN 으로 변경되는 경우
#    - slidingWindowSize 값이 10으로 설정 되어 있으므로 10초동안 
#      6번이상 호출되고 payment-service 호출 실패가 50% 이상인 
#      경우
#
# 2. STATUS: HALF_OPEN 으로 변경되는 경우
#    - waitDurationInOpenState 가 30초로 설정 되어있기 때문에 
#      OPEN 상태에서 30초후 HALF_OPEN 으로 변경
#
# 3. STATUS: CLOSED 으로 변경되는 경우
#    - permittedNumberOfCallsInHalfOpenState = 5 로 설정 되어 
#      있기 때문에 HALF_OPEN 상태에서 payment-service 가 
#      성공/실패 상관 없이 5번 호출 되는 경우
# --------------------------------------------------------------
resilience4j:
  circuitbreaker:
    instances:
      orderService:
        registerHealthIndicator: true
        slidingWindowSize: 10
        permittedNumberOfCallsInHalfOpenState: 5
        slidingWindowType: TIME_BASED
        minimumNumberOfCalls: 6
        failureRateThreshold: 50
        waitDurationInOpenState: 30s
        automaticTransitionFromOpenToHalfOpenEnabled: true
        eventConsumerBufferSize: 10

Count-based sliding window 와 설정 자체는 크게 다르지 않다.

차이점은 slidingWindowSize가 N초를 의미한다.

그리고 slidingWindowType이 TIME_BASED 로 설정되어 있다.

 

실패율을 구할 때는 위의 설정을 보면 10초 동안 6번은 호출 되어야 실패율이 계산된다.

 

[테스트 결과]

OPEN 상태

위의 그림은 CLOSED → OPEN 상태로 변경된 것을 확인할 수 있다.

 

실패율 계산식

실패율 = 실패횟수/minimumNumberOfCalls* 100

 

나머지 상태 변화는 Count-based sliding window와 동일하다.

 

02. CircutBreaker 적용 결과 화면

CircuitBreaker 가 정상적으로 동작 하였다면 아래와 같이 FallBack 메서드에 작성한 메시지가 정상적으로 보일 것이다.

CircuitBraker 정상작동한 경우

 

반대로 CircuitBreaker가 정상적으로 작동 하지 않는다면 기존에 500 에러 페이지가 보일 것이다.

CircuitBreaker가 정상작동 하지 않은 경우

 

 

 

 

 

※ Grafana dashboard json 파일은 아래 사이트에서 다운로드할 수 있습니다.

https://github.com/resilience4j/resilience4j/blob/master/grafana_dashboard.json

 

GitHub - resilience4j/resilience4j: Resilience4j is a fault tolerance library designed for Java8 and functional programming

Resilience4j is a fault tolerance library designed for Java8 and functional programming - GitHub - resilience4j/resilience4j: Resilience4j is a fault tolerance library designed for Java8 and functi...

github.com

Import 방법은 https://jydlove.tistory.com/70 글을 참고하시면 됩니다.

 

 

반응형

'SpringBoot Monitoring > SpringBoot Resilience4j' 카테고리의 다른 글

RateLimiter 예제  (0) 2021.08.22
Bulkhead 예제  (0) 2021.08.15
Retry 예제  (0) 2021.08.07
CircuitBreaker 개념  (0) 2021.07.31