ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Circuit Breaker 소개/동작원리와 resilience4j-circuitbreaker 사용법
    개발/기타 2021. 5. 7. 02:02

    서킷브레이커 도입 배경

    • 마이크로 서비스 구조는 여러개의 서비스 모듈로 구성하여 서비스 모듈간에 호출하는 방식
    • 마이크로 서비스 구조의 장점은 유연한 확장성과 개발 속도 향상, 기술적 자유 등등
    • 단점으로는 모듈이 느려지거나 장애가 발생할 경우 그에 종속된 모듈까지도 장애가 전파되는 문제
    • 특정 모듈 장애가 발생하여 해당 모듈 요청 지연이 발생하고 이여파로 서비스가 종료되는 문제를 방지하기위해 도입

    서킷브레이커?

    • 개별 모듈 장애로 인한 서비스 장애를 방지하기 위해 나온패턴이 서킷브레이커
    • 전기 회로 차단기의 개념을 차용한 패턴으로 전기 흐름에 문제없으면 close
    • 문제가 생기면 open하여 흐름을 차단

    서킷브레이커 패턴에는 1가지 상태가 추가되어, 총 3개의 상태가 존재

    • 정상 상태 : Closed
    • 오류 상태 : Open
    • 반열림 상태 : Half Open (일부 request만 실행해보면서 기능이 다시 정상적으로 동작하는지 확인하는 과정)

     

    3가지 상태 전환 과정

    • Closed 상태
      • 특정 모듈이 요청한 결과(성공/실패)를 기록.
      • 실패 횟수(또는 시간)가 임계치에 도달했을시 Open 상태로 전환
    • Open 상태
      • 지정된 시간만큼 open 상태를 유지하며
      • 요청에 대해 지정된 결과를 응답한다.(예외를 던지거나 임시복구 데이터를 응답한다.)
    • Half Open 상태
      • Open 상태가 종료되면, 조금씩 요청을 받아 처리한다.
      • 요청 결과가 성공적이면 Closed 상태로 전환

    어떤 라이브러리를 사용했나?

    • 넷플릭스에서 개발한 Hystrix가 있는데 개발하지않고 유지보수만한다고 함. resilience4j를 추천.
    • resilience4j는 hystrix의 경량화된 버전으로 사용하기 쉽고, 자유도도 높다
      • https://github.com/resilience4j/resilience4j
      • functional interface, lambda 등을 지원
      • 조절 가능한 bit buffer와 실행 결과를 제거하지 않기때문에, 요청 빈도와 상관없이 이용 가능
      • half-open 상태에서 요청 수행 횟수와 임계값을 설정 가능
    • 이외에 Retry, RateLimiter, TimeLImiter, BulkHead(동시 실행 제어) 기능이 있음.

    resilience4j 사용 예

    CircuitBreakerConfig config = CircuitBreakerConfig.custom()
                    // 오류 발생한 요청들의 백분율을 임계값으로 설정. 
    		// 실패율이 임계값보다 크거나 같으면 open상태로 전환.
    		// 예) 80% 이상 실패하면 상태 전환
                    .failureRateThreshold(80)
    				
                    // 응답 지연으로 실패한 요청들의 백분율을 임계값으로 설정. 
    		// 응답 지연율이 임계값보다 크거나 같으면 open상태로 전환
    		// 예) 60% 이상 실패하면 상태 전환
                    .slowCallRateThreshold(60)
    				
    		// 응답 지연 시간의 임계값
    		// 예) 응답이 5초이상 소요되면 실패로 간주.
                    .slowCallDurationThreshold(Duration.ofSeconds(5))       
    				
    		// open 상태 유지 기간
    		// 예) 30초간 유지
                    .waitDurationInOpenState(Duration.ofSeconds(30))    
    				
                    // halfOpen상태에서 허용가능한 요청 수
    		// 예) open => halfOpen으로 전환된 상태에서, 3개 요청에 대해서만 실제 API 요청.
                    .permittedNumberOfCallsInHalfOpenState(3)
    				
                    // 실패율 계산하기 위한 최소한의 요청수
    		// 예) 최소 5번 요청이 있어야 실패율을 계산. 
                    .minimumNumberOfCalls(5)
    				
    		// 버퍼 사이즈
                    .slidingWindowSize(5)
    
    		// 슬라이딩윈도우 타입
    		// 시간 기반, 횟수 기반으로 구분.
                    .slidingWindowType(SlidingWindowType.TIME_BASED)
    				
    		// 자동으로 open -> halfopen 으로 전환
                    .enableAutomaticTransitionFromOpenToHalfOpen()
                    .build();
    
    CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config);
    CircuitBreaker testCircuitBreaker = registry.circuitBreaker("test")

     

    실행

    interface BackService {
    	String getName();
    }
    
    BackService backService = new BackService();
    
    CircuitBreaker breaker = registry.circuitBreaker("test")
    
    // 기본값으로 최대 3회 재시도.
    Retry retry = Retry.ofDefaults("test");
    
    
    // 호출할 메소드와 데이터형 설정
    Supplier<String> decoratedSupplier= CircuitBreaker.decorateSupplier(breaker , backService::getName);
    
    // 호출 실패시, 3회 재시도 설정
    decoratedSupplier = Retry.decorateSupplier(retry, decoratedSupplier);
    
    // 예외 발생시 복구할 데이터 설정
    Try recovery = Try.ofSupplier(decoratedSupplier).recover(throwable -> "Hello from Recovery");
    
    // 요청 (실패하면 "Hello from Recovery" 리턴)
    String result = recovery.get();

     

    참고

    https://netflixtechblog.com/introducing-hystrix-for-resilience-engineering-13531c1ab362
    https://github.com/Netflix/Hystrix
    https://medium.com/@NetflixTechBlog/performance-under-load-3e6fa9a60581
    https://github.com/Netflix/concurrency-limits

Designed by Tistory.