Patterns

image.png

장애 전파 방지 : Fail-Fast, Circuit Breaker

Circuit Breaker

일정 시간, 일정 개수 이상의 호출 시, 일정 비율의 에러가 발생한다면 호출 차단 (Circuit open). 빨리 실패 (Fail-fast)하게 하여 Thread-pool 등이 차서 장애가 전파되지 않게 한다.
몇몇 호출을 허용하여 (Half-Open)하여 성공하면 그 때 호출 허용 (Circuit close) 한다.

Hystrix

특정 api 그룹이 같은 서버를 보고 있다면 -> commandKey 단위로 circuit breaker를 지정할 수 있다.
func 안에서 Remote call이 아닌 내부 코드에서 오류가 난 경우는 어떻게 처리하나 -> HystrixBadRequestException 발생. circuit open을 위한 통계에 집계되지 않음

@ HystrixCommand
public String func(fallbackMethod="fbFunc") { ... }
public class SampleCommand extends HystrixCommand<String> {
 protected String run() { ... }
}

Load balancing

서버 사이드 로드 밸런싱

하드웨어 : L4, L7 스위치를 이용한 방식
요청 : client -> L4 -> NAT(주소변조) -> serve
응답 : server -> NAT(주소변조) -> L4 -> client
소프트웨어 : HA proxy를 이용한 방식
응답시 쿠키에 서버 정보를 추가. 쿠키를 사용하여 로드 밸런싱한다.

클라이언트 사이드 로드 밸런싱

스위치에서 하던 분산 역할을 클라이언트측에서 처리. 클라이언트가 서버 목록중에 접속할 서버를 선택하여, 접속하지 못하는 경우 다른 서버로의 접속을 시도한다.

Ribbon

클라이언트 사이드 로드 밸런싱

Eureka

환경 설정 파일에 서버 목록을 ip로 지정하는 것이 바람직한 일인가? 이러한 이슈를 해결하기 위한 것이 Eureka (동적으로 서비스 등록, 발견)
모든 micro service가 자신의 가용성을 레지스트리 서버에 등록하고, 30초마다 heart-beat하여 살아 있음을 알린다. 서버 종료시 레지스트리 서버에 상태 down 한다.

API Gateway

Single endpoint 제공하며, API 공통 로직 구현이 용이하다. (로깅, 인증) 트래픽 조절이 가능하다.
외부 호출은 API Gateway로. 내부 호출도 API Gateway를 사용해야 할까?
내부 호출은 peer to peer. 각 서버 주소를 알아야 하는 이슈는 Eureka로 해결한다.

Spring Cloud Zuul

Spring Cloud Zuul : Hystrix, Ribbon, Eureka를 통해 구현

Spring Cloud Feign

REST 기반 서비스 호출을 추상화한다. Ribbon + Eureka 기반의 Http 호출 방법 중의 하나 (다른 하나는 @LoadBalanced 어노테이션 활용)

모니터링

서버 간의 API 호출/응답은 어떻게 trace할 것인가? API간 TraceId 전달

TraceId 전달 방법

Http Header와 같은 Protocol 헤더를 통해 전달
Thread Local 등을 사용하여 전달 -> 하지만 thread가 자주 바뀌어서 사용하기 어려움 -> 호출 내외부 구간에서 생성 및 전달, 로그에 남기거나 수집 서버에 전송하여 시각화한다.

참고

Spring Camp 2018 : 11번가 Spring Cloud 기반 MSA로의 전환