이 글은 책 「가상 면접 사례로 배우는 대규모 시스템 설계 기초」를 공부하고 정리한 글입니다.
오늘은 시스템 규모를 확장하는 방법에 대해 알아볼 것이다.
상태 정보를 관계형 데이터베이스나 NoSQL 같은 지속성 저장소에 보관하고, 필요할 때 가져오도록 구성된 웹 계층을
무상태 웹 계층
이라고 부른다.
상태 정보를 보관하는 서버는 클라이언트 정보
, 즉 상태를 유지하여 요청들 사이에 공유되도록 한다.
사용자 A
의 세션 정보나 프로파일 이미지 같은 상태 정보는 서버 1
에 저장된다. 사용자 A
를 인증하기 위해서 HTTP 요청은 반드시 서버 1
로 전송되어야 한다. 서버 2
에 사용자 A에 관한 데이터는 보관되어 있지 않기 때문에 요청이 서버 2
로 전송되면 인증은 실패한다.
마찬가지로, 사용자 B
로부터 HTTP 요청은 전부 서버 2
로 전송되어야 하고, 사용자 C
로부터의 요청은 전부 서버 3
으로 전송되어야 한다.
문제는, 같은 클라이언트로부터의 요청은 항상 같은 서버로 전송되어야 한다는 것이다.
대부분의 로드밸런서가 이를 지원하기 위해 고정 세션(sticky session)
이라는 기능을 제공하고 있는데, 이는 로드밸런서에 부담을 준다. 게다가 로드밸런서 뒷단에 서버를 추가하거나 제거하기도 까다로워지며, 이들 서버의 장애를 처리하기도 복잡해진다.
이 구조에서 사용자로부터의 HTTP 요청은 어떤 웹 서버로도 전달될 수 있다.
웹 서버는 상태 정보가 필요할 경우 공유 저장소(shared storage)
로부터 데이터를 가져온다. 즉, 상태 정보는 웹 서버로부터 물리적으로 분리되어 있다. 이러한 무상태 아키텍처는 단순하고, 안정적이며, 규모 확장이 쉽다.
세션 데이터를 웹 계층에서 분리하고 지속성 데이터 보관소에 저장하도록 만들었다.
공유 저장소는 관계형 데이터베이스
일 수도 있고, Memcached/Redis 같은 캐시 시스템
일 수도 있으며, NoSQL
일 수도 있다. 이 중에서 NoSQL
을 사용한 이유는, 규모 확장이 간편해서이다.
①의 자동 규모 확장(autoscaling)
은 트래픽 양에 따라 웹 서버를 자동으로 추가하거나 삭제하는 기능을 뜻한다. 상태 정보가 웹 서버들로부터 제거되었으므로, 트래픽 양에 따라 웹 서버를 넣거나 빼기만 하면 자동으로 규모를 확장할 수 있게 되었다.
가용성을 높이고 전 세계 어디서도 쾌적하게 사용할 수 있도록 하기 위해서는 여러 데이터 센터를 지원하는 것이 필수다.
장애가 없는 상황에서 사용자는 가장 가까운 데이터 센터로 안내되는데, 보통 이 절차를 지리적 라우팅(geoDNS-routing 또는 geo-routing)
이라고 부른다. 지리적 라우팅에서의 geoDNS
는 사용자의 위치에 따라 도메인 이름을 어떤 IP 주소로 변환할지 결정할 수 있도록 해 주는 DNS 서비스다.
아래 그림에서, x%
사용자는 US-East 센터
로, 그리고 (100 - x)%
의 사용자는 US-West 센터
로 안내된다.
이들 데이터 센터 중 하나에 심각한 장애가 발생하면 모든 트래픽은 장애가 없는 데이터 센터로 전송된다. 아래 그림은 데이터센터2(US-West)
에 장애가 발생했을 때, 모든 트래픽이 데이터센터1(US-East)
로 전송되는 상황이다.
이 사례와 같은 다중 데이터센터 아키텍처를 만들려면 몇 가지 기술적 난제를 해결해야 한다.
GeoDNS
는 사용자에게서 가장 가까운 데이터센터로 트래픽을 보낼 수 있도록 해 준다.시스템을 더 큰 규모로 확장하기 위해서는 시스템의 컴포넌트를 분리하여, 각기 독립적으로 확장될 수 있도록 해야 한다.
메시지 큐(message queue)
는 많은 실제 분산 시스템이 이 문제를 풀기 위해 채용하고 있는 핵심적 전략 가운데 하나다.
메시지 큐는 메시지의 무손실(durability, 즉 메시지 큐에 일단 보관된 메시지는 소비자가 꺼낼 때까지 안전히 보관된다는 특성)을 보장하는, 비동기 통신을 지원하는 컴포넌트이다. 메시지의 버퍼 역할을 하며, 비동기적으로 전송한다.
생산자(or 발행자)
라고 불리는 입력 서비스가 메시지를 만들어 메시지 큐에 발행한다. 소비자(or 구독자)
라고 불리는 서비스 혹은 서버가 연결되어 있는데, 메시지를 받아 그에 맞는 동작을 수행한다.이미지의 크로핑(cropping)
, 샤프닝(sharpening)
, 블러링(blurring)
등을 지원하는 사진 보정 애플리케이션을 만든다고 해 보자. 이러한 보정은 시간이 오래 걸릴 수 있는 프로세스이므로 비동기적으로 처리하면 편리하다.
사진 보정 작업(job)
을 메시지 큐에 넣는다. 사진 보정 작업(worker) 프로세스
들은 이 작업을 메시지 큐에서 꺼내어 비동기적으로 완료한다.