SpringCloud

[11번가 Spring Cloud 기반 MSA로의 전환] 2. Deep Dive into Hystrix, Ribbon, Eureka

nineDeveloper 2021. 2. 8.
728x90

Deep Dive into Hystrix, Ribbon, Eureka


youtu.be/J-VP0WFEQsY?t=504

 


Hystrix

Netflix가 만든 Fault Tolerance Library

  • 장애 전파 방지 & Resilience

기능적 관점에서 본 Hystrix의 주요 4가지 기능

  • Circuit Breaker
  • Fallback
  • Thread Isolation
  • Timeout

Hystrix 적용하기

Hystrix Annotation 사용

  • Hystrix Javanica, Spring Cloud Netflix에 포함되어 있음
@HystrixCommand
public String anyMethodWithExternalDependency() {
    // REST API로 다른 서버 호출
}

HystrixCommand 상속

public class SampleCommand extends HystrixCommand<String> {
    @Override
    protected String run() {
      // REST API로 다른 서버 호출
    } 
}

Hystrix Command를 호출할 때 벌어지는 일

  1. 이 메소드를 Intercept하여 대신 실행한다
    • Thread Isolation
  2. 메소드의 실행 결과 성공 혹은 실패(Exception) 발생 여부를 기록하고 통계를 낸다
    통계에 따라 Circuit Open 여부를 결정한다
    • Circuit Breaker
  3. 실패한 경우(Exception) 사용자가 제공한 메소드를 대신 실행한다
    • Fallback
  4. 특정시간 동안 메소드가 종료되지 않는 경우 Exception을 발생시킨다
    • Timeout

Hystrix - Circuit Breaker

  • (1)일정시간 동안 (2)일정 개수 이상의 호출이 발생한 경우, (3)일정 비율 이상의 에러가 발생하면
    • Circuit Open(호출차단)
  • (4)일정 시간 경과 후에 단 한개의 요청에 대해서 호출을 허용하며 (Half Open), 이 호출이 성공하면
    • Circuit Close(호출허용)

hystrix.command.<commandKey>.

  1. metrics.rollingStats.timeInMilliseconds - Default 10초
  2. circuitBreaker.requestVolumeThreshold - Default 20개
  3. circuitBreaker.errorThresholdPercentage - Default 50%
  4. circuitBreaker.sleepWindowInMilliseconds - Default 5초

10초간 20개 이상의 호출이 발생한 경우, 50% 이상의 에러가 발생하면 5초간 Circuit Open


Hystrix - Circuit Breaker의 단위

Hystrix Circuit Breaker는 한 프로세스 내에서 주어진 CommandKey 단위로 통계를 내고 동작한다

  • 즉, Circuit Breaker는 CommandKey 단위로 생성된다
@HystrixCommand(commandKey = "ExtDep1")
public String anyMethodWithExternalDependency1() {
    // 추천 서버 호출 - 상품 추천 #1
}
@HystrixCommand(commandKey = "ExtDep1")
public String anyMethodWithExternalDependency2() {
    // 추천 서버 호출 - 상품 추천 #2
}

동일한 Dependency를 갖는 Hystrix Command들을 동일한 CommandKey로 묶는 것을 고려해야 함


Hystrix - Fallback

Fallback으로 지정된 메소드는 다음의 경우에 원본 메소드 대신 실행된다

  • Circuit Open
  • Any Exception (HystrixBadRequestException 제외)
  • Semaphore / ThreadPool Rejection (나중 Isolation에서 설명)
  • Timeout
@HystrixCommand(commandKey = "ExtDep1", fallbackMethod="recommendFallback")
public String anyMethodWithExternalDependency1() {
    // 추천 서버 호출
}
public String recommendFallback() {
    return "<미리 준비된 상품 목록>";
}

HystrixBadRequestException

사용자의 코드에서 HystrixBadRequestException을 발생시키면,
이 오류는 Fallback을 실행하지 않으며, Circuit Open을 위한 통계에도 집계되지 않는다

Method Caller의 실수 (ex 잘못된 파라메터의 전달)의 경우
HystrixBadRequestException을 Throw하게 작성 필요

만약 Caller의 실수를 다른 Exception으로 던진다면...

  • Circuit Breaker의 통계에 집계되어 Caller의 잘못으로 Circuit이 Open
  • Fallback이 실행되어, 개발과정에 오류를 인지하지 못할 수 있다

Hystrix - Timeout

Hystrix에서는 Circuit Breaker 단위로 (CommandKey 단위로) Timeout을 설정할 수 있다

  • hystrix.command.<commandKey>.execution.isolation.thread.timeoutInMilliseconds
    • Default 1초

Circuit Breaker의 Timeout 사용시 주의 사항

  • Semaphore Isolation인 경우 - 제 시간에 Timeout이 발생하지 않는 경우가 대부분이다
  • Default 값이 매우 짧다 - 1초

Hystrix - Isolation

두가지 Isolation 방식을 Circuit Breaker별로 지정 가능

  • Semaphore
  • Thread(default)

Hystrix - Semaphore Isolation

  • Circuit Breaker 1개당 1개의 Semaphore 생성
  • Semaphore별로 최대 동시 요청 개수 지정
  • 최대 개수 초과시 Semaphore Rejection 발생 - Fallback 실행
  • Command를 호출한 Caller Thread에서 메소드 실행

*Timeout이 제 시간에 발생하지 못함


Hystrix - Thread Isolation

  • Circuit Breaker 별로 사용할 Thread Pool을 지정 (ThreadPoolKey)
  • Circuit Breaker:Thread Pool = N:1 관계 가능
  • 최대 개수 초과시 Thread Pool Rejection 발생 - Fallback 실행
  • Command를 호출한 Thread가 아닌 Thread Pool에서 메소드 실행

실제 메소드의 실행은 다른 Thread에서 실행되므로 Thread Local 사용 시 주의 필요


Ribbon

Netflix가 만든 Software Load Balancer를 내장한 RPC(REST) Library

  • Client Load Balancer with HTTP Client


Ribbon in Spring Cloud

Spring Cloud에서는 Ribbon 클라이언트를 사용자가 직접 사용하지 않음

  • Spring Cloud의 Http 통신이 필요한 요소에 내장되어 있음
    • Zuul API Gateway
    • RestTemplate(@LoadBalanced)
    • Spring Cloud Feign - 선언적 Http Client

Ribbon이 기존 Load Balancer와 다른점

Ribbon은 대부분의 동작은 Programmable 함

Spring Cloud에서는 아래와 같은 BeanType으로

  • IRule - 주어진 서버 목록에서 어떤 서버를 선택할 것인가
  • IPing - 각 서버가 살아있는 가를 검사
  • ServerList<Server> - 대상 서버 목록 제공
  • ServerListFilter<Server> - 대상 서버들 중 호출할 대상 Filter
  • ServerListUpdater
  • IClientConfig
  • ILoadBalancer

Eureka

Netflix가 만든 Dynamic Service Discovery

  • 등록: 서버가 자신의 서비스 이름(종류)와 IP주소 포트를 등록
  • 조회: 서비스 이름(종류)을 갖고 서버 목록을 조회


Eureka in Spring Cloud

Eureka가 Enable된 Spring Cloud Application은

  • Server 시작으로 Eureka 서버에 자동으로 자신의 상태 등록(UP)
  • 주기적으로 HeartBeat으로 Eureka Server에 자신이 살아 있음을 알림
  • Server 종료시 Eureka 서버에 자신의 상태 변경(DOWN) 혹은 자신의 목록 삭제
  • Eureka 상에 등록된 이름은 spring.application.name

Eureka + Ribbon in Spring Cloud

하나의 서버에 Eureka Client와 Ribbon Client가 함께 설정되면
Spring Cloud는 다음의 Ribbon Bean을 대체

1. ServerList<Server>

  • 기본: ConfigurationBasedServerList
  • 변경: DiscoveryEnabledNIWSServerList

2. IPing

  • 기본: DummyPing
  • 변경: NIWSDiscoveryPing

서버의 목록을 설정으로 명시하는 대신 Eureka를 통해서 Look Up 해오는 구현

이 세가지를 잘 적용하면 MSA 환경에서 Server 들간의 통신이 큰 문제없이 잘 될 것 같다는 생각...

728x90

댓글

💲 추천 글