SpringCloud

[11번가 Spring Cloud 기반 MSA로의 전환] 3. Hystrix, Ribbon, Eureka 적용 in 11st

nineDeveloper 2021. 2. 8.
728x90

Hystrix, Ribbon, Eureka 적용 in 11st


youtu.be/J-VP0WFEQsY?t=1815

 

 


API Gateway

MSA 환경에서 API Gateway의 필요성

  • Single Endpoint 제공
    • API를 사용할 Client들은 API Gateway 주소만 인지
  • API의 공통 로직 구현
    • Logging, Authentication, Authorization
  • Traffic Control
    • API Quota, Throttling

자체 개발 Vs Zuul

SK planet은 자체 개발 API Gateway를 상용 운영 중

  • 11번가를 제외한 서비스의 Open API 제공
  • Node.js / Koa Framework 기반
  • 100% 자체 개발 from Scratch
  • Logging, Authorization, Throtting 등..

100% 자체 개발한 API Gateway를 두고 Zuul을 도입해야 할까?


Spring Cloud Zuul

Spring Cloud Zuul은 API Routing을 Hystrix, Ribbon, Eureka를 통해서 구현

  • Spring Cloud와 가장 잘 Integration 되어있는 API GateWary


Hystrix, Ribbon, Eureka in Spring Cloud Zuul

API 요청들은 각각 HystrixCommand를 통해서 실행되며,
각 API의 Routing은 Ribbon & Eureka의 조합으로 수행


Hystrix Circuit Breaker in Spring Cloud Zuul

Reminder

  • Hystrix Circuit BreakerCommandKey 이름 단위로 동작한다

Spring Cloud Zuul에서 Hystrix CommandKey는

  • 각 서버군 이름 (Zuul 용어로 Service ID, Eureka에 등록된 서버군 이름)이 사용됨
  • 앞선 그림을 예를 들면 3개의 CommandKey가 사용
    • HystrixCommand('product')
    • HystrixCommand('display')
    • HystrixCommand('member')

Histrix의 옵션을 서버군(Service ID)별로 부여 가능

hystrix.command.[product|display|member].

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

Hystrix Isolation in Spring Cloud Zuul

Reminder

  • Hystrix Isolation은 Semaphore/Thread 두가지 모드가 있으며, Semaphore는 CommandKey단위로
    ThreadPool은 별도 부여된 ThreadPoolkey 단위로 생성된다

Spring Cloud Zuul에서 Histrix Isolation은

  • Semaphore Isolation을 기본으로 한다
  • Hystrix의 원래 Default는 Thread Isolation

Spring Cloud Zuul의 기본설정으로는 Semaphore Isolation

  • 특정 API 군의 장애(지연)등이 발생하여도 Zuul 자체의 장애로 이어지지 않음

Spring Cloud Zuul에서 우리는 Thread Isolation을 사용하고 싶다는 생각...

Thread Isolation을 통해서

  • Hystrix Timeout을 통해서 특정 서버군의 장애시에도 Zuul의 Container Worker Thread의 원할한 반환
zuul:
  rebbon-isolation-strategy: thread

Spring Cloud Zuul의 Histrix Isolation을 Thread로 바꾸면

  • Server 전체에 한개의 Thread Pool이 생겨버리게 구현
  • 'RibbonCommand'라는 이름의 Thread Pool

이건 우리가 원하던 모습이 아니다!

  • 서버군(Service ID)별로 Thread Pool을 분리해주는 것이 필요하다는 팀의 판단
  • Spring Cloud Netflix 프로젝트에 Pull Request를 통해 해당코드 수정
zuul:
  threadPool:
    useSeparateThreadPools: true
    threadPoolKeyPrefix: zuulgw


Server to Server 호출 in MSA

MSA 플랫폼 외부의 호출은 API Gateway를 단일 창구로 사용

MSA 플랫폼 내부의 API Server 간의 호출은 어덯게 할것인가?

Gateway 경우 모델

  • 장점
    • 모든 API 호출을 한곳에서 통제할 수 있다
    • 각 API서버가 다른 API서버의 주소를 알 필요가 없다
  • 단점
    • 불필요한 Network Hop/부하가 생긴다
    • API GW가 SPOF가 될 수 있다

Peer to Peer 호출

  • 장점
    • Server간의 호출이 별도의 Hop/부하가 없다
    • API Server간의 호출이 많아질 수록 유리하다
  • 단점
    • API 호출을 한곳에서 모두 통제할 수 없다
    • 모든 API서버가 다른 API서버의 주소를 알아야 한다 -> Eureka가 해결 가능

Ribbon + Eureka 조합으로 Peer to Peer 호출을 하기로 결정

Spring Cloud에서는 다음의 Ribbon + Eureka 기반의 Http 호출 방법을 제공

  • @LoadBalanced RestTemplate
    • @LoadBalanced 주석을 붙이는 경우 RestTemplate가 Ribbon + Eureka 기능을 갖게 됨
    • RestTemplate이 Bean으로 선언된 것만 적용가능
  • Spring Cloud Feign

Spring Cloud Feign

Declarative Http Client

  • Java Interface + Spring MVC Annotation 선언으로 Http 호출이 가능한 Spring Bean을 자동 생성
  • OpenFeign기반의 Spring Cloud 확장
  • Hystrix + Ribbon + Eureka와 연동되어 있음

Spring Cloud Feign with Eureka and Ribbon

Ribbon + Eureka 없이 사용하기

URL 직접 명시

@FeignClient(name = "product", url = "http://localhost:8081") // URL 직접 명시
public interface FeignProductRemoteService {
    @RequestMapping(path = "/products/{productId}")
    String getProductInfo(@PathVariable("productId") String productId);
}

Ribbon + Eureka 연동

URL 생략

@FeignClient(name = "product") // URL 생략
public interface FeignProductRemoteService {
    @RequestMapping(path = "/products/{productId}")
    String getProductInfo(@PathVariable("productId") String productId);
}

Spring Cloud Feign with Hystrix

Hystrix 연동하기

  • Hystrix가 Classpath에 존재
  • feign.hystrix.enabled=true

Default Hystrix Key

  • CommandKey: 각 메소드 단위로 생성
    • ex) FeignProductRemoteService#getProductInfo(String)
    • 메소드 단위로 Circuit Breaker 생성
  • ThreadPoolKey: 서버군 별로 생성
    • ex) product
    • Feign에서는 CommandGroupKey를 설정한, ThreadPoolKey가 명시되지 않는 경우 CommandGroupKey가 대신 사용

Hystrix 규칙 Customizing 하기

  • Feign Interface별로 Configuration 클래스 지정가능
  • Hystrix Key 및 속성을 지정할 수 있는 SetterFactoryBean 선언 가능

11번가의 Feign Hystrix Key 정책

  • CommandKey: 기본 정책에서 파라메터 제거
    • ex) FeignProductRemoteService#getProductInfo
  • ThreadPoolKey: <Caller서버군 이름>-<Callee서버군 이름>
    • ex) display-product
  • 자체 Annotation으로 위 속성 임의 변경 가능

Spring Cloud Feign with Hystrix, Ribbon, Eureka

  • 호출하는 모든 메소드는 Hystrix Command로 실행
    • Circuit Breaker, Timeout, Isolation, Fallback 적용
  • 호출할 서버는 Eureka를 통해 얻어서, Ribbon으로 Load Balancing되어 호출

728x90

댓글

💲 추천 글