서킷 브레이커 이해하기

  • 서킷 브레이커 패턴은 우리가 작성한 코드가 실행에 실패하는 경우에 안전하게 처리되도록 해준다.
    • 마이크로서비스의 경우, 한 마이크로서비스의 실패가 다른 마이크로서비스의 연쇄적인 실패로 확산되는 것을 방지해야 하기 때문에 더 중요하다.
  • 서킷 브레이커는 메서드의 호출을 허용하며, 서킷은 닫힘 상태에서 시작된다.
    • 어떤 이류로 실패하면, 서킷 브레이커가 개방되고 실패한 메서드에 더 이상 호출이 수행되지 않는다. 대신 폴백을 제공하여 자체적으로 실패를 처리한다.
    • 개방 상태의 서킷이 때때로 절반-열림 상태로 바뀌면서 실패했던 메서드의 호출을 서킷 브레이커가 다시 시도한다.
      • 여전히 실패하면, 서킷은 다시 열림 상태가 되고, 이후에 다시 폴백 메서드가 호출된다.
      • 성공하면, 문제가 해결된 것으로 간주하여 서킷은 닫힘 상태가 된다.
  • 주로 서킷 브레이커를 선언할 후보들
    • REST를 호출하는 메서드: 사용할 수 없거나 HTTP 500 응답을 반환하는 원격 서비스로 인해 실패할 수 있는 메서드다.
    • 데이터베이스 쿼리를 수행하는 메서드: 어떤 이유로든 데이터베이스가 무반응 상태가 되거나, 애플리케이션을 중단시킬 수 있는 스키마의 변경이 생기면 실패할 수 있는 메서드다.
    • 느리게 실행될 가능성이 있는 메서드: 너무 오랫동안 실행된다면 비정상적인 상태를 고려할 수 있다.(지연 문제)
  • Netflix 오픈 소스 프로젝트가 Hystrix 라이브러리를 사용하여 서킷 브레이크 패턴을 제공한다.

서킷 브레이커 선언하기

  • 의존성 추가
  • Hystrix 활성화
  • 서킷 브레이커가 적용될 메서드에 @HystrixCommand를 지정한다.
    • 해당 메서드를 호출 했을 때 예외가 던져지면 fallbackMethod 필드에 선언한 메소드를 호출한다.
    • 폴백 메서드는 원래 호출할 메서드와 이름을 제외한 시그니처가 같다.
  • 폴백 메서드 자신도 서킷 브레이커를 가질 수 있다.
    • 폴백 메서드를 연쇄적으로 사용할 때, 폴백 스택의 제일 밑에는 실행에 실패하지 않아서 서킷 브레이커가 필요 없는 메서드가 있어야 한다.

지연 시간 줄이기

  • @HystrixCommand 애노테이션의 commandProperties 속성을 통해 Hystrix 명령 속성을 설정할 수 있다.
  • 서킷 브레이커의 타임아웃을 변경하려면 execution.isolation.thread.timeoutInMilliseconds 명령 속성을 설정해야 한다.
  • 타임아웃이 필요 없을 때는 execution.timeout.enabledfalse로 설정하여 타임아웃을 없앨 수 있다.

서킷 브레이커 한계값 관리하기

  • 서킷 브레이커 기본값으로는 메서드가 10초동안 20번 이상 호출되면서 50%이상이 실패한다면, 열림 상태가 된다. 그리고 5초 후이 이 서킷은 절반-열림 상태가 되어 원래 메서드 호출이 다시 시도된다.
  • 서킷 브레이커의 상태 변화를 초래하는 명령 속성들
    • circuitBreaker.requestVolumeThreshold: 지정된 시간 내에 메서드가 호출되어야 하는 횟수
    • circuitBreaker.errorThresholdPercentage: 지정된 시간 내에 실패한 메서드 호출의 비율(%)
    • metrics.rollingStats.timeInMilliseconds: 요청 횟수와 에러 비율이 고려되는 시간
    • circuitBreaker.sleepWindowInMilliseconds: 절반-열림 상태로 진입하여 실패한 메서드가 다시 시도되기 전에 열림 상태의 서킷이 유지되는 시간

실패 모니터링하기

  • 서킷 브레이커로 보호되는 메서드가 매번 호출될 떄마다 해당 호출에 관한 여러 데이터가 수집돠어 Hystrix 스트림으로 발행된다.
  • Hystrix 스트림은 다음을 포함한다.
    • 메서드가 몇 번 호출되는지
    • 성공적으로 몇 번 호출되는지
    • 폴백 메서드가 몇 번 호출되는지
    • 메서드가 몇 번 타임아웃되는지
  • Hystrix 스트림은 엑추에이터 엔드포인트로 제공된다.
    • /actuator/hystrix.stream
  • 다음 구성을 추가하면 Hystrix 스트림 엔드포인트를 활성화할 수 있다.
  • Hystrix 스트림이 노출되면 어떤 REST 클라이언트를 사용해도 Hystrix 스트림을 소비할 수 있다.

Hystrix 대시보드 개요

  • Hystrix 스트림으로 클라이언트에 노출하는 대신, Hystrix 대시보드를 사용해서 모니터링하는 방법도 있다.
  • 의존성 추가
  • 구성 클래스에 @EnableHystrixDashboard로 활성화
  • 기본 설정 기준으로 ‘{baseUrl}/hystrix’ 경로에 접속하면 대시보드 홈페이지가 열린다.
  • 택스트 필드에 ‘{모니터링할 서버의 baseUrl}/actuator/hystrix.stream’을 입력하면 서킷 브레이커의 매트릭을 볼 수 있다.
    • 호출 횟수의 각 칸 정보
      • | 성공한 호출 횟수 | 타임아웃된 요청 횟수 |
      • | 숏-서킷 요청 횟수 | 스레드 풀이 거부한 횟수 |
      • | 잘못된 요청의 횟수 | 실패한 요청 횟수 |

Hystrix 스레드 풀 이해하기

  • Hystrix가 관리하는 메서드가 다른 서비스에 HTTP 요청을 보냈는데 응답이 느리면 블록킹된다.
  • 블록킹된 스레드가 제한된 수의 스레드(예: 톰캣의 요청 처리 스레드) 중 하나인데 문제가 계속 생긴다면, 사용 가능한 모든 스레드가 포화 상태가 되어 응답을 기다리게 된다.
  • 이런 상황을 방지하기 위해 Hystrix는 의존성 모듈의 스레드 풀을 할당한다.
    • 예: 하나 이상의 Hystrix 명령 스레드를 갖는 각 스프링 빈마다 스레드 풀 할당
  • Hystrix 명령 메서드 중 하나가 호출될 때 이 메서드는 Hystrix가 관리하는 스레드 풀의 스레드에서 실행된다.
  • 대시 보드에서 확인
    • 큐 스레드 개수: 현재 큐에 있는 스레드 개수. 기본적으로 큐가 비활성화 되어 있으므로 이 값은 항상 0이다.
    • 최대 활성 스레드 개수: 샘플링 기간 도안의 최대 활성 스레드 개수
    • 실행 횟수: Hystrix 명령을 처리하기 위해 스레드 풀의 스레드가 호출된 횟수
    • 큐 크기: 스레드 풀 큐의 크기. 스레드 큐는 기본적으로 비활성화 되어 있으므로 이 값은 항상 0이다.

다수의 Hystrix 스트림 종합하기

  • Netflix 프로젝트인 Turbine이 모든 마이크로서비스로부터 모든 Hystrix 스트림을 Hystrix 대시보드가 모니터링할 수 있는 하나의 스트림으로 종합하는 방법을 제공한다.
  • 의존성 추가
  • 구성 클래스에 @EnableTurbine 애노테이션 지정
  • Turbine은 유레카의 클라이언트로 작동하므로 Hystrix 스트림을 종합할 서비스들을 유레카에서 찾는다.
    • 그러나 유레카에 등록된 모든 서비스의 Hystrix 스트림을 종합하지 않는다.
    • 따라서 Hystrix 스트림을 종합할 서비스들을 알 수 있게 Turbine을 구성해야 한다.
    • turbine.app-config 속성에 종합할 서비스 이름을 명시한다.
    • cluster-name-expression: 이름이 default인 클러스터에 있는 모든 종합될 스트림을 Turbine이 수집한다.