*https://medium.com/netflix-techblog/fault-tolerance-in-a-high-volume-distributed-system-91ab4faae74a
이번 글에서는 Netflix 분산 시스템에서 fault tolerance 수행하기 위해 고민했던 흔적을 소개해보려고 한다.
이전 글에도 언급했듯이, API는 서비스에 문제가 발생했을 때 영향을 받을 수 있다.
특히, SOA(Service-Oriented Architecture) 환경에서는 더더욱이나 서비스의 문제가 API를 더 취약하게(vulnerable)하게 만들 수 있다.
Circuit breaker 패턴을 사용하여 API를 resilient하도록 한 것 이외에도 내부적으로 장애를 어떻게 격리하고 부하를 줄일 수 있는지 등에 대해 기술적으로 알아보려고 한다.
Fault Tolerance* is a Requirement, Not a Feature
* Fault Tolerance를 단순히 번역하면 장애 허용이라는 뜻으로 보다 자세한 것은 아래 URL 참조
https://en.wikipedia.org/wiki/Fault_tolerance
Netflix는 하루에 10억건 이상의 요청을 받고 내부 서브 시스템과 통신한다.
그림 1. Netflix Requests and Access over Network
그림 1에서 확인 할 수 있듯이, App Container에서 사용자의 요청을 받고 내부 의존 서비스*와 연결한다.
*내부 서비스는 클라우드 환경에서 수 천개의 EC2 인스턴스를 사용한다.
그런데 fault tolerance를 보장하지 않으면, 서비스의 중단 시간이 발생한다. (아래 원문 참조)
"Without taking steps to ensure fault tolerance, 30 dependencies each with 99.99% uptime would result in 2+ hours downtime/month
(99.99%30= 99.7% uptime = 2+ hours in a month)."
그림 1을 바탕으로 한 가지 예를 들어보면, latency가 높아진 상황에서 API가 실패하면 모든 Tomcat(또는 Jetty와 같은 다른 컨테이너) 요청 스레드를 포화(saturate)시키고 결과적으로 전체 API를 멈추게 할 수 있다. (그림 2)
그림 2. Request blocked by Latency in Single Network Call
그림 2만 확인하여도 사용자의 요청이 내부 시스템의 문제로 인해 막힐 수 있다.
그렇기 때문에 high volume, high availability 어플리케이션은 fault tolerance가 필수 이다. (모든 것은 사용자를 위해)
Netflix DependencyCommand Implementation
Netflix에서 몇몇 고려 사항*을 바탕으로 fault tolerance를 구현하기 위해 아래와 같은 접근 방식을 취했다.
* 내부 API 팀 당 프로토콜이 다를 수 있고, 서드 파티 라이브러리에 의존
- Network timeouts and retries
- separate threads on per-dependency thread pools
- semaphores
- circuit breakers
위의 언급한 4가지 방식은 장단점이 존재하지만, 함께 사용하게 되면 사용자 요청과 의존성 사이에 완충제*가 될 수 있다. (그림 3 참조)
*4가지 방식을 동시에 사용하면 많이 좋아진다는 의미
그림 3. DependencyCommand
그림 3에서도 확인 할 수 있듯이, DependencyCommand는 별도의 스레드를 사용한다. (Dependency A Thread -> Dependency A Client 확인)
각 스레드에서는 Network binding 및 fail, reject에 대한 fallback 로직*을 정의한다.
*관련된 부분은 그림 4 참조
그림 4. DependencyCommand Thread Logic
이렇듯 의존성 호출(DependencyCommand)를 별도의 스레드로 분리하면 단점보다는 장점이 더 많다고 한다.
특히, API의 동시성(concurrency)이 점차 많아지고 있는 상황에서 별도 스레드의 내부 알고리즘(그림 4)으로 fault tolerance 및 performance를 얻을 수 있다.
(Parallel한 스레드 사용으로 인한 장점)
때문에 아래 그림 1이 그림 5와 같이 바뀐다. (Thread pool을 통한 routing)
그림 5. Thread Pool Routing
DependencyCommand의 별도의 스레드가 만들어지면서, 내부 시스템에서 문제가 발생했을 때 timeout 또는 reject가 발생한다.
즉, 이전에는 blocking을 사용하여 대기 시간을 발생시켰다면 지금은 fault tolerance를 통해 대응한다.
그림 6. Throws an Exception
How do we respond to a user request when failure occurs?
그림 7. Use Case
'IT > AWS' 카테고리의 다른 글
[Netflix] Part 5 - API 배포 준비 (0) | 2018.12.22 |
---|---|
Circuit Breaker 패턴 (0) | 2018.12.20 |
[Netflix] Part 3 - Resilient API (0) | 2018.12.18 |
[Netflix] Part 2 - Zuul 2 여정의 시작 (0) | 2018.12.06 |
[Netflix] Part 1 - Zuul 소개 (0) | 2018.12.04 |
댓글