본문 바로가기
Spring

뭐? MSA? 그렇다면 장애 전파를 막아보자! Circuit Breaker. - 03

by zkdlu 2021. 4. 16.

Circuit Breaker

MSA는 서비스에 장애가 발생할 경우 이 서비스에 종속된 다른 서비스까지 장애가 전파될 수 있습니다. Circuit Breaker는 회로차단기라는 의미로 MSA에서는 이 Circuit Breaker패턴을 사용해 위와같은 문제를 해결하였습니다. Circuit Breaker는 A라는 서비스에 장애가 발생하면 이 서비스를 호출하는 B 서비스가 A 서비스를 호출할 때 즉각적으로 호출을 끊어 스레드를 점유하지 않도록 해줍니다.

Netflix는 Circuit Breaker 또한 오픈소스로 Hystrix라는 자바 라이브러리를 제공해주고 있습니다.

Hystrix

귀엽네..

Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.

Hystrix는 분산환경을 위한 Latency and Fault Tolerance 시스템으로 Circuit Breaker, Fallback, Thread Isolation, Timeout 등 4가지의 주요 기능을 가지고 있습니다.

 

그러면 앞서 만들었던 Display Service에 Hystrix를 적용해주겠습니다. 먼저 Hystrix를 사용하기 위해서는 아래의 의존성을 추가해주어야 합니다.

ext {
    set('springCloudVersion', "Hoxton.SR9")
}

dependencies {
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

그 후 @EnableCircuitBreaker 어노테이션을 사용해 Circuit Breaker를 활성화 하고, 메서드에 HystrixCommand 어노테이션을 추가해 Circuit Breaker를 사용한다. HystrixCommand는 같은 commandKey를 가진 메서드를 그룹으로 통계가 내어집니다. commandKey를 지정하지 않으면 default가 기본설정이 되고, timeout을 넘겨 장애 통계가 정해진 threshold를 넘기면, 호출을 즉시 차단하고, fallbackMethod를 사용합니다.

 

아래 코드는 Product 서비스에 장애가 발생한 경우 fallback method에서는 빈 배열을 반환해줍니다.

@EnableCircuitBreaker
@SpringBootApplication
public class DisplayApplication {
    ...
}

@Service
public class DisplayService {
    private final RestTemplate restTemplate;

    public DisplayService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @HystrixCommand(fallbackMethod = "getProductFallback")
    public List<Product> getProducts() {
        var products = restTemplate.getForObject("http://localhost:8081/products", Product[].class);

        return Arrays.asList(products);
    }
    
    public String getProductFallback(Throwable throwable) {
        return Collections.singletonList(Product.Empty);
    }
}

 

Command Key별 상세한 통계 조건은 application.yml에서 작성합니다. 

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000 
      circuitBreaker:
        requestVolumeThreshold: 1 # 감시 시간 내 요청 수, 기본값 20
        errorThresholdPercentage: 50 # 요청 대비 오류율, 기본값 50

 

Feign Client에 Hystrix 적용하기

Feign Client에서 Hystrix를 이용하기 위해서는 몇가지 작업이 필요합니다. 먼저 Feign Client에 Fallback Method를 만들어야 하는데 우리가 만든 Feign Client는 인터페이스 만을 가지고 있습니다. 그렇다면 메서드는 어디서 작업하면 될까요?

 

간단합니다. 그냥 Feign Client 인터페이스의 구현체를 만들고 Fallback method를 정의해줍니다. 그 후 Feign Client에 Fallback

@Component
public class FeignProductServiceFallbackImpl implements FeignProductService {
    @Override
    public List<Product> getProducts() {
        return Collections.singletonList(Product.Empty);
    }
    
    ...
}

@FeignClient(name = "product", 
             url = "http://localhost:8081/", 
             fallback = FeignProductServiceFallbackImpl.class)
public interface FeignProductService {
    @RequestMapping(path = "/products/{productId}")
    Product getProduct(@PathVariable("productId") String productId);
    
    @RequestMapping(path = "/products")
    List<Product> getProducts();
}

 

application.yml에 feign이 hystrix를 사용할 수 있도록 설정을 변경해주고 feign client에 대한 hystrix 설정을 해줍니다. Feign Client는 Command Key로 {fegin client}#{method(param)} 의 형태로 만들어집니다.

feign:
  hystrix:
    enabled: true

hystrix:
  command:
    FeignProductService#getProducts():
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000
      circuitBreaker:
        requestVolumeThreshold: 1
        errorThresholdPercentage: 50

 

github.com/zkdlu/spring-boot/tree/main/spring-service

 

zkdlu/spring-boot

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

github.com