Tech Note

글로벌 비디오 서비스가 가능하게 한 넷플릭스의 Microservice 아키텍쳐 구조 분석

Samgim 2021. 1. 24. 01:55

Cao Duc Nguyen

원문 링크 A Design Analysis of Cloud-based Microservices Architecture at Netflix | by Cao Duc Nguyen | The Startup | Medium

역주 그림을 따라서 보아야하는 단어들의 경우는 굳이 한국어로 바꾸지 않고 그림과 똑같은 단어를 사용하였습니다.

 

 

1. 시작

넷플릭스는 매년 전세계 인터넷 트래픽의 15% 이상([ 12 ])을 차지하고 있습니다. 2019년에는 이미 1억 6700만명의 구독자가 생겼고, 매 4분기 마다 5백만명이 200개 이상의 국가에서 구독하기 시작했습니다. 구독자들은 매일 47000 개의 에피소드와 영화 4000개를 보며 약 1억 6500만 시간 이상을 쓰고 있습니다. 이 놀라운 통계는 넷플릭스 기술팀이 글로벌 서비스를 지원하기 위해, 고가용성과 확장성을 가진 비디오 스트리밍 시스템을 설계했기 때문입니다.

하지만 이건 기술팀이 8년간 노력해온 결과입니다.([ 1 ]) 사실 2008년 8월에 데이터센터가 내려가 렌트 서비스가 3일이나 다운된 적이 있었습니다. 우리는 SPOF(Single Point Of Failure) 가 되지 않도록 더 신뢰성있는 인프라가 필요하다는 것을 깨달았습니다. 그래서 두 가지 중요한 결정을 내렸습니다. 먼저, 인프라를 자체 데이터센터에서 공개 클라우드로 옮겨야겠다는 것이고, 두번째는 모놀리틱 프로그램을 작게 관리할 수 있는 마이크로서비스 아키텍처로 변경하기로 했습니다. 이렇게 내린 결정들이 지금의 넷플릭스의 성공을 만들어 주었습니다.

넷플릭스는 AWS 클라우드([ 4 ])를 선택했습니다. 왜냐하면 AWS 는 매우 신뢰할 수 있는 데이터베이스를 제공할 수 있고, 큰 스케일의 클라우드 저장소와 세계 곳곳에 여러 개의 데이터 센터를 가지고 있기 때문이었습니다. AWS 에 인프라를 세우고 유지보수하도록 하려면, 넷플릭스는 엄청난 데이터를 어떤 변경도 없이 옮겨야 했습니다. 게다가 동시에 핵심 비즈니스인 고화질의 비디오 스트리밍도 제공해야 했습니다. 또한, AWS 클라우드에 문제없이 부드럽게 동작하게 하려고 모든 관련 기술들을 재빌드 했습니다. 하지만, 이러한 작업들이 넷플릭스의 확장성과 서비스 고가용성을 크게 향상시켰습니다.

넷플릭스는 마이크로서비스 아키텍처 외에도 중요한 변화가 있었습니다. 마이크로서비스는 모놀리틱 서비스의 문제 하나를 해결하는 것을 목표로 합니다. 커다란 프로그램을 작은 컴포넌트로 쪼개면 데이터를 모듈로 만들 수 있고, 곧 캡슐화 할 수 있다는 뜻이 됩니다. 그래서 걱정거리를 분리([ 11 ])할 수 있게 되죠. 마이크로서비스는 또한 수평적 스케일링이 가능해지고 부하를 나누게 되어 확장성을 늘려줍니다. 마이크로서비스를 채택하고 넷플릭스의 엔지니어들은 이제 빠르게 배포할 수 있게 되었습니다. 따라서 어떤 서비스라도 변경하기 쉬워졌습니다. 더 중요한 것은 각 서비스의 성능을 추적할 수 있고, 운영 중인 다른 서비스의 문제를 빠르게 분리할 수 있게 되었습니다.

이 조사를 하면서 저는 넷플릭스의 클라우드 아키텍처 안의 컴포넌트들이 서로 다른 부하와 네트워크 한계를 가지고 있을 텐데 과연 어떤 성능을 낼지 흥미로워졌습니다. 특히 이 연구에서는 시스템의 네트워크 장애 상황이나 시스템 오류 상황에서 가용성 availability, 레이턴시 latency, 확장성 scalability, 신뢰성 resilience 이 어떻게 될지를 분석해 볼 것입니다. 이 글은 다음과 같이 구성되어 있습니다. 섹션 2에서는 여러가지 온라인 소스에서 어떻게 넷플릭스 아키텍처가 동작하는지를 알아볼 것입니다. 그리고 섹션 3에서는 시스템 컴포넌트에 대해서 더 자세히 알아볼 것입니다. 그리고 섹션 4, 5, 6, 7 에서는 위의 설계 목적에 비추어 각각 분석해보려 합니다. 마지막으로 이 분석에서 어떤 것들을 배웠는지, 아키텍처를 더 향상시키위해 필요한 다음 단계에 대해 이야기하며 마치려 합니다.

 

 

2. 아키텍처

넷플릭스의 시스템들은 AWS 와 Open Connect 의 인하우스 CDN(Content Delivery Network) 를 기반으로 합니다([1]). 이 두 가지 시스템들은 끊임없이 고화질 스크리밍 서비스를 전세계에 전달해야 합니다. 소프트웨어 아키텍처 면에서보면, 넷플릭스는 주로 세 가지 부분으로 나눌 수 있습니다. 클라이언트와 백엔드 그리고 CDN 입니다.

클라이언트는 노트북이나 데스크탑의 브라우저, 또는 모바일, 스마트 TV의 넷플릭스 앱 안에서 구동됩니다. 넷플릭스는 iOS 와 안드로이드 앱에서 최상의 시청 환경을 제공하도록 개발되었습니다. 각 기기의 SDK 를 통해서 앱을 컨트롤하여 넷플릭스는 느린 네트워크 환경이나 서버 부하가 심한 상황에서도 아주 쾌적한 서비스를 제공할 수 있습니다.

백엔드는 AWS 클라우드에서 운영하는 모든 서비스, 데이터베이스, 저장소 등을 말합니다. 백엔드는 기본적으로 스트리밍 비디오를 제외한 모든 것을 다룹니다. AWS 에서 돌아가는 백엔드 컴포넌트는 다음과 같습니다.

  • 확장 가능한 컴퓨팅 인스턴스 (AWS EC2)
  • 확장 가능한 스토리지 (AWS S3)
  • 비즈니스 로직을 갖고 있는 마이크로서비스 (넷플릭스에서 만든 프레임워크)
  • 확장가능한 분산 데이터베이스 (AWS DynamoDB, Cassandra)
  • 빅데이터 처리 및 분석 작업 (AWS EMR, Hadoop, Spark, Flink, Kafka 그리고 넷플릭스에서 만든 도구들)
  • 비디오 처리 및 transcoding (넷플릭스에서 만든 도구들)


Open Connect CDN 은 Open Connect Appliances (OCAs) 라고 불리는 네트워크 서비스 입니다. 이 서비스는 커다란 비디오를 저장하는 것과 스트리밍을 할 수 있도록 최적화되어 있습니다. 이 OCAs 서버는 인터넷 서비스 제공자(ISPs) 안에 자리잡고 있습니다. 그리고 이 OCAs 서버와 인터넷 교환 지점(IXPs, Internet Exchange Point) 네트워크는 전 세계에 걸쳐 있습니다. 이 OCAs 는 클라이언트에 직접 비디오를 스트리밍할 책임이 있습니다.

 

아래 섹션에서는 넷플릭스의 클라우드 아키텍처를 3개로 나누어 설명할 것입니다. 섹션 2.1에서는 비디오 스트리밍을 얼마나 감당할 수 있는지 전반적인 아키텍처를 살펴볼 것입니다. 이 아키텍처는 Playback 아키텍처라고 부르는데요. 구독자가 앱에서 플레이 버튼을 누르고 난 이후의 과정을 맡고 있습니다. 그리고 2.2 섹션에서는 백엔드의 마이크로서비스 아키텍처를 더 자세히 설명할 것입니다. 이 아키텍쳐가 어떻게 넷플릭스의 가용성과 확장성을 글로벌 스케일로 다룰 수 있는지를 알아보도록 하겠습니다.

 

2.1 Playback 아키텍처

구독자가 플레이 버튼을 누르면 클라이언트는 AWS 에 있는 백엔드와 넷플릭스 CDN 의 OCAs 에 스트리밍 될 비디오가 무엇인지 말해줍니다. ([7]) 아래 그림은 Playback 이 어떻게 동작하는지 알려줍니다.

 

그림 1 . 스트리밍 비디오를 위한 Playback 아키텍처

 

  1. OCAs 는 지속적으로 현재 부하와 라우팅이 가능한지 여부, 그리고 사용가능한 비디오에 대한 health 정보를 Cache Control Service(CCS) 에 보냅니다. (이 CCS 는 AWS ECS 안에 있습니다.) 이 과정은 Playback Apps 이 최신 OCAs 의 health 상태를 클라이언트에게 업데이트하기 위한겁니다.
  2. 클라이언트 기기가 재생 요청을 보냅니다. 이 요청은 넷플릭스의 Playback Apps 서비스에서 스트리밍할 비디오의 URL을 가져오도록 합니다.
  3. Playback Apps 는 반드시 Play 요청이 가능한 비디오를 찾을 수 있도록 해야 합니다. 이 때, 구독자의 구독 모델, 요청한 비디오에 라이센스가 있는 국가인지 등을 확인(validation)합니다.
  4. Playback Apps 는 Steering Service 에서 요청한 비디오의 적절한 OCAs 서버 목록을 물어봅니다. Steering Service 는 클라이언트의 IP 와 ISPs 정보를 사용해 클라이언트에게 가장 적절한 OCAs 목록인지를 확인(identify)합니다.
  5. Playback Apps 가 10개의 다른 OCAs 서버 목록을 반환하면, 클라이언트는 이 OCAs 목록의 네트워크의 퀄리티를 테스트해서 그 중 가장 빠르고 안정적인 것을 선택합니다. 그리고 선정한 OCA 에 스트리밍할 비디오 파일을 요청합니다.
  6. 선택된 OCA 서버가 요청을 수락해 클라이언트에 비디오를 스트리밍합니다.


위의 다이어그램에서 Playback Apps 서비스, Steering 서비스 그리고 Cache Control 서비스가 모두 AWS 클라우드에서 마이크로서비스로 실행되는 것을 보았습니다. 다음 섹션에서는 넷플릭스 백엔드가 마이크로서비스 아키텍처로 어떻게 서비스 도중에 가용성과 확장성을 늘릴 수 있는지 알아보도록 하겠습니다.

 

2.2 백엔드 아키텍처

이전 섹션에서 백엔드가 거의 모든 것을 다룬다고 이야기했습니다. 가입, 로그인, 빌링, 그리고 비디오 트랜스코딩이나 개인 추천과 같이 더 복잡한 프로세스까지 백엔드가 다룹니다. 같은 기반의 인프라에서 엄청난 부하를 빠르고 가볍게 지원하기 위해 넷플릭스는 클라우드 기반의 마이크로서비스 아키텍처를 적용했습니다. 그림 2의 다이어그램은 제가 몇 개의 온라인 소스([11, 13, 14]) 에서 찾은 넷플릭스의 마이크로서비스 아키텍처를 보여줍니다.

 

그림 2 . 여러 소스를 통해 알아본 백엔드 아키텍처

 

  1. 클라이언트가 재생 요청을 AWS에 있는 백엔드에 보냅니다. 이 요청은 AWS 의 로드 밸런서(ELB) 에서 처리됩니다.
  2. AWS ELB 는 이 요청을 AWS EC2 인스턴스에서 실행되는 API Gateway Service로 보냅니다. Zuul 이라고 부르는 이 컴포넌트는 넷플릭스 팀이 만들었습니다. 이 컴포넌트는 동적 라우팅, 트래픽 모니터링과 보안, 그리고 클라우드 배포가 실패했을 때 복구하도록 해줍니다. 이제 사용자의 요청에 관련된 비지니스 로직들이 미리 정의된 필터들을 통해 적용될 것입니다. 그리고 이제 Application API 로 전달됩니다.
  3. Application API 컴포넌트는 비즈니스 로직의 핵심입니다. 여기에는 가입 API, 추천 API 와 같이 유저에 따라 달라지는 몇 가지 API 들이 있습니다. API Gateway 서비스를 통해서 들어온 요청은 Play API 가 다루게 됩니다.
  4. Play API는 요청을 처리할 마이크로서비스를 호출합니다. 그림 1에서 보았던 Playback Apps 서비스, Steering 서비스와 Cache Control 서비스는 이 다이어그램의 마이크로서비스 안에 있습니다.
  5. 마이크로서비스는 대부분 상태가 없는 (stateless) 한 작은 프로그램입니다. 그리고 이들은 서로를 각각 호출할 수도 있습니다. ::_cascading 실패_나, _복구 가능성_을 컨트롤 하기 위해 각각의 마이크로서비스는 Hystrix 를 사용해 서로 호출하는 프로세스를 분리시켜 놓았습니다.:: 이것은 매우 낮은 레이턴시를 가진 요청이 빠르게 데이터에 접근하도록 메모리 기반의 캐시를 사용할 수 있게 해줍니다.
  6. 이 과정을 거치는 동안 마이크로서비스는 데이터 저장소에서 데이터를 가져오거나 저장할 수 있습니다.
  7. 마이크로서비스는 유저 활동과 다른 데이터들을 트래킹하는 이벤트를 Stream Processing Pipeline 으로 보낼 수 있습니다. 이것은 실시간 개인화 추천이나 BI(Business Intelligence) 를 위한 배치 작업처리에 사용됩니다.
  8. Stream Processing Pipeline 를 통해 나온 데이터는 AWS S3, Hadoop HDFS, Cassandra 와 같은 영구(persistent) 저장소에 저장됩니다.

 

이 아키텍처는 비디오 스트리밍을 하기 위해 얼마나 다양한 과정들이 조화롭게 움직어야 하는지를 알려줍니다. 하지만 아키텍처의 가용성과 확장성을 분석하기 위해서는 더 중요한 각각의 컴포넌트들을 살펴볼 필요가 있습니다. 이 컴포넌트들은 서로 견디고 있는 부하가 다른데도 어떻게 동작하는지를 보여줍니다. 다음 섹션에서 이것에 대해 알아봅시다.

 

 

3. 컴포넌트

이 섹션에서는 섹션 2에서 본 컴포넌트들을 자세히 살펴보겠습니다. 이 컴포넌트들을 보고 나면 우리가 이 디자인을 분석한 목표를 달성할 수 있게 될 것입니다. 이 설계 분석을 좀 더 자세히 살펴본 다음에는 이어지는 섹션에서 전체 시스템을 조망해보겠습니다.

 

3.1 클라이언트

넷플릭스 기술팀은 노트북, 데스크탑, 모바일에서 빠르고 스마트하게 동작하는 클라이언트를 개발하기 위해 많은 노력을 기울였습니다. 넷플릭스가 설치되어 있지 않은 스마트TV 라도 넷플릭스는 제공된 SDK 를 통해서 성능을 제어할 수 있습니다. 사실 모든 디바이스 환경에는 Netflix Ready Device Platform (NRDP) 가 설치되어 있어야 합니다. 왜냐하면 이 NDRP 가 넷플릭스의 시청 경험을 최상의 상태로 만들어주기 때문입니다. 일반적인 클라이언트의 컴포넌트 구조는 ([11]) 아래의 그림 3. 으로 설명할 수 있습니다.

 

그림 3 . Client 앱 컴포넌트

 

  • 클라이언트 앱은 백엔드로 가는 2가지 커넥션을 가지고 있습니다. 하나는 Content discovery 와 다른 하나는 playback 입니다. 클라이언트는 NTBA 프로토콜([15]) 을 사용해 Playback 요청을 보냅니다. 이 요청은 OCAs Locations 로 가는 보안을 맡아주는 동시에, SSL/TLS handshake 과정 때문에 일어나는 레이턴시를 없앤, 새로운 연결을 맺어줍니다.
  • 비디오가 스트리밍되는 동안 네트워크 커넥션에 부하가 걸리거나 에러가 나면, 클라이언트 앱은 알아서 비디오 퀄리티를 낮추거나 다른 OCAs 로 변경해서 붙습니다. OCA 가 부하가 걸리거나 에러가 나는 경우에도 클라이언트 앱은 더 나은 시청 경험을 제공할 다른 OCA 서버로 쉽게 바꿔서 붙을 수 있습니다. 이 모든 것은 클라이언트의 넷플릭스 플랫폼 SDK가 그림 1에서 보았던 Playback Apps 서비스에서 보내는 OCAs 의 최신 health 정보를 트래킹하기 때문에 가능한 것입니다.

 

3.2 Backend

3.2.1 API Gateway Service

API Gateway Service 컴포넌트는 클라이언트에서 오는 모든 요청을 처리하기 위해 AWS 로드 밸런서와 통신합니다. 이 컴포넌트는 서로 다른 리전(region) 에 있는 여러 개의 AWS EC2 인스턴트에 배포됩니다. 아래의 다이어그램은 넷플릭스 팀이 만든 API Gateway 를 구현한 오픈 소스인 Zull 을 나타냅니다.

 

그림 4 . Zuul Gateway Service 컴포넌트

 

  • Inbound Filter는 인증과 요청을 라우팅하고 decorate 하기 위해 사용됩니다.
  • Endpoint Filter는 정적 리소스를 반환하거나 Request가 적절한 Origin 또는 Application API를 찾아가도록 라우팅합니다.
  • Outbound Filter는 트래킹한 정보를 metrics 하고, 응답에 커스텀 헤더를 붙이거나 하는 decorate를 합니다.
  • Zuul 은 Service discovery 인 Eureka를 사용해 새로운 Application API를 discovery 할 수 있습니다.
  • 새로운 Application API 를 사용하게 되거나 부하 테스트, 또는 엄청난 부하를 감당하기 위해 다른 서비스로 라우팅하는 경우 등 특정한 목적을 가진 트래픽들을 확장성 있게 라우팅하기 위해 Zuul을 사용할 수 있습니다.

 

3.2.2 Application API

Application API 는 넷플릭스 마이크로서비스에서 오케스트레이션 레이어 역할을([18]) 합니다. 이 API는 호출할 때 순서가 필요한 마이크로서비스를 로직들로 구성되어 있습니다. 그리고 응답에 적절한 데이터들을 추가로 붙여주기도 합니다. 넷플릭스 팀은 이 Application API 컴포넌트를 디자인하는데 많은 시간을 쏟았습니다. 왜냐하면 이게 핵심 비즈니스 기능이니까요. 또한 이 컴포넌트들은 엄청난 요청을 버틸 확장성과 고가용성이 필요합니다. 현재 Application APIs 는 세가지로 구분할 수 있습니다. 가입하지 않은 사용자의 가입과 과금, 무료 사용 등을 다루는 Signup API, 검색과 추천을 다루는 Discovery API, 그리고 스트리밍과 라이센스를 처리하는 Play API 가 그것입니다. Application API의 자세한 컴포넌트의 구조는 아래 그림 5 에서 볼 수 있습니다.

그림 5 . Play 와 Discovery Application API 의 분리

 

  • 최근에 업데이트된 Play API 의 구현에서는 PlayAPI 와 마이크로서비스 간의 네트워크 프로토콜을 gRPC/ HTTP2 로 사용하고 있습니다. gRPC는 “사용 가능한 RPC 메소드이자, Protocol Buffers로 정의된 엔티티를 사용합니다. 그리고 클라이언트의 라이브러리와 SDK에서 사용하는 다양한 프로그래밍 언어로 생성할 수 있습니다.”([13]) 이렇게 바꾸고나니 Application API 를 자동으로 생성하는 클라이언트와 양방향 통신이 가능하도록 통합할 수 있었습니다. 그리고 서로 다른 서비스 간에 코드를 여러 번 만드는 일을 최소한으로 할 수 있었습니다.
  • Application API 는 Hystrix 커멘드를 기본으로하고 있어서 일반적으로 복원 가능한 메카니즘을 제공합니다.

Application API 는 거대한 요청을 다루고 적절한 응답을 주도록 해야하기 때문에 내부 프로세스가 매우 병렬적으로 실행되야 합니다. 넷플릭스 팀은 비동기적 I/O([13]) 으로 접근하는 것이 훨씬 나은, 동기적으로 실행되던 조합들을 찾아내었습니다.

 

그림 6 . Application API의 동기적 실행과 비동기적 I/O

 

  • API Gateway 서비스의 각 요청들은 Application API 의 Network Event Loop 에서 처리됩니다.
  • 각 요청들은 getCustomerInfo, getDeviceInfo 와 같은 Hystrix 커맨드 안의 스레드 핸들러가 블로킹합니다. 그리고 Outgoing Event Loop 는 클라이언트마다 만들어지고, non-blocking I/O 로 동작합니다. 한번 마이크로서비스를 호출하거나 타임아웃되었다면 Dedicated thread 가 적절한 응답을 만들어 줄 것입니다.

 

3.2.3 Microservices

마틴 파울러가 정의하기를, “마이크로서비스는 작은 서비스들의 모음(suite)이고, 각 서비스에서 동작하는 프로세스와 통신들은 가벼운 메카니즘을 가진다…” 이 작은 프로그램들은 독립적으로 배포되고 업그레이드 할 수 있다. 왜냐하면 이들 각각이 각자의 데이터를 캡슐화하고 있기 때문이다.

넷플릭스의 마이크로서비스 컴포넌트 구현([11])을 나타내면 아래 그림 7과 같습니다.

그림 7 . Structural component of a microservice

 

  • 마이크로서비스는 혼자서, 또는 다른 마이크로서비스를 REST 또는 gRPC 를 통해 호출하여 동작합니다.
  • 마이크로서비스의 구현은 Application API 에서 설명한 그림 6과 비슷합니다. 요청을 Network Event Loop 에서 받아 결과 값을 다른 마이크로서비스에 돌려줍니다. 이 때의 결과값은 비동기적 non-blocking I/O 의 큐에 쌓여있습니다.
  • 각 마이크로서비스는 각자의 데이터 저장소를 가지고 있고, 최신 결과값을 인메모리 캐시에 저장하고 있습니다. EVCache 는 넷플릭스가 가장 잘 사용하는 마이크로서비스용 캐시입니다.

 

3.2.4 데이터 저장소

AWS 클라우드로 인프라를 마이그레이션할 때, 넷플릭스는 매우 다양한 데이터 저장소를 쓰고 있었습니다. (그림 8) SQL과 NoSQL 들이 서로 다른 목적으로 쓰이고 있었습니다.([6])

그림 8 . AWS에 배포된 Netflix의 데이터 저장소

 

  • MySQL 은 영화 제목 관리와 트랜잭션/빌링을 목적으로 사용했습니다.
  • Hadoop은 사용자 로그를 기반으로 하는 빅데이터 처리 목적으로 사용했습니다.
  • Elasticsearch 는 넷플릭스 앱에서 제목 검색을 처리하기 위해 사용했습니다.
  • Cassandra 는 SPOF(Single Point of Failure) 없이 많은 양의 요청을 다루기 위한 분산 column 기반 NoSQL 저장소입니다. 엄청난 양의 쓰기 요청을 받을 때 레이턴시를 최적화하려면, Cassandra 의 최종적 일관성(eventual consistency. [역주] 카산드라에서 한 테이블에 대한 쓰기 동작이 결국에는 일관성을 유지한다는 의미. 활동성 liveness 과 비슷한 의미로 쓰인다.)을 사용했습니다.

 

3.2.5 Stream Processing 파이프라인

Stream Processing 파이프라인 ([14, 3]) 은 넷플릭스의 비즈니스 분석과 개인화 추천에 중추적인 역할을 하고 있습니다. 이것은 생성, 수집, 처리, 집계(aggregation) 그리고 거의 실시간으로 모든 마이크로서비스의 이벤트를 데이터 프로세서로 옮겨줍니다. 그림 9는 이 플랫폼의 다양한 조각들을 보여줍니다.

 

그림 9 . Netflix의 Stream Processing 플랫폼의 핵심

 

  • stream precessing 플랫폼은 조 단위의 이벤트와 페타바이트 단위의 데이터를 하루에 처리합니다. 또한 구독자수에 맞춰서 자동으로 스케일링도 됩니다.
  • Router 모듈은 다른 데이터 처리기로 라우팅하게 해줍니다. 또한 Kafka 같은 어플리케이션은 메시지 라우팅과 downstream 시스템을 buffering 을 하는 역할을 합니다.
  • Stream Processing as a Service (SPaaS) 는 데이터 엔지니어가 커스텀된 stream processing 어플리케이션을 만들고 모니터링하도록 해줍니다. 이 어플리케이션들은 확장성과 연산 과정들을 관리해주어야 하기 때문입니다.

 

3.3 Open Connect

Open Connect 는 글로벌 CDN(Content Delivery Network)입니다. 넷플릭스 TV쇼와 영화를 저장하고 전세계의 구독자들에게 보내줍니다(delivery). 넷플릭스는 사람들이 원하는 것이 무엇이든, 어디서든 가장 가까운 곳에서 효율적으로 받아보도록 Open Connect를 만들어 운영하고 있습니다. 넷플릭스 비디오의 트래픽을 사용자의 네트워크까지 가져가려면 넷플릭스는 ISPs(인터넷 서비스 제공자), IXs(또는 IXPs. Internet Exchangee Points)와 파트너쉽을 맺어, 그들의 네트워크 안에 Opan Connect Appliances 라는 특별한 장비를 전 세계에 배포했습니다.([7])

 

그림 10 . OCAs 에서 IXs 또는 ISPs Sites 로의 배포


OCAs는 IX 또는 ISP 사이트에서 직접 구독자의 집으로 커다란 사이즈의 비디오 파일을 저장하고 스트리밍할 수 있도록 최적화된 서버입니다. 이 서버들은 주기적으로 IXP/ISP 네트워크의 최적화된 라우팅을 health metrics로 보내줍니다. 또한 OCA 의 SSD 디스크에 어떤 비디오를 저장하고 있는지를 AWS에 있는 Open Connect Control Plane 서비스에 보내줍니다. 그리고 Control Plane 서비스는 직접 클라이언트 기기에서 받아온 데이터로 가장 최적화된 OCA 파일을 자동으로 찾아줍니다.


이 Control Plane 서비스는 밤중에 새로 추가된 파일이나 업데이트된 파일을 채우는 일도 컨트롤합니다. 이렇게 채워주는 동작([8, 9])은 아래 그림 11에서 볼 수 있습니다.

  • 새로운 비디오가 트랜스코딩되면 AWS S3에 저장하고, AWS의 Controle Plane 서비스는 이 파일들을 IXP 에 있는 OCA 서버로 옮겨줍니다. 이 OCA 서버들은 cache fill 을 적용하여 ISP에 있는 서브 네트워크로 파일을 옮깁니다.
  • OCA 서버가 성공적으로 비디오 파일을 저장하면 peer fill 이 시작됩니다. 이 peer fill 은 필요하다면 이 파일들을 복사하여 같은 ISP 서브 네트워크에 있는 다른 OCA 서버로 옮겨줍니다.
  • 서로 다른 IP를 가진 네트워크 사이에서는 cache fill을 사용하는 대신 OCA 가 tier fill 을 적용합니다.

 

그림 11 . OCAs 사이의 Fill 패턴

 

4. 설계 목표

이전 섹션에서 넷플릭스의 비디오 스트리밍 비즈니스를 지탱하는 클라우드 아키텍처와 컴포넌트들을 자세히 살펴보았습니다. 이번 섹션과 이어지는 서브 섹션에서는 이 아키텍처의 디자인에 대해서 깊이 분석해보려고 합니다. 먼저, 가장 중요한 디자인 목표들을 살펴보겠습니다.

  • 글로벌 스케일의 스트리밍 서비스에서는 고가용성이 보장되어야 합니다.
  • 네트워크 실패가 나거나 시스템 부하가 심하게 걸릴 때 복구되어야 합니다.
  • 서로 다른 네트워크 환경에 있는 모든 디바이스에서 스트리밍 레이턴시를 최소화 해야 합니다.
  • 많은 요청을 받을 수 있도록 확장성이 있어야 합니다.

 

아래 서브 섹션에서는 스트리밍 서비스의 가용성과 최적화된 레이턴시에 대해서 분석해보려고 합니다. 섹션 6에서는 Chaos Engineering 과 같은 복구 메커니즘에 대해서 더 깊이 알아보겠습니다. 그리고 섹션 7에서는 스트리밍 서비스의 확장성에 대해서 분석해보겠습니다.

 

4.1 고가용성 High Availability

시스템의 가용성이라는 것은 정해진 시간 내에 들어온 요청에 얼마나 많은 응답을 돌려주었나를 측정하는 것입니다. 정보의 최신성을 보장하지는 않지만요. 이 시스템 설계로는 스트리밍 서비스의 가용성이 Backend 서비스의 가용성과 OCAs 서버가 얼마나 비디오를 스트리밍할 수 있는가에 달려있었습니다.

Backend 서비스의 목표는 가장 건강한 OCAs 가 클라이언트에게 근접해야 한다는 것입니다. 캐시나 다른 마이크로서비스들도요. 그래서 시스템의 가용성은 각자 다른 컴포넌트에게 Playback 요청을 보냅니다. 로드 밸런서 (AWS ELB), 프록시 서버 (API Gateway), Play API, 마이크로서비스들, 캐시 저장소(EVCache) 그리고 데이터 저장소(Cassandra) 에요.

 

로드밸런서는 트래픽을 다른 프록시 서버에 라우팅하여 부하가 오버로딩 되는 것을 막아줍니다. 이렇게하여 로드밸런서는 가용성을 향상시킬 수 있습니다.

Hystrix 커멘드는 어떤 서비스의 실패가 다른 서비스에게로 번지는 것을 막아줍니다. Play API는 이것을 사용하여 마이크로서비스의 타임아웃을 컨트롤합니다.


외부 서비스나 데이터 저장소를 호출할 때, 기대한 것보다 더 오래 걸리는 경우, Play API는 데이터를 캐시에서 가져옵니다. 마이크로서비스는 이렇게 가져온 데이터로 응답을 돌려줄 수 있습니다.


캐시
는 빠른 접근을 할 수 있도록 데이터를 복제합니다.

 


Backend에서 OCA 서버 리스트를 받을 때, 클라이언트는 이 OCA 리스트를 네트워크에서 찾고, 가장 연결하기 좋은 OCA 를 선택합니다.만약 OCA 의 부하가 심하거나 스트리밍 도중 실패한다면, 클라이언트는 다른 OCA 로 붙거나 Platform SDK 로 다른 OCA를 달라고 요청합니다. 따라서 가용성은 ISP나 IXP 안에 있는 모든 OCA 의 가용성과 밀접한 연관이 있다고 할 수 있습니다.
넷플릭스 스트리밍의 높은 가용성은 AWS 의 여러 리전에서 일어나는 복잡한 동작들의 비용과 서비스, 그리고 OCA 서버들의 여유분에 의해 결정된다고 할 수 있습니다.

 

4.2 낮은 레이턴시(Latency)

스크리밍 서비스의 낮은 레이턴시는 대부분 얼마나 빨리 Play API가 건강한 OCA 리스트를 반환하고, 클라이언트가 얼마나 OCA 서버를 잘 선택하는지에 달려있습니다.

Application API 컴포넌트 섹션에서 이야기했듯이, Play API 는 영원히 마이크로서비스가 실행되기를 기다리지는 않습니다. 왜냐하면 Hystrix 커멘드가 캐시의 데이터가 더이상 갱신되지 않기 전에 얼마나 결과를 기다려야 하는지를 조절하기 때문입니다. 이렇게 하는 것은 레이턴시가 납득할 수 있을만큼 낮게 하고, 또한 실패한 서비스가 더 많은 서비스에 전파되는 것을 막기 위해서 입니다.

클라이언트가 즉시 가장 근처의 OCA 서버에 가장 신뢰성 있는 네트워크와 연결되어도, 네트워크가 끊어지거나 OCA 서버에 많은 부하가 걸릴 수도 있습니다. 이것 또한 비디오 성능을 낮추기 때문에 네트워크가 느려지고 있다는 것을 감지해야 합니다.

 

5. Tradeoffs

위에서 설명한 시스템 설계는 아래의 두가지 중요한 trade-off 가 있습니다.

  • 낮은 레이턴시는 일관성을 낮춘다.
  • 높은 가용성은 일관성을 낮춘다.

 

레이턴시와 알관성의 trade-off는 Backend 서비스 설계에서 발생합니다. Play API 는 오래된 데이터를 EVCache에서 빨리 가져오거나, 일관성이 보장되는 Cassandra 같은 데이터 저장소에서 천천히 가져와야 합니다.
비슷하게 가용성도 마찬가지로 일관성과 trade-off 가 있습니다. 응답을 만들 때, 납득할 수 있는 수준의 레이턴시를 제공하려면 가장 최신 데이터가 담겨있는 Cassandra 데이터 저장소에 요청하는 방식으로 마이크로서비스를 실행시키면 안됩니다.
또다른 trade-off 는 확장성과 퍼포먼스입니다([ 21 ]). 확장성을 향상시키려면 인스턴스의 프로세스를 늘려서 더 많은 부하를 주어야 합니다. 이렇게 하면 시스템은 기대했던 퍼포먼스만큼 동작하지 않을 것입니다. 또한 이것은 부하가 잘 밸런싱되지 않는 설계상의 문제가 될 수도 있습니다. 하지만 넷플릭스는 이 trade-off를 AWS의 자동 스케일링으로 해결했습니다. 자세한 내용은 섹션 7에서 설명하겠습니다.

 

 

6. 복원가능성 Resilience

클라우드 시스템은 실패나 장애 상황에서 스스로를 치유할 수 있는 능력이 있어야 합니다. 이것은 넷플릭스가 AWS 클라우드로 옮겨가기 시작한 날부터 세운 장기적인 목표였습니다. 몇가지 시스템이 장애 날 수 있는 상황들은 아래와 같습니다.

의존성이 있는 서비스들 간의 연결(resolving) 실패

마이크로서비스 수행 중 다른 서비스로 실패가 전파되는 현상

API 의 부하가 넘쳐서 발생한 연결 실패

인스턴스의 연결 실패나 OCA 와 같은 서버의 연결 실패

 

이러한 상황을 탐지하고 해결하려 API 게이트웨이 서비스 Zuul ([ 20 ]) 은 재시도, Application API 의 동시 호출 제한 등의 기능을 포함하고 있습니다. 따라서 Application API 는 Hystrix 명령어를 사용해 마이크로서비스의 time-out 을 호출하고, 실패가 전파되는 것을 막으며, 실패된 포인트를 다른 컴포넌트들과 격리합니다.

넷플릭스 기술팀은 또한 카오스 엔지니어링 실행을 잘하기로 유명합니다. 이 아이디어는 의사 랜덤(pseudo-random) 한 에러를 실제 환경에 주입하고, 자동으로 탐지하고, 격리하고, 실패한 것들을 복원시켜 해결책을 찾습니다. 에러는 마이크로서비스를 실행하는 응답을 늦추고, 서비스를 죽이고, 서버와 인스턴스를 멈추게 하고, 한 리전의 모든 인프라 서비스들을 다운시킵니다.([ 5 ]) 넷플릭스는 장애를 탐지하고 해결하는 도구를 사용해 모니터링이 되는 환경에서 실제 프로덕션 실패를 의도적으로 주입했습니다. 이렇게 해서 넷플릭스는 더 커다란 문제가 되기 전에 약점이 무엇인지 빠르게 밝혀내고 있습니다.

 

 

7. 확장성 Scalability

이번 섹션에서는 넷플릭스의 스트리밍 서비스의 확장성에 대해서 분석할 것입니다. 넷플릭스의 스트리밍 서비스는 수평적 확장, 동시 실행과 데이터베이스 파티셔닝을 포함합니다. 다른 부분인 캐시와 로드 밸런싱, 또한 확장성에 대해서는 섹션 4에서 언급했습니다.

첫번째로, EC2 인스턴스의 수평적 확장은 AWS의 Auto Scaling Service에서 제공합니다. 이 AWS 서비스는 요청하는 볼륨이 늘어나거나 인스턴스가 꺼지면, 자동으로 유연하게 인스턴스를 가동시켜줍니다. 또다른 멋진 점은 이런 수천대의 인스턴스의 꼭대기에 넷플릭스의 Titus([ 17 ]) 를 빌드해놓은 것입니다. Titus 는 오픈소스인 컨테이너 관리 플랫폼입니다. 이 플랫폼은 거의 1주일에 3백만 개의 컨테이너를 띄우고 있습니다. 또한 그림 2와 같이 우리 아키텍쳐의 어떤 컴포넌트도 컨테이너 안에서 배포할 수 있습니다. 게다가 Titus 는 컨테이너가 전세계 여러 대륙간의 여러 리전에도 컨테이너를 올릴 수 있게 해줍니다.

두번째로, Application API 의 구현이나 섹션 3.2.2의 마이크로서비스는 Network Event Loop 나 비동기적 Outgoing Event Loop 에서도 병렬적으로 작업을 실행하여 확장성을 늘려줍니다.

마지막으로, Cassandra 와 같은 컬럼이 많은 저장소와 ElastricSearch와 같은 key-value 저장소도 높은 가용성과 확장성을 SPOF(Single Point Of Failure) 없이 제공합니다.

 

 

8. 결론

이 연구는 넷플릭스 스트리밍 서비스의 모든 클라우드 아키텍쳐를 설명했습니다. 또한 서로 다른 설계 목표인 가용성, 레이턴시, 확장성, 그리고 네트워크나 시스템 장애 상황에서의 복구가능성을 분석했습니다. 요약하자면, 실제 서비스에서 증명된 넷플릭스 클라우드 아키텍쳐는 백만 단위의 구독자들에게 몇 천개의 가상 서버로 서비스를 제공하고 있습니다. 그리고 최적화된 레이턴시로 높은 가용성을 가지고 있고, AWS 클라우드 서비스를 사용해 높은 확장성도 가지고 있습니다. 또한 글로벌 스케일의 장애 상황에서도 회복가능성이 있다는 것을 알아보았습니다. 설명한 아키텍처와 컴포넌트들은 믿을만한 온라인 리소스를 통해 알게 되었습니다. 직접 마이크로서비스의 내부 구현이나 퍼포먼스 모니터링 도구, 시스템을 설명하지는 않았지만, 이 연구는 어떻게 일반적인 프로덕션 시스템을 구현할 수 있을까에 대한 레퍼런스가 되어줄 것입니다.

 

 

레퍼런스

  1. Netflix: What Happens When You Press Play? By Todd Hoff on Dec 11, 2017. Link
  2. High Quality Video Encoding at Scale. By Anne Aaron and David Ronca on HighScalability. Dec 9, 2015. Link
  3. Building and Scaling Data Lineage at Netflix to Improve Data Infrastructure Reliability, and Efficiency. By Di Lin, Girish Lingappa, Jitender Aswani on The Netflix Tech Blog. Mar 25, 2019. Link
  4. Ten years on: How Netflix completed a historic cloud migration with AWS. By Tom Macaulay on Computerworld. Sep 10, 2018. Link
  5. The Netflix Simian Army. By Yury Izrailevsky and Ariel Tseitlin on The Netflix Tech Blog. Link
  6. Globally Cloud Distributed Applications at Netflix. By Adrian Cockcroft. Oct 2012. Link
  7. Open Connect Overview. By Netflix. Link
  8. Open Connect Deployment Guide. By Netflix. Link
  9. Netflix and Fill. By Michael Costello and Ellen Livengood. Aug 11, 2016. Link
  10. Automating Operations of a Global CDN. By Robert Fernandes at Strange Loop. Sep 14, 2019. Link
  11. Mastering Chaos — A Netflix Guide to Microservices. By Josh Evans at QCon. Dec 07, 2016. Link
  12. Netflix Revenue and Usage Statistics. By Mansoor Iqbal on BusinessofApps. March 6, 2020. Link
  13. Netflix Play API — Why we build an Evolutionary Architecture. By Suudhan Rangarajan at QCon 2018. Dec 12, 2018. Link
  14. Keystone Real-time Stream Processing Platform. By Zhenzhong Xu on The Netflix Tech Blog. Sep 10, 2018. Link
  15. Netflix Releases Open Source Message Security Layer. By Chris Swan on InfoQ. Nov 24th, 2014. Link
  16. Netflix Open Source. Link
  17. Titus, the Netflix container management platform, is now open source. By Amit Joshi and others. Link
  18. Engineering Trade-Offs and The Netflix API Re-Architecture.By Katharina Probst and Justin Becker on The Netflix Tech Blog. Aug 23, 2016. Link
  19. Kafka Inside Keystone Pipeline. By Real-Time Data Infrastructure Team. April 27, 2016. Link
  20. Open Sourcing Zuul 2. By Arthur Gonigberg and others on The Netflix Tech Blog. May 21, 2018. Link
  21. Performance Vs Scalability. By Beekums. Aug 19, 2017. Link

'Tech Note' 카테고리의 다른 글

Haskell 책 한 권 읽었다  (0) 2021.05.16
테스트 코드는 어떻게 만들까  (1) 2021.03.18
Consistent Hashing 일관된 해싱  (0) 2020.12.27
HTTP/2 HTTP/3 의 차이점  (0) 2019.09.10
Group by 에 대해서  (0) 2019.05.05