본문 바로가기
IT/기타

chapter 15. 실패와 지연 처리하기 (책. Spring in Action)

by eddie_factory 2022. 3. 25.
반응형

15.1 서킷 브레이커 이해하기

서킷 브레이커 패턴 (circuit breaker pattern)

우리가 작성한 코드가 실행에 실패하는 경우 안전하게 처리되도록 한다.
마이크로 서비스의 실패가 다른 마이크로서비스의 연쇄적인 실패로 확산이 되는 걸 방지할 수 있다

어떤 이유로든 메서드의 실행이 실패하면, 서킷 브레이커가 개방되고 실패한 메서드에 대해 더이상 호출이 수행되지 않음.

이때 풀백을 제공해 자체적으로 실패를 처리한다.

 

  • 서킷브레이커로 보호되고 있는 메서드가 실행에 성공하면(Success) 서킷은 닫힘 상태를 유지한다.
  • 실패할 시 지금 실행되고 있는 실패한 메서드 대신 풀백 메서드가 호출되고 서킷 상태는 열림으로 바뀐다.
  • 때때로 서킷이 절반-열림 상태(half-open)로 바뀌면서 실패했던 메서드의 호출을 서킷 브레이커가 다시 시도한다.
  • 여전히 실패하면 서킷은 다시 열림 상태가 되고, 이후에는 다시 폴백 메서드가 호출된다.
  • 성공하면 닫힘 상태가 된다.

서킷 브레이커를 강화된 try/catch라고 생각하면 이해하는데 도움이 됨.

닫힘상태는 try, 폴백 메서드는 catch와 유사함. 그러나 서킷브레이커는 원래 호출하려던 메서드가 너무 자주 실패하면 폴백 메서드를 호출함.

 

서킷 브레이커는 메서드에 적용되며, 하나의 마이크로서비스에 많은 서킷 브레이커가 있을 수 있다. 서킷 브레이커를 사용할 수 있는 주요 메서드들이 있다.

  1. REST를 호출하는 메서드 (원격 서비스로 인해 실패)
  2. 데이터베이스 쿼리를 수행하는 메서드 (데이터베이스가 무반응 상태가 될 수 있거나 스키마 변경으로 인해 실패)
  3. 느리게 실행될 가능성이 있는 메서드 (필시 실패하는 메서드는 아지지만 너무 오랫동안 실행되면 비정상적 상태를 고려)

책에서 사용하는 서킷 브레이커 패턴은 NetFlix의 Hystrix로, 자바로 구현이 되었고 대상 메서드가 실패할 때 폴백 메서드를 호출하는 동시에 대상 메서드가 얼마나 실패를 하는지 추적하고, 실패율이 한계값을 초과하면 풀백 메서드를 호출한다.

 

15.2 서킷 브레이커 선언하기
pom.xl에 dependency 추가

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

 

그리고 스프링 클라우드의 버전도 지정해줌.

 

애플리케이션의 메인 클래스에 @EnableHystrix 애노테이션을 지정하면 활성화 됨.

@SpringBootApplication
@EnableHystrix
public class IngredientServiceApplication {
    ...
}

 

이후 서킷 브레이커를 사용할 메서드에 @HystrixCommand를 지정하고 폴백 메서드를 아래와 같이 지정할 수 있다.

@HystrixCommand(fallbackMethod="getDefaultIngredients")
public Iterable<Ingredient> getAllIngredients() {
...
}

위와 같이 선언 하고나면, 어떤 이유로든 unchecked 예외가 발생하여 getAllingredients() 메서드를 벗어나면 서킷브레이커가 해당 예외를 잡아서 폴백 메서드인 getDefualtIngredients()를 호출해준다.

폴백 메서드 자신도 서킷 브레이커를 가질 수 있다. 폴백 메서드로 지정한 메서드의 잠재적인 장애점이 있다면 또다른 메서드를 폴백메서드로 제공할수 있다. 다만 폴백 스택의 제일 마지막 실행에는 서킷브레이커가 필요없는 메서드가 있어야 함.

 

15.2.1 지연 시간 줄이기
서킷 브레이커는 메서드의 실행이 끝나고 복귀하는 시간이 너무 오래 걸릴 경우 타임아웃을 사용해 지연시간을 줄일 수 있다.

HystrixCommand를 지정하면 디폴트로 메서드는 1초후에 타임아웃이 되고 폴백메서드가 호출된다.
이유를 불문하고 타임아웃이 되면 무조건 풀백메서드를 호출한다고 보면 된다.

1초의 타임아웃은 대부분의 경우에 맞는 합리적인 값이지만 Hystrix는 commandProperties를 통해 속성을 지정하여 타임아웃을 변경할 수 있다. 

@HystrixCommand(
    fallbackMethod="getDefaultIngredients",
    commandProperties={
        @HystrixProperty(
            name="execution.isolation.thread.timeoutInMilliseconds",
            value="500")
    })
public Iterable<Ingredient> getAllIngredients() {
  ...
}
@HystrixCommand(
    fallbackMethod="getDefaultIngredients",
    commandProperties={
        @HystrixProperty(
            name="execution.timeout.enabled",
            value="false")
    })
public Iterable<Ingredient> getAllIngredients() {
  ...
}

위와 같이 타임아웃을 지정하거나, 지정하지 않을 수 있다.

 

15.2.2 서킷 브레이커 한계값 관리하기
서킷브레이커로 감싸진 메서드는 기본으로 10초 동안에 20번 이상 호출되고 이 중 50% 이상이 실패하면 열림 상태가 된다.
이후의 모든 호출은 폴백 메서드에 의해 처리되다가 5초후에 half-open 상태가 되어 원래 메서드 호출을 시도한다.

  • circuitBreaker.requestVolumeThreshold : 지정된 시간 내에 메서드가 호출되어야하는 횟수
  • circuitBreaker.errorThresholdPercentage : 지정된 시간 내에 실패한 메서드 호출 비율 (%)
  • metrics.rollingStats.timeInMilliseconds : 요청 횟수와 에러 비율이 고려되는 시간
  • circuitBreaker.sleepWinfowInMilliseconds : half-open 상태로 진입하여 실패한 메서드가 다시 시도되기 전에 열림 상태의 서킷이 유지되는 시간
@HystrixCommand(
    fallbackMethod="getDefaultIngredients",
    commandProperties={
        @HystrixProperty(
            name="circuitBreaker.requestVolumeThreshold",
            value="30"),
        @HystrixProperty(
            name="circuitBreaker.errorThresholdPercentage",
            value="25"),
        @HystrixProperty(
            name="metrics.rollingStats.timeInMilliseconds",
            value="20000")
		@HystrixProperty(
            name="circuitBreaker.sleepWindowInMilliseconds",
            value="60000")
    })
public List<Ingredient> getAllIngredients() {
  // ...
}

 

15.3 실패 모니터링하기
서킷 브레이커로 보호되는 메서드가 매번 호출될 때마다 해당 호출에 관한 여러 데이터가 수집되어 Hystrix 스트림으로 발행된다.
앞에서 말한 것처럼 이 스트림은 실행중인 어플리케이션의 상태를 실시간으로 모니터링하는데 사용할 수 있다.

  • 메서드가 몇 번 호출되는지
  • 성공적으로 몇 번 호출되는지
  • 풀백 메서드가 몇 번 호출되는지
  • 메서드가 몇 번 타임아웃되는지

이 Hystrix 스트림은 액추에이터 앤드포인트로 제공된다. 액추에이터 의존성을 빌드에 추가하고 application.yml에 구성 속성을 추가하면 Hystrix 스트림 엔드포인트가 활성화 된다.

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream

 

15.3.1 Hystrix 대시보드

Hystrix 대시보드 또한 스타터 의존성을 갖는 새로운 Spring boot 프로젝트를 생성, 애플리케이션 메인 클래스에 @EnableHystrixDashboard 애노테이션을 지정하면 대시보드를 확인 할 수 있다. 여기서는 각 서키브레이커의 메트릭을 확인 할 수 있다.

 

15.3.1 Hystrix 쓰레드풀 이해하기

어떤 메서드가 수행하는데 너무 오랜 시간이 걸리는 경우, 해당 서비스가 응답 할 때까지 Hystrix는 응답을 기다리면서 관련 스레드를 블로킹한다.

만일 그런 메서드가 호출자와 같은 스레드의 컨텍스트에서 실행 중이라면 호출자는 오래 실행되는 메서드로부터 벗어날 기회가 없다.

이런 상황을 방지하기 위해 Hystrix는 각 의존성 모듈의 스레드 풀을 할당한다. Hystrix 명령 메서드 중 하나가 호출될 때 이메서드는 Hystrix가 관리하는 스레드 풀의 스레드에서 실행된다. 따라서 이 메서드가 너무 오래걸린다면 호출 스레드는 해당 호출을 포기하고 벗어날 수 있으므로 잠재적인 스레드 포화를 Hystrix가 관리하는 스레드 풀에 고립시킬 수 있다.

 

요약

  • 서킷 브레이커 패턴은 유연한 실패처리를 할 수 있다.
  • Hystrix는 메서드가 실행에 실패하거나 너무 느릴 때 폴백 처리를 활성화하는 서킷 브레이커 패턴을 구현한다.
  • Hystrix가 제공하는 각 서킷 브레이커는 어플리케이션의 건강 상태를 모니터링할 목적으로 Hystrix 스트림의 메트릭을 발행한다.
  • Hystrix 스트림은 Hystrix 대시보드가 소비할 수 있다. Hystrix 대시보드는 서킷 브레이커 메트릭을 보여주는 웹 어플리케이션이다.
  • Turbine은 여러 애플리케이션의 Hystrix 스트림들을 하나의 Hystrix 스트림으로 종합하며, 종합된 Hystrix 스트림은 Hystrix 대시보드에서 볼 수 있다.
반응형

댓글