LINE LIVE 서비스의 인코더 레이어 구조

안녕하세요, LINE에서 글로벌 인프라 시스템을 운영하는 조직에서 개발자로 일하고 있는 김수혁입니다. 2017년 12월 10일은 LINE LIVE 서비스가 공개된 지 2년이 되는 날이었습니다. 서비스 출시 후 수많은 개발자들의 노력으로 지금까지 큰 장애없이 원활하게 운영되고 있습니다. 이번 블로그에서는, 라이브 미디어 서비스를 구축하거나 운영해 본 경험이 없는 상태에서 초기 설계와 구축을 진행하면서 개인적으로 고민했던 내용을 정리해 보았습니다.

배경 및 과제

LINE LIVE는 누구든지, 언제든지 방송할 수 있는 서비스로, 예측할 수 없이 많은 사용자가 동시에 원활하게 방송하고 시청할 수 있어야 합니다. 따라서 아래와 같은 내용이 충족되는 구조가 필요하다고 판단하였습니다.


  • 리소스가 부족할 때 시스템을 빠르게 확장할 수 있어야 한다

    얼마나 많은 사용자가 방송 및 시청을 하게 될지 예측하기 어려울 것으로 보고 동시에 많은 처리를 할 수 있어야 합니다.


  • 동시 접속한 모든 사용자에게 방송 및 시청에 대한 안정적인 품질을 보장해야 한다

    LINE LIVE에서는 서비스 내에서의 방송과 시청 이외에도 LINE 공식 계정(OA, Official Account)에서 방송할 때가 있습니다. 이때 방송 시작과 동시에 해당 계정의 친구로 등록된 사용자에게 방송을 알리는 메시지가 발송되고, 그에 따른 동시 접속으로 트래픽 스파이크가 발생할 수 있다고 보았습니다.


  • 초기 구축 이후 변경사항이 발생할 수 있기 때문에 변경에 유연하게 대응 가능해야 한다

    서비스의 성장과 함께 인프라를 변경할 필요가 생길 수 있다고 보고, 컴포넌트간의 결합을 최대한 낮추어 유연하게 변경할 수 있는 구조가 필요하였습니다. 특히, 미디어 서버는 방송하는 사용자가 증가할수록 스케일 아웃이 필요하기 때문에 결합도를 낮추는데 각별히 신경을 썼습니다.

이러한 요구사항을 충족하는 구성은 최근에 많이 사용하는 MSA(MicroService Architecture)와 유사한 형태입니다. 결론적으로 LINE LIVE 의 미디어 서버도 필수적인 트랜스코딩과 리코딩 기능을 제외한 나머지 기능은 최대한 분리하여 애플리케이션 간 결합성을 낮추는 방향으로 설정했습니다.

LINE LIVE 인코더 레이어의 구조

LINE LIVE 인코더 레이어의 전체 흐름은 대략적으로 다음의 그림과 같습니다. 각 컴포넌트에 대한 세부 내용을 참고하여 함께 보시면 전체 흐름을 조금 더 쉽게 이해하실 수 있습니다.

미디어 서버

일반적으로 미디어 서버는 다음의 세 가지 기능을 제공합니다.

  • 사용자가 송출하는 RTMP 신호를 시청자가 볼 수 있게 변환하는 작업
  • RTMP 신호 인증
  • 방송 녹화

조금 더 자세하게 들여다보면 고려해야 할 사항은 다음과 같습니다.


  • 다양한 환경에서도 안정적 시청을 위한 트랜스코딩

    LINE LIVE는 각기 다른 네트워크 환경에서 접속하는 시청자들이 방송을 안정적으로 시청할 수 있도록 다양한 해상도와 bitrate를 제공하고 있습니다. 이를 위해 반드시 필요한 작업이 바로 트랜스코딩입니다. 동영상 트랜스코딩은 서버 리소스를 많이 소모하는 ‘비싼’ 작업이기 때문에, 서버가 많이 필요합니다.


  • 방송을 송출하는 사용자의 증가

    방송을 송출하는 사용자가 증가하면 미디어 서버 수도 함께 증가되어야 합니다. 미디어 서버 수의 변경으로 인해 다른 시스템에 영향을 끼치는 것은 최소화해야 합니다.

LINE LIVE는 Wowza media server를 사용하고 있습니다. Wowza에서 제공하는 인증 기법은 기본적으로 Wowza 서버의 로컬 파일을 기반으로 하는데, 이러한 인증 기법으로는 LINE LIVE 사용자를 관리하기가 쉽지 않습니다. 따라서 LINE LIVE 서비스에서는 Wowza가 기본으로 제공하는 인증 기능을 사용하는 대신 별도의 인증 시스템을 구축하여, 이를 LINE 서비스와 연동하는 안을 검토하였습니다. Wowza는 외부 인증 시스템과의 연동을 지원하는 SDK를 제공하지만, 안정성 문제로 인해 사용하지 않게 되었습니다. 자체 모듈을 개발한다해도, 자체 개발 모듈에 대한 안정성을 검증할 수 있는 시간이나 개발 리소스 모두 부족한 상황이었습니다. 또한, Wowza 버전이 업데이트될 때마다 자체 제작한 모듈의 동작 여부를 확인하고 업데이트하는 것은 운영에 부담이 됩니다. 검토한 결과를 바탕으로, 미디어 서버에서 인증 기능을 분리하기로 하였습니다.

프록시 서버

미디어 서버에서 인증 모듈을 분리하기로 결정한 후 인증에 대한 대체 방안을 찾기 시작했습니다. 인중 모듈이 반드시 수행해야 하는 작업은 다음과 같이 두 가지였습니다.

  • RTMP 신호를 받으면 LINE LIVE 인증 시스템에 확인 후 RTMP 신호를 accept하거나 drop하기
  • 인증에 성공하면 RTMP 신호를 미디어 서버로 릴레이하기

즉, 우리는 RTMP 신호를 제어(proxy)할 수 있는 애플리케이션이 필요했습니다. 조사한 바에 따르면 일반적으로 사용되는 구조는 미디어 서버의 로드 밸런싱을 위해 HAProxy를 사용하는 것이었습니다. HAProxy를 사용하면 RTMP 신호를 릴레이할 수 있지만, 미디어 서버가 추가되거나 제거되었을 때 모든 프록시 서버의 설정을 변경해야 하는 부담이 있었고, 인증에 대한 부분이 해결되지 않았습니다. 인증을 해결하기 위해서 HAProxy와 Lua 스크립트를 이용하는 안에 대한 가능성을 검토하던 중 FIFA 2014 World Cup live stream architecture 기사를 보고 nginx-rtmp-module(Nginx 기반의 rtmp-module)도 함께 검토하게 되었습니다. nginx-rtmp-module을 이용하여 인증과 RTMP 신호 릴레이에 대한 부분을 PoC(Proof of Concept)를 통해 확인한 결과, 프록시 서버를 문제 없이 구성할 수 있었습니다. 추가적으로 로드 테스팅(load testing)과 long-running 테스트 등을 통해 사용 적합성을 검증한 후, nginx-rtmp-module을 LINE LIVE의 프록시 솔루션으로 도입하기로 결정했습니다. 프록시 서버를 도입하게 된 덕분에 미디어 서버가 사용자와 직접 통신하지 않게 됨에 따라 미디어 서버로의 접근을 내부망에서만 가능하도록 제한할 수 있게 되었으며, 외부에 노출되는 엔드포인트도 단일화할 수 있게 되었습니다.

매니저 서버

서비스를 안정적으로 운영하기 위해 매니저 서버는 미디어 서버와 운영을 위한 백엔드 시스템 사이에서 다음과 같이 다양한 기능을 처리합니다.

  • 방송에 사용된 streamkey 인증
  • 미디어 서버 모니터링
  • 미디어 서버 로드 밸런싱
  • 동일한 streamkey의 중복 송출 방지
  • 방송 종료 시 VOD 생성 등 후속 작업
  • 아이들 연결(idle connection) 관리

CDN과 오리진 서버

LINE LIVE 사용자가 방송을 안정적으로 시청할 수 있도록 보장하기 위해 LINE LIVE 는 다음의 두 가지 큰 문제를 해결해야 했습니다.

  • CDN 요청에 대한 내부 라우팅
  • 스파이크 트래픽에 대한 안정적인 처리

LINE의 공식 계정(Official Account)은 흔히 수십만 명에서 천만 명 이상의 친구를 가지고 있습니다. LINE 사용자는 LINE 공식 계정이 보낸 메시지의 링크를 클릭하여 방송을 시청하는데, 많은 LINE 사용자들이 짧은 시간 안에 동시에 시청을 시도하게 될 수 있습니다. 이런 상황에서 발생 가능한 문제가 두 가지 있습니다.

첫 번째로, 정상적인 요청을 DDoS로 판단하게 되는 문제입니다. 방송은 CDN을 통해 LINE 사용자에게 제공이 되지만, 짧은 시간 동안 다수의 사용자가 CDN으로 동일한 요청을 보내게 되면, CDN에서 캐시 미스가 발생하여 사용자의 요청이 오리진 서버까지 전달됩니다. 이에 따라 요청이 정상적임에도 불구하고 오리진 서버에서 DDoS로 판단할 수 있을 정도의 요청이 발생할 가능성이 있습니다.

두 번째로, 특정 방송이 어떤 미디어 서버에 할당이 되어 있는지 CDN이 알 수 없음으로 인해 발생하는 문제입니다. 미디어 서버를 할당하는 작업은 매니저 서버가 담당하는데, 미디어 서버는 상황에 따라 동적으로 할당될 수 있습니다. 예를 들어 사용자 A의 방송이 미디어 서버 A에서 인코딩된 후 송출되고 있는 상황에서 서버 장애가 발생하면, 재시도 후 사용자 A의 방송이 미디어 서버 B에서 제공되는 상황이 발생할 수 있습니다. CDN은 방송이 어떤 미디어 서버에 할당되어 있는지 모르기 때문에, 이런 변경에 대해 CDN이 즉각적으로 대응하도록 하는 것은 어렵습니다.

위 두 가지 문제를 방지하기 위해 CDN 요청을 처리해 줄 오리진 서버가 필요하며, 오리진 서버는 크게 다음의 두 가지 방법 중 하나로 구축이 가능합니다.

  • A안: 시청에 필요한 정보를 공유 저장소에 저장하고 저장소를 오리진 서버로 설정하기
  • B안: CDN 요청을 미디어 서버와 연결시켜 주는 프록시 서버를 구축하기

구축 방법을 선택함에 있어 저희가 가장 중요하게 고려한 것은, 예상하지 못한 장애가 발생했을 때 장애의 범위를 최소화하는 방법은 무엇인가였습니다. 결론을 먼저 말씀드리면 LINE LIVE는 B안으로 구축했습니다. A안에 대해서는 다음과 같은 문제점이 있었습니다. 공유 저장소를 사용하면, 저장소에 장애가 발생했을 때 장애가 서비스 전체의 장애로 확대될 가능성이 높고, 상황에 따라 장애 시간이 길어질 가능성이 높습니다. 또한 방송의 수가 증가할수록 저장소의 디스크 I/O는 증가하게 되고 저장소 확장이 필요하게 됩니다. 그리고 트래픽 스파이크가 발생했을 때 이를 안정적으로 처리해 줄 수 있는 캐시와 같은 보호 장치가 있어야 합니다.

B안을 선택한 이유는 다음과 같습니다. 프록시 서버로 오리진 서버를 구축하면 CDN 요청을 올바른 미디어 서버로 라우팅할 수 있는 로직을 추가해야 하는데, 라우팅 로직의 코드를 잘 작성하면 라우팅 작업을 전부 메모리에서 처리하게 할 수 있어 디스크 I/O가 발생하지 않습니다. 또한, 장애 유발 범위가 개발자가 작성한 코드로 한정된다는 점과 개별 머신 단위로 조치가 가능하여 예상하지 못한 장애에도 빠르게 대처할 수 있는 점이 공유 저장소와 비교했을 때의 장점입니다.

우리는 프록시 서버에 중요한 캐시 기능을 추가했습니다. 이 기능은 짧은 시간 동안 동일한 요청이 여럿 유입되었을 때, 요청을 큐에 적재하여 최초의 요청만 미디어 서버로부터 받아온 후 캐시하고, 이후 큐에 있는 요청을 캐시 히트(hit)로 처리하는 로직을 포함하고 있습니다. 결론적으로 미디어 서버의 부하 감소는 물론, 상당수의 시청자가 동시에 접속하여 오리진 서버로 동일한 요청이 다수 유입이 된다고 하더라도 미디어 서버의 부하를 일률적으로 유지할 수 있게 되어, 전체적으로 서비스 안정화를 꾀할 수 있게 됩니다.

앞으로

PC 클라이언트로 방송할 수 있는 기능이 출시되면서 게임 방송 등 고화질의 방송이 점점 늘어나고 있어, 이에 대한 대응을 검토하고 있습니다. 또한, 서비스의 성장과 함께 보다 다양한 요구를 충족시키기 위한 최적의 환경을 제공하기 위해 노력하고 있습니다.

글을 맺으며

오랜만에 작성한 글이라 다소 쓰기 어려웠지만, 간단하게나마 LINE LIVE의 일부 기능을 소개할 수 있게 되어 기쁘게 생각합니다. 아래에 LINE LIVE에 대한 발표 자료와 생방송 송출 시스템을 구축할 때 참고할 만한 글의 링크를 몇 개 공유합니다. 특히, LINE LIVE 서비스가 공개된 시점과 비슷한 시점에 게시된 Facebook의 live에 대한 글을 보면 저와 비슷한 고민을 한 것을 볼 수 있습니다. 글을 읽으시는 여러분들 중 비슷한 고민을 하고 계시는 분들께 이 글이 꼭 도움이 되었으면 좋겠습니다.

Related Post