2021. 7. 31. 23:32ㆍSpringBoot Monitoring/SpringBoot Resilience4j
Resilience4j의 CircuitBreaker에서 Count-based sliding window 예제를 통하여 어떻게 동작하는지 알아보도록 하겠습니다.
예제 프로그램은 order-service에서 payment-service 호출 시 CircuitBreaker의 상태 변화를 알아보도록 하겠습니다.
소스는 아래 사이트에서 받으실 수 있습니다.
https://github.com/roopy1210/spring-boot-resilience4j
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. 다이어그램 설명 및 테스트 결과
① 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 모니터링 결과를 보면 state 상태가 CLOSED 인 것을 확인할 수 있다.
grafana를 통하여서 확인해보아도 마찬가지로 CLOSED 상태인 것을 확인할 수 있다.
두번째로 payment-service 서버 실행 후 payment-service를 3번 호출한다.
결과를 보면 상태가 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_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번은 호출 되어야 실패율이 계산된다.
[테스트 결과]
위의 그림은 CLOSED → OPEN 상태로 변경된 것을 확인할 수 있다.
실패율 계산식
실패율 = 실패횟수/minimumNumberOfCalls* 100
나머지 상태 변화는 Count-based sliding window와 동일하다.
02. CircutBreaker 적용 결과 화면
CircuitBreaker 가 정상적으로 동작 하였다면 아래와 같이 FallBack 메서드에 작성한 메시지가 정상적으로 보일 것이다.
반대로 CircuitBreaker가 정상적으로 작동 하지 않는다면 기존에 500 에러 페이지가 보일 것이다.
※ Grafana dashboard json 파일은 아래 사이트에서 다운로드할 수 있습니다.
https://github.com/resilience4j/resilience4j/blob/master/grafana_dashboard.json
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 |