Today
-
Yesterday
-
Total
-

ABOUT ME

-

  • Spring Cloud MSA - 5 | Circuit Breaker, Resilience4J 구현하기
    ▼ Backend/└ MSA, Spring Cloud 2021. 12. 3. 17:59
    반응형

     

    ▶ Circuit Breaker란

    어떤 서비스가 과부하 또는 장애가 발생하였을 때 그 서비스를 호출하는 다른 서비스들의 연쇄적인 장애를 막기 위해 미리 차단하여 전체 서비스에 영향이 없게 방지하기 위한 기능이다.

     

    대표적인 Circuit Breaker 중 하나인 Netflix Hystrix를 사용하려고 했으나 Deprecated 되어 있는 걸 확인했다. 스프링 블로그를 찾아보니 아래의 Netflix 프로젝트들이 Entering Maintenance Mode (Spring Cloud 팀이 더 이상 모듈에 새로운 기능을 추가하지 않는다는 것을 의미) 된다는 내용이 있었다. 삭제가 되어 사용이 불가능한 것은 아니지만, 새로운 프로젝트 환경에서는 Resilience4J를 사용하는 것을 대안으로 하고 있다고 한다.

     

    Resilience4J는 Netflix Hystrix에서 영감을 받은 가볍고 사용하기 쉬운 내결함성 라이브러리로 Java 8 및 함수형 프로그래밍을 위해 설계되었다고 한다.

     

    Deprecated, EnableCircuitBreaker

     

    Spring Cloud Netflix Projects Entering Maintenance Mode

    • spring-cloud-netflix-archaius
    • spring-cloud-netflix-hystrix-contract
    • spring-cloud-netflix-hystrix-dashboard
    • spring-cloud-netflix-hystrix-stream
    • spring-cloud-netflix-hystrix
    • spring-cloud-netflix-ribbon
    • spring-cloud-netflix-turbine-stream
    • spring-cloud-netflix-turbine
    • spring-cloud-netflix-zuul

    build.gradle

    implementation 'io.github.resilience4j:resilience4j-spring-boot2'
    implementation 'org.springframework.boot:spring-boot-starter-aop'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'

     

    application.yml

    #resilience4j
    resilience4j.circuitbreaker:
        configs:
            default:
                slidingWindowSize: 100
                permittedNumberOfCallsInHalfOpenState: 10
                waitDurationInOpenState: 5000
                failureRateThreshold: 50
                eventConsumerBufferSize: 10
                registerHealthIndicator: true
        instances:
            venhMsa: # 인스턴스명
                baseConfig: default
                
    #actuator
    management:
      endpoints:
        web:
          exposure:
            include: "*"
      endpoint:
        shutdown:
          enabled: true
        health:
          show-details: always # actuator에서 디테일한 정보들을 확인하기 위해 설정
      health:
        circuitbreakers:
          enabled: true # actuator를 통해 circuitbraker 상태를 확인하기 위해 설정

     

     

    추가적인 설정과 가이드 레퍼런스
    https://resilience4j.readme.io/docs/circuitbreaker

     

    Config-Name Default Description
    slidingWindowSize 100 서킷의 상태가 CLOSED일 때 요청의 결과를 기록하기 위한 sliding window 크기 설정
    permittedNumberOfCallsInHalfOpenState 10 회로가 반-개방 상태일 때, 받아들일 요청의 개수를 지정
    waitDurationInOpenState 60000[ms] 서킷브레이커가 open에서 half-open으로 전환하기 전 대기 시간
    failureRateThreshold 50 실패 비율 threshold를 설장한다.
    해당 값보다 같거나 클 경우 Circuit을 open한다.
    eventConsumerBufferSize 10 이벤트가 발행되면, 해당 버퍼에 저장되는데 그 크기를 지정한다.
    registerHealthIndicator true actuator를 통해 circuitbraker 상태를 확인하기 위해 설정

     

    마이크로 서비스 A

    RestTemplate를 통해 서비스 간의 호출을 한다.

    마이크로 서비스 A의 ~/venh-msa-call/support를 통해 마이크로 서비스 B의 /venh-msa-support를 호출할 것이다.

    이 과정을 통해 비정상적인 응답을 발생하게 만들어 CircuitBreaker가 어떻게 작동하는지 확인한다.

     

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    import com.venh.msa.service.ConfigService;
    
    @RestController
    @RefreshScope
    public class ConfigController {
    
        @Autowired
        private ConfigService configService;
    
        @Value("${venh.test}")
        private String str;
    
        @GetMapping("/test")
        public String test() {
            return str;
        }
    
        @GetMapping("/venh-msa/{param}")
        public String getVenhMsa(@PathVariable String param) {
            return "VenhMsa Param : " + param;
        }
    
        @GetMapping("/venh-msa-call/support/{param}")
        public String getVenhMsaSupport(@PathVariable String param) {
            return configService.getVenhMsaSupport(param);
        }
    }

     

     

    RestTemplate를 이용하여 마이크로 서비스 B를 호출한다.

     

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
    
    @Service
    public class ConfigService {
    
        @Autowired
        private RestTemplate restTemplate;
    
        // application.yml에 적용한 instance 이름
        private static final String CIRCUIT_INSTANCES = "venhMsa";
    
        @CircuitBreaker(name = CIRCUIT_INSTANCES, fallbackMethod = "getVenhMsaSupportFallBack")
        public String getVenhMsaSupport(String param) {
            String url = "http://localhost:8090/venh-msa-support/" + param;
            return restTemplate.getForObject(url, String.class);
        }
    
        public String getVenhMsaSupportFallBack(Throwable t) {
            return "== > getVenhMsaSupportFailBack : " + t.getClass();
        }
    }

     

    마이크로 서비스 B

    테스트를 위해 param을 넘겨받아 해당 param이 fail일 경우에 RuntimeException을 발생시켜본다.

     

    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class SupportController {
    
        @GetMapping("/venh-msa-support/{param}")
        public String getVenhMsa(@PathVariable String param) {
            if (param.equals("fail")) {
                throw new RuntimeException("failed");
            }
            return "Call Success VenhMsa Support Param : " + param;
        }
    }

     

    테스트

    정상적인 Parameter 호출

     

    고의적으로 fail을 넘겨 RuntimeException 발생 시킨다.

     

    CircuitBreaker가 걸리면 정상적인 호출을 해도 일시적으로 제한

    CircuitBreaker가 작동하면 application.yml에 설정된 waitDurationInOpenState 시간이 지난 후 half-open 상태가 된다. 그 후에 정상적인 Parameter로  호출 시 응답하지만 요청수가 permittedNumberOfCallsInHalfOpenState (회로가 반-개방상태 일 때 받아 들 일요청의 개수를 지정) 설정에 의해 조정된다.

     

    CircuitBreaker 후 정상적인 Parameter를 요청해도 응답하지 않는다.

     

    health 상태 확인 (/actuator/health)

    CircuitBreaker CLOSED

     

     

     

    CircuitBreaker OPEN

     

     

    GitHub

     

    Reference - CircuitBreaker

     

    반응형

    댓글

Designed by Tistory.