이 글은 책 「가상 면접 사례로 배우는 대규모 시스템 설계 기초」를 공부하고 정리한 글입니다.

오늘은 시스템 규모를 확장하는 방법에 대해 알아볼 것이다.

  • 웹 계층을 수평적으로 확장하기 위해서는 상태 정보를 웹 계층에서 제거해야 하며(무상태),
  • 가용성을 높이고 전 세계 어디서도 쾌적하게 사용하기 위해서는 여러 데이터 센터를 지원해야 하며,
  • 시스템의 컴포넌트를 분리하여 각기 독립적으로 확장될 수 있어야 한다. (메시지 큐 이용)

[ 무상태(stateless) 웹 계층 ]

상태 정보를 관계형 데이터베이스나 NoSQL 같은 지속성 저장소에 보관하고, 필요할 때 가져오도록 구성된 웹 계층무상태 웹 계층이라고 부른다.

1. 상태 정보 의존적인 아키텍처

상태 정보를 보관하는 서버는 클라이언트 정보, 즉 상태를 유지하여 요청들 사이에 공유되도록 한다.

사용자 A의 세션 정보나 프로파일 이미지 같은 상태 정보는 서버 1에 저장된다. 사용자 A를 인증하기 위해서 HTTP 요청은 반드시 서버 1로 전송되어야 한다. 서버 2에 사용자 A에 관한 데이터는 보관되어 있지 않기 때문에 요청이 서버 2로 전송되면 인증은 실패한다.

마찬가지로, 사용자 B로부터 HTTP 요청은 전부 서버 2로 전송되어야 하고, 사용자 C로부터의 요청은 전부 서버 3으로 전송되어야 한다.

문제는, 같은 클라이언트로부터의 요청은 항상 같은 서버로 전송되어야 한다는 것이다.

대부분의 로드밸런서가 이를 지원하기 위해 고정 세션(sticky session)이라는 기능을 제공하고 있는데, 이는 로드밸런서에 부담을 준다. 게다가 로드밸런서 뒷단에 서버를 추가하거나 제거하기도 까다로워지며, 이들 서버의 장애를 처리하기도 복잡해진다.


2. 무상태 아키텍처

이 구조에서 사용자로부터의 HTTP 요청은 어떤 웹 서버로도 전달될 수 있다.

웹 서버는 상태 정보가 필요할 경우 공유 저장소(shared storage)로부터 데이터를 가져온다. 즉, 상태 정보는 웹 서버로부터 물리적으로 분리되어 있다. 이러한 무상태 아키텍처는 단순하고, 안정적이며, 규모 확장이 쉽다.


3. 무상태 웹 계층을 갖도록 기존 설계 변경

세션 데이터를 웹 계층에서 분리하고 지속성 데이터 보관소에 저장하도록 만들었다.

공유 저장소는 관계형 데이터베이스일 수도 있고, 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)로 전송되는 상황이다.

이 사례와 같은 다중 데이터센터 아키텍처를 만들려면 몇 가지 기술적 난제를 해결해야 한다.

1. 트래픽 우회

  • 올바른 데이터 센터로 트래픽을 보내는 효과적인 방법을 찾아야 한다.
  • GeoDNS는 사용자에게서 가장 가까운 데이터센터로 트래픽을 보낼 수 있도록 해 준다.

2. 데이터 동기화(synchronization)

  • 데이터 센터마다 별도의 데이터베이스를 사용하고 있는 상황이라면, 장애가 자동으로 복구되어(failover) 트래픽이 다른 데이터베이스로 우회된다 해도, 해당 데이터센터에는 찾는 데이터가 없을 수 있다.
  • 이런 상황을 막는 보편적 전략은 데이터를 여러 데이터센터에 걸쳐 다중화하는 것이다.

3. 테스트와 배포(deployment)

  • 여러 데이터 센터를 사용하도록 시스템이 구성된 상황이라면 웹 사이트 또는 애플리케이션을 여러 위치에서 테스트해보는 것이 중요하다.
  • 자동화된 배포 도구는 모든 데이터 센터에 동일한 서비스가 설치되도록 하는 데 중요한 역할을 한다.

[ 메시지 큐 ]

시스템을 더 큰 규모로 확장하기 위해서는 시스템의 컴포넌트를 분리하여, 각기 독립적으로 확장될 수 있도록 해야 한다. 메시지 큐(message queue)는 많은 실제 분산 시스템이 이 문제를 풀기 위해 채용하고 있는 핵심적 전략 가운데 하나다.

메시지 큐는 메시지의 무손실(durability, 즉 메시지 큐에 일단 보관된 메시지는 소비자가 꺼낼 때까지 안전히 보관된다는 특성)을 보장하는, 비동기 통신을 지원하는 컴포넌트이다. 메시지의 버퍼 역할을 하며, 비동기적으로 전송한다.

메시지 큐의 기본 아키텍처

  • 생산자(or 발행자)라고 불리는 입력 서비스가 메시지를 만들어 메시지 큐에 발행한다.
  • 큐에는 보통 소비자(or 구독자)라고 불리는 서비스 혹은 서버가 연결되어 있는데, 메시지를 받아 그에 맞는 동작을 수행한다.

메시지 큐 사용 목적

  • 메시지 큐를 이용하면 서비스 또는 서버 간 결합이 느슨해져서, 규모 확장성이 보장되어야 하는 안정적 애플리케이션을 구성하기 좋다.
  • 생산자소비자 프로세스가 다운되어 있어도 메시지를 발행할 수 있고,
    소비자생산자 서비스가 가용한 상태가 아니더라도 메시지를 수신할 수 있다.

메시지 사용 예

이미지의 크로핑(cropping), 샤프닝(sharpening), 블러링(blurring) 등을 지원하는 사진 보정 애플리케이션을 만든다고 해 보자. 이러한 보정은 시간이 오래 걸릴 수 있는 프로세스이므로 비동기적으로 처리하면 편리하다.

  • 웹 서버는 사진 보정 작업(job)을 메시지 큐에 넣는다.
  • 사진 보정 작업(worker) 프로세스들은 이 작업을 메시지 큐에서 꺼내어 비동기적으로 완료한다.
    • 이렇게 하면 생산자와 소비자 서비스의 규모는 각기 독립적으로 확장될 수 있다.
  • 큐의 크기가 커지면 더 많은 작업 프로세스를 추가해야 처리 시간을 줄일 수 있다. 하지만 큐가 거의 항상 비어 있는 상태라면, 작업 프로세스의 수는 줄일 수 있을 것이다.
profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글