1장. 사용자 수에 따른 규모 확장성

규모 확장성과 관계된 설계 문제 푸는 데에 유용한 지식들을 배워보자!

1. 단일 서버

  • 단일 서버란? 모든 컴포넌트가 단 한 대의 서버에서 실행되는 시스템 웹, 앱, 데이터베이스, 캐시 등이 모두 서버 한 대에서 실행
  • 사용자 요청 처리 흐름 1) 사용자 : 도메인 이름을 통해 웹사이트 접속 2) DNS(third party 유료 서비스) 조회 결과로 IP 주소 반환 3) 해당 IP주소로 HTTP 요청 전달 4) 요청받은 웹 서버는 HTML 페이지나 JSON 형태의 응답 반환
  • 단말의 종류 1) 웹 애플리케이션 2) 모바일 앱

2. 데이터베이스

  • 이중화 서버 사용자 🔝 단일 서버로는 역부족 1) 웹/모바일 트래픽 처리 서버 2) 데이터베이스 서버
  • 데이터 베이스 종류 1) 관계형 데이터베이스 (relational database)
    • RDBMS (Relational Data-Base Management System)

      관계형 데이터베이스 관리 시스템이라고도 한다.

    • 대표적으로 ..

      MySQL, 오라클 데이터베이스, PostgreSQL

    • 자료

      테이블, 열, 칼럼으로 표현
      
      여러 테이블에 있는 데이터를 관계에 따라 join 가능

      2) 비-관계형 데이터베이스 (irrelational database)

    • NoSQL 이라고도 부름

    • 대표적으로 ..

      CouchDB, Neo4j, Cassandra, HBase, Amazon DynamoDB

    • NoSQL : join 연산X

      a) 키-값 저장소 key-value store

      b) 그래프 저장소 graph store

      c) 칼럼 저장소 column store

      d) 문서 저장소 document store

    • 비-관계형 DB 선택이 바람직한 경우

      아주 낮은 응답 지연 시간(latency) 요구

      다루는 데이터가 비정형

      데이터의 직렬화, 역직렬화만 필요

      아주 많은 양의 데이터 저장

3. 수직적 규모 확장 vs 수평적 규모 확장

  • 수직적 규모 확장 프로세스 1) Scale Up 서버에 고사양 자원(더 좋은 CPU, 더 많은 RAM)을 추가하는 행위 서버로 유입되는 트래픽의 양이 적을 때 Good 2) 장점 단순하다. 3) 단점 한계가 존재 : 한 대의 서버에 CPU, 메모리 무한대 증설할 수 X 장애에 대한 자동복구나 다중화방안 존재 X → 서버에 장애 발생 시 웹 사이트/앱은 완전히 중단
  • 수평적 규모 확장 프로세스란? 1) Scale Out 더 많은 서버를 추가하여 성능을 개선하는 행위 대규모 어플리케이션에서 Good 2) 서버에 장애가 발생한다면? 서버가 다운되거나 너무 많은 사용자가 접속하게 될 경우 부하 분산기 or 로드밸런서 도입하여 해결
  • 로드밸런서 1) 역할 : 부하 분산 집합에 속한 웹 서버들에게 트래픽 부하를 고르게 분산 2) 과정 사용자가 로드밸런서의 공개 IP 주소로 접속 ( = 웹 서버는 클라이언트의 접속을 직접 처리X) → 사설 IP 주소로 로드밸런서와 웹 서버가 통신 (사설 IP 주소 : 같은 네트워크에 속한 서버 사이의 통신에만 쓰일 수 있는 IP주소, 인터넷을 통해서는 접속 불가) → 부하를 나누기 위해 새로운 서버 추가 가능
    • 서버 1 다운 → 모든 트래픽은 서버 2로 전송

      → 웹 사이트 전체가 다운되는 일 방지

    • 트래픽 가파르게 증가 → 두 대의 서버로 트래픽을 감당할 수 없는 시점에서 로드밸런서가 대처 (웹 서버 계층에 더 많은 서버 추가) → 로드 밸런서가 자동적으로 트래픽 분산

      3) 한계

      장애의 자동복구나 다중화를 지원 X

      → 데이터베이스 다중화

  • 데이터베이스 다중화 1) 대부분의 DB가 다중화 지원 2) 서버 간 주(master)-부(slave) 관계 설정 원본 → 주서버, write + read 사본 → 부서버, read only 3) 장점
    • 더 나은 성능

      • 분산 처리 : 변경 연산은 주서버에, 읽기 연산은 부서버에
      • 병렬 처리 : 처리될 수 있는 질의 수 증가
    • 안정성(reliability) : 여러 장소에 서버 다중화

      • DB서버 가운데 일부 파괴되어도 데이터 보존
    • 가용성(availability) : 장애 대처 용이
      - 데이터를 여러 지역에 복제

      4) 데이터베이스 서버 가운데 하나가 다운되면?

    • 부 서버가 한 대 뿐인데 다운된 경우

      • 읽기 연산은 한시적으로 모두 주 데이터베이스로 전달
      • 즉시 새로운 부 데이터베이스 서버가 장애 서버를 대체
    • 부 서버가 여러 대인데 다운된 경우

      • 읽기 연산은 나머지 부 데이터베이스 서버들로 분산
      • 새로운 부 데이터베이스 서버가 장애 서버를 대체
    • 주 데이터베이스 서버가 다운된 경우

      • 한 대의 부 서버가 주 서버를 대체

      • 새로운 부 서버 추가

        → 부 서버에 보관된 데이터가 최신 상태가 아닐 경우

      • 없는 데이터는 복구 스크립트를 돌려서 추가

      • 다중 마스터(multi-masters), 원형 다중화(circular replication) 도입

  • 동작 과정
    • 사용자는 DNS로부터 로드밸런서의 공개 IP 주소를 받는다.
    • 사용자는 해당 IP 주소를 사용해 로드밸런서에 접속한다.
    • HTTP 요청은 서버 1이나 서버 2로 전달된다.
    • 웹 서버는 사용자의 데이터를 부 데이터베이스 서버에서 읽는다.
    • 웹 서버는 데이터 변경 연산을 주 데이터베이스로 전달한다. (데이터 추가, 삭제, 갱신 연산 등이 이에 해당한다.)

4. 캐시

  • 캐시란?
    • 값비싼 연산 결과 또는 자주 참조되는 데이터를 메모리 안에 두고
    • 뒤이은 요청이 보다 빨리 처리될 수 있도록 하는 저장소
    • 데이터베이스를 얼마나 자주 호출하느냐에 성능이 크게 좌우 → 캐시가 문제를 완화
  • 응답 시간(latency) 캐시를 붙이고 정적 콘텐츠를 전송 네트워크(CDN)으로 옮기면 개선 가능 성능 ← DB를 얼마나 자주 호출하느냐 (캐시가 완화)
  • 캐시 계층 1) 장점 DB보다 훨씬 빠르다. DB부하 감소 캐시 계층의 규모 독립적 확장 가능 일반적으로 널리 쓰이는 프로그래밍 언어로 API를 제공
    const cacheAvailable = 'caches' in self;
    const cache = await caches.open('my-cache');
    // 캐시로 뭔가를 한다...
    2) 읽기 주도형 캐시 전략(read-through caching strategy) 저장되어있으면 반환 없으면 DB에 질의해서 저장 후 반환 이 외에도 다양한 캐시 전략이 존재
  • 캐시 사용 시 유의할 점 1) 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어날 때 바람직 2) 휘발성 메모리 → 영속적 보관 X 3) 만료 정책 필수! SShort → DB 자주 접근 / LLong → 원본과 차이 4) 데이터 저장소의 원본 ?= 캐시 내의 사본 일관성(consistency) 유지 중요 → 원본, 캐시 갱신하는 연산이 단일 트랜잭션으로 처리 good → but, 어려움 (cf. 페이스북, Scaling Memcache at Facebook) 5) 장애 대응 : 캐시 서버를 한 대만 두는 경우 단일 장애 지점 발생 → 캐시 서버 분산
    • 어떤 특정 지점에서의 장애가 전체 시스템의 동작을 중단시켜버릴 수 있는 경우 → 단일 장애 지점

      6) 캐시 메모리의 적절한 크기

      SSmall → 너무 자주 밀려나 캐시의 성능 저하

      (대응) 캐시 메모리 과할당(overprovision)

      → 캐시에 보관될 데이터가 갑자기 늘어났을 때 생긴 문제도 방지할 수 있게 된다.

      7) 데이터 방출 정책 : 캐시가 꽉 찬 후에 추가로 데이터를 넣어야 할 경우, 기존 데이터를 내보내야 한다.

      대표적) LRU(Least Recently Used) : 마지막으로 사용된 시점이 가장 오래된 데이터를 내보내는 정책

      LFU(Least Frequently Used) : 사용된 빈도가 가장 낮은 데이터를 내보내는 정책

      FIFO(First In First Out) : 가장 먼저 캐시에 들어온 데이터를 가장 먼저 내보내는 정책

5. 콘텐츠 전송 네트워크(CDN)

  • CDN
    • 정적 콘텐츠를 전송하는 데 쓰이는 지리적으로 분산된 서버의 네트워크
    • 이미지, 비디오, CSS, JavaScript 파일 등을 캐시 가능
    • 동작 과정
      • 웹사이트 방문 시, 그 사용자에게 가장 가까운 CDN 서버가 정적 콘텐츠를 전달

      • 사용자가 CDN 서버로부터 멀면 멀수록 웹사이트 로드 속도 줄어듬

        1) 사용자 A가 이미지 URL을 이용해 image.png에 접근

        → URL의 도메인은 CDN 서비스 사업자가 제공

        2) CDN 서버의 캐시에 해당 이미지가 없는 경우, 서버는 원본 서버에 요청하여 파일을 가져옴.

        3) 원본 서버가 파일을 CDN 서버에 반환

        → 응답의 HTTP 헤더에는 해당 파일이 얼마나 오래 캐시될 수 있는지를 설명하는 TTL 값이 들어있다.

        4) CDN 서버는 파일을 캐시하고 사용자A에게 반환

        → 이미지는 TTL에 명시된 시간이 끝날 때까지 캐시

        5) 사용자 B가 같은 이미지에 대한 요청을 CDN 서버에 전송

        6) 만료되지 않은 이미지에 대한 요청은 캐시를 통해 처리

  • CDN 사용시 고려해야 할 사항 1) 비용
    • 보통 제3 사업자(third-party providers)에 의해 운영됨

    • 사용자는 CDN으로 들어가고 나가는 데이터 전송 양에 따라 요금 내야 함

    • 자주 사용하지 않는 콘텐츠를 캐싱하는 것은 이득 X, CDN에서 빼는 것을 고려하자!

      2) 적절한 만료 기한 설정

    • 시의성이 중요한 콘텐츠의 경우 만료 시점을 잘 정해야 함

    • 너무 길면, 콘텐츠의 신선도 하락

    • 너무 짧으면, 원본 서버에 빈번히 접속

      3) CDN 장애에 대한 대처 방안

    • CDN 자체가 죽었을 경우 웹사이트/앱이 어떻게 동작해야하는지 고려해야 함

    • 해당 문제를 감지하여 원본 서버로부터 직접 콘텐츠를 가져오도록 클라이언트를 구성하는 것이 필요

      4) 콘텐츠 무효화 방법

    • 아직 만료되지 않은 콘텐츠여도 CDN에서 제거하는 방법

    • CDN 서비스 사업자가 제공하는 API를 이용한 콘텐츠 무효화

    • 콘텐츠의 다른 버전을 서비스하도록 오브젝트 버저닝(object versioning) 이용

      → 콘텐츠의 새로운 버전을 지정하기 위해서는 URL 마지막에 버전 번호를 인자로 주면 된다.

      ex. image.png?v=2

  • 장점
    • 정적 콘텐츠는 더 이상 웹 서버를 통해 서비스 X, CDN을 통해 제공 → 더 나은 성능 보장
    • 캐시가 데이터베이스 부하를 줄여준다.

6. 무상태(stateless) 웹 계층

  • 무상태 웹 계층
    • 웹 계층을 수평적으로 확장하는 방법
    • 상태 정보(사용자 세션 테이터)를 웹 계층에서 제거해야한다.
    • 상태정보를 지속성 저장소에 보관하고 필요할 때 가져오도록 하는 것이 바람직 → 이렇게 구성된 웹 계층 = 무상태 웹 계층
  • 상태 정보 의존적인 아키텍처
    • 상태 정보를 보관하는 서버
      • 클라이언트 정보(상태)를 유지하여 요청들 사이에 공유
      • 무상태 서버에는 이런 장치 X

7. 데이터 센터

8. 메시지 큐

9. 로그, 메트릭 그리고 자동화

10. 데이터베이스의 규모 확장

11. 백만 사용자, 그리고 그 이상

+) 계속 읽는 중입니당

profile
숭실대학교 컴퓨터학부 21

0개의 댓글