안정 해시 사용 : 수평적 규모 확장성을 위해 요청, 데이터를 서버에 균등하게 나누기 

 

 

해시 키 재배치(refresh) 문제

  • N개의 서버가 있을 때, 부하를 균등하게 나누기 위해 해시 함수 사용
  • serverIndex = hash(key) % N(서버의 개수)
  • hash(key0) % 4 = 1인 경우, 클라이언트가 캐시에 보관된 데이터를 가져오기 위해 서버 1에 접속
  • 서버 풀(server pool) 크기가 고정되어 있고, 데이터 분포가 균등할 때 잘 동작한다.
  • 대규모 캐시 미스(cache miss) : 하지만 서버가 추가되거나 기존 서버가 삭제되면 문제가 생긴다. 
    • 1번 서버 장애 -> 1번 동작 중지 -> 서버 풀 크기 3 변경 -> 나머지 서버 인덱스 값들이 달라짐 

 

안정 해시(consistent has)

  • 해시 테이블 크기가 조정될 때 평균적으로 k/n개의 키만 재배치하는 해시 기술(k:키의 개수, n:슬롯 개수)

 

해시 공간과 해시 링

  • 해시 함수 f를 SHA-1을 사용한다고 가정할 경우
    • 함수의 출력 값 : x0, x1, x2, .. xn
    • 해시 공간 범위 : 0 ~ (2^160)-1
    • 해시 공간 표현

  • 해시 링(hash ring) : 해시 공간의 양쪽을 구부려 접은 형태

 

서버 조회

  • 해시 함수를 사용해서 서버 4개를 해시 링 위에 해시 서버 배치 : s0, s1, s2, s3
  • 해시 링 어느 지점에 해시 키 배치 : k0, k1, k2, k3
  • 키가 저장되는 서버 : 해당 키 위치로부터, 시계 방향으로 링을 탐색해 나가면서 만나는 첫 번째 서버

 

 

서버 추가

  • 키 가운데 일부만 재배치
  • 서버 4추가 시, key0만 재배치
  • key0은 서버 4에 저장된다.

 

서버 제거

  • 하나의 서버가 제거되면 키 가운데 일부만 재배치
  • 서버1이 삭제되면, key1만 서버 2로 재배치

 

기본 구현법 두가지 문제

  • 어떤 서버는 굉장히 큰 해시 공간을 할당 받는 상황이 생길 수 있다.
  • ex. s1 삭제 -> s2 파티션이 다른 파티션 대비 2배로 커짐
  • 가상 노드(virtual node) 또는 복제(replica) 사용 : 키의 균등 분포 문제 해결을 위해 사용한다.

 

가상 노드

  • 실제 노드 또는 서버를 가리키는 노드
  • 하나의 서버는 링 위에 여러 개 가상 노드를 가질 수 있다.
  • 키가 저장될 서버 : 키의 위치로부터 시계 방향으로 링을 탐색하다가 만나는 최초의 가상 노드
  • ex. k0은 가상 노드 s1_1가 나타내는 서버1에 키 저장

 

 

재배치할 키 결정

  • 서버 추가 or 제거되면 데이터 일부를 재배치해야 한다.

마무리 - 안정 해시 이점

  • 서버 추가 or 삭제시 재배치되는 키의 수 최소화
  • 데이터의 균등한 분포 가능 -> 수평적 규모 확장성 용이
  • 핫스팟 키 문제 축소 

처리율 제한 장치(rate limiter)

  • 클라이언트나 서비스가 보내는 트래픽의 처리율을 제어하기 위한 장치
  • API 요청 횟수가 제한 장치에 정의된 임계치(threshold)를 넘어가면 추가로 도달한 모든 호출은 처리가 중단된다.
    • 사용자는 초당 2회 이상 새 글을 올릴 수 없다.
    • 같은 IP 주소로 하루에 10개 이상 계정 생성 불가능
    • 같은 디바이스로 주당 5회 이상 리워드 요청 불가능

 

API 처리율 제한 장치의 장점

  • Dos(Denial of Service) 공격에 대한 자원 고갈을 방지 
    • ex. 트위터 : 3시간 동안 300개 트윗만 게시 가능
    • ex. 구글 독스 API : 사용자당 분당 300회의 read 요청까지 허용
    • 처리율 제한 장치는 추가 요청에 대해 처리를 중단함으로써 Dos 공격을 방지한다.
  • 비용 절감 : 추가 요청에 대한 처리 제한은 서버를 많이 두지 않아도 되고, 우선순위가 높은 API에 더 많은 자원 할당 가능
  • 서버 과부하 방지 : 봇에서 오는 트래픽이나 사용자의 잘못된 이용을 처리율 제한 장치로 걸러낼 수 있다.

 

 

1단계 : 문제 이해 및 설계 범위 확정

  • 처리율 제한 장치 구현에 여러 가지 알고리즘 적용 가능

 

  • 클라이언트 측 제한 장치? 서버 측 제한 장치인지 확인
  • 서버측 API 인 경우, 어떤 기준으로 API 호출을 제어할 것인지(IP 주소 or 사용자 ID)
  • 시스템 규모는? 사용자가 얼마나 많은 제품인지?
  • 분산 환경에서 동작해야 하는 시스템인지? -> 하나의 처리율 제한 장치를 여러 서버나 프로세스에 공유할 수 있어야 한다.
  • 처리율 제한 장치는 독립된 서비스인가? 애플리케이션 코드에 포함되는지? -> 제한 장치에 장애가 생겨도 전체 시스템에 영향 X
  • 사용자에게 처리율 제한 장치에 걸러진 경우 알림을 줄 것인지? -> 예외 처리

2단계 : 개략적 설계안 제시 및 동의 구하기

  • 처리율 제한 장치는 어디에 둘 것인가?
    • 클라이언트 측
      • 일반적으로 클라이언트 처리율 제한은 안정적인 장소X
      • 클라이언트 요청은 쉽게 위변조가 가능하다.
    • 서버 측 

1. 처리율 제한 장치를 API 서버에 두는 방식  

 

2. 처리율 제한 미들웨어로 API 서버에 가는 요청을 통제하는 방식

    •  

 

  • 예제로, API 서버의 처리율이 초당 2개 요청으로 제한되었을 경우
  • 클라이언트가 3번째 요청을 앞의 2개의 요청들과 같은 초 범위 내에 전송 되었을 때
  • 세 번째 요청은 처리율 제한 미들웨어로 인해 클라이언트에게 HTTP status Code(429 : Too many requests)를 반환한다.

 

MSA(Microservice Architecture)

  • 마이크로서비스 아키텍처
  • 작고, 독립적으로 배포 가능한 각각의 기능을 수행하는 서비스로 구성된 프레임워크
  • 처리율 제한 장치는 보통 API gateway(게이트웨이)라 불리는 컴포넌트에 구현된다.
  • API gateway 
    • 처리율 제한, SSL 종단(termination), 사용자 인증, IP 허용 목록 관리 등을 지원하는 완전 위탁관리형 서비스
    • 클라우드 업체가 유지 보수를 담당하는 서비스
    • 처리율 제한을 지원하는 미들웨어로 외우기

 

처리율 제한 장치 배치 기준

  • 프로그래밍 언어, 캐시 서비스 등 사용 기술 스택 점검하기 
  • 사업에 맞는 처리율 제한 알고리즘 찾기
    • 서버 측에서 모두 구현하면 알고리즘의 선택이 자유롭지만
    • 제 3사업자가 제공하는 게이트웨이를 사용하면 선택지 제한이 생길 수 있다.
  • MSA 구조이고, 사용자 인증과 IP 허용목록 관리 등을 API 게이트웨이로 포함하고 있으면, 처리율 제한 기능도 게이트웨이에 포함해야할 수 있다.

 

처리율 제한 알고리즘

  • 토큰 버킷(token bucket)
  • 누출 버킷(leaky bucket)
  • 고정 윈도 카운터(fixed window counter)
  • 이동 윈도 로그(sliding window log)
  • 이동 윈도 카운터

 

토큰 버킷 알고리즘

  • 보편적인 처리율 제한 알고리즘
  • 토큰 버킷 : 지정된 용량을 갖는 컨테이너.
  • 사전 설정된 양의 토큰이 주기적으로 채워진다. 버킷이 꽉 차면 토큰 추가 불가능
  • 용량이 4인 버킷에서 토큰 공급기가 매초 2개씩 토큰을 추가할 때, 오버플로(overflow) 된 토큰은 버려진다.

  • 충분한 토큰이 있는 경우, 버킷에서 토큰을 하나 꺼내고 요청을 시스템에 전달
  • 충분한 토큰이 없는 경우, 해당 요청은 버려진다.

  • 버킷 알고리즘은 2가지 인자(parameter)를 받는다.
    • 버킷 크기 : 버킷에 담을 수 있는 토큰의 최대 개수
    • 토큰 공급률(refill rate) : 초당 몇 개의 토큰이 버킷에 공급되는가
  • 버킷은 몇개 사용해야 하는지?
    • API 엔드포인트(endpoint)마다 별도의 버킷을 둔다.
    • 사용자가 하루에 한 번 포스팅, 친구는 150명까지 추가 가능, 좋아요 버튼은 다섯 번 까지 누를 수 있으면 사용자는 3개의 버킷을 두어야 한다.
    • IP 주소별로 처리율을 제한하면 -> IP 주소 개수마다 버킷 할당
    • 시스템 처리율을 초당 10,000개 요청으로 제한하면 -> 모든 요청이 하나의 버킷을 공유
  • 토큰 버킷 알고리즘 장점
    • 쉬운 구현과 효율적인 메모리 사용
    • 짧은 시간에 집중되는 트래픽 처리 가능
  • 토큰 버킷 알고리즘 단점
    • 2가지 인자(버킷 크기, 토큰 공급률)의 값을 적절하게 튜닝하는 것이 까다롭다.

 

누출 버킷 알고리즘(leaky bucket)

  • 토큰 버킷 알고리즘과 유사하지만, 요청 처리율이 고정되어 있다.
  • FIFO(First-In-First-Out) 큐로 구현
  • 동작 원리
    • 요청 도착
    • 큐의 크기 확인
      • 빈자리가 있으면 큐에 요청 추가
      • 가득찬 경우 새 요청 버리기
    • 지정된 시간마다 큐에서 요청 꺼내어 처리

  • 누출 버킷 알고리즘은 2가지 인자(parameter)를 받는다.
    • 버킷 크기 : 큐 사이즈와 같은 값
    • 처리율(outflow rate) : 지정된 시간당 몇 개의 항목을 처리할지 지정하는 값
  • 누출 버킷 알고리즘 장점
    • 제한된 큐의 크기 : 효율적인 메모리 사용량
    • 고정된 처리율 : 안정적 출력이 필요한 경우에 적합 
  • 누출 버킷 알고리즘 단점
    • 단시간에 많은 트래픽이 쌓이는 경우, 큐에 오래된 요청이 쌓이고, 요청 처리를 못하면 최신 요청들이 버려진다.
    • 두 개의 인자의 올바른 튜닝의 까다로움

 

고정 윈도 카운터 알고리즘(fixed window counter)

  • 타임라인(timeline)을 고정된 간격의 윈도(window)로 나눈다. 각 윈도에 카운터(counter)를 붙인다.
  • 요청이 접수되면 counter 1씩 증가
  • 카운터 값이 임계치(threshold)에 도달하면, 새로운 요청은 새 윈도가 열릴 때까지 버려진다.
  • 큰 문제점 : 윈도 경계 부근에 순간적으로 많은 트래픽이 집중되면, 윈도 할당량보다 더 많은 요청이 처리될 수 있다.

 

  • 고정 윈도 카운터 알고리즘 장점
    • 메모리 효율이 좋고, 이해하기 쉽다.
    • 특정 트래픽 패턴을 처리하기 적합하다. (윈도가 닫히는 시점에 카운터 초기화)
  • 고정 윈도 카운터 알고리즘 단점
    • 윈도 경계 부근에 순간적으로 많은 트래픽이 몰리면, 시스템 처리 한도보다 많은 양의 요청을 처리한다.

 

이동 윈도 로깅 알고리즘

  • 고정 윈도 카운터 알고리즘 문제 해결
  • 요청의 타임스탬프(timestamp)를 추적한다. 타임스탬프 데이터는 Redis의 정렬 집합(sorted set) 같은 캐시에 보관
  • 새 요청이 오면 만료된 타임 스탬프를 제거한다. (만료된 타임스탬프 = 그 값이 현재 윈도의 시작 시점보다 오래된 타임스탬프)
  • 새 요청 타임스탬프를 로그(log)에 추가
  • 로그의 크기가 허용치보다 같거나 작으면 요청을 시스템에 전달
  • 로그의 크기가 허용치보다 크면 처리 거부

  • 이동 윈도 로깅 알고리즘 장점
    • 처리율 제한 메커니즘이 정교하기 때문에 허용되는 요청 개수가 시스템 처리율 한도를 넘지 않는다.
  • 이동 윈도 로깅 알고리즘 단점
    • 거부된 요청의 타임스탬프도 보관하기 때문에, 다량의 메모리를 사용한다.

 

이동 윈도 카운터 알고리즘(sliding window counter)

  • 고정 윈도 카운터 알고리즘 + 이동 윈도 로깅 알고리즘
  • 동작 원리 
    • 처리율 제한 장치 한도 분당 7개 
    • 현재 1분간 요청 수 + 직전 1분간 요청 수 X 이동 윈도와 직전 1분이 겹치는 비율
    • 현재 윈도에 있는 요청 = 3 + 5 X 70% = 6.5개(내림 6개)

 

  • 이동 윈도 카운터 알고리즘 장점
    • 이전 시간대 평균 처리율에 따라 현재 윈도 상태를 계산해서 짧은 시간에 몰리는 트래픽을 잘 대응할 수 있다.
  • 이동 윈도 카운터 알고리즘 단점
    • 직전 시간대에 도착한 요청이 균등하게 분포되어 있다는 가정에서 추정치를 계산해서 다소 느슨하다.

 

개략적인 아키텍처

  • 얼마나 많은 요청이 접수되었는지를 추적할 수 있는 카운터를 추적 대상별로 둔다.
    • 사용자별로 둘 것인지?
    • IP 주소별
    • API 엔드포인트나 서비스 단위
  • 카운터 값이 한도를 넘으면 다음 요청은 거부하기
  • 카운터 보관 장소는?
    • 데이터베이스는 디스크 접근 때문에 느리다.
    • 메모리 상에서 동작하는 캐시가 빠르고 시간에 기반한 만료 정책을 지원한다.
      • Redis : 처리율 제한 장치를 구현할 때 자주 사용되는 메모리 기반 저장장치. (INCR, EXPIRE 두가지 명령어 지원)
      • INCR : 메모리에 저장된 카운터의 값을 1 증가
      • EXPIRE : 카운터에 타임아웃 값을 설정한다. 설정된 시간이 지나면 카운터 자동 삭제

  • 동작 원리
    • 클라이언트가 처리율 제한 미들웨어에게 요청 전송
    • 처리율 제한 미들웨어는 Redis의 지정 버킷에서 카운터를 가져와서 한도에 도달했는지 검사 
      • 한도 도달 -> 요청 거부
      • 한도 도달 X -> 요청이 API 서버에 전달, 미들웨어는 카운터 값 증가 후 다시 레디스 저장

3단계 : 상세 설계

  • 처리율 제한 규칙은 어디서 만들고 어디서 저장되는지?
  • 처리가 제한된 요청은 어떻게 처리하는지?

 

처리율 제한 규칙

  • 설정 파일(configuration file) 형태로 디스크에 저장
  • 예제 : 시스템이 처리할 수 있는 마케팅 메시지 최대치를 하루 5개로 제한

  • 예제 : 클라이언트가 분당 5회 이상 로그인할 수 없도록 제한

 

 

처리율 한도 초과 트래픽 처리

  • 한도 제한 후 API는 HTTP status (429: too many requests) 응답을 클라이언트에게 보낸다.
  • 또는 큐에 보관할 수도 있다. 

 

처리율 제한 장치가 사용하는 HTTP 헤더

  • 클라이언트가 자기 요청이 처리율 제한에 걸리고 있는지 어떻게 감지?
    • 처리율 제한 장치는 HTTP 응답 헤더(Response header)를 클라이언트에게 보낸다.
      • X-Ratelimit-Remaining : 윈도 내에 남은 처리 가능 요청의 수
      • X-Ratelimit-Limit : 매 윈도마다 클라이언트가 전송할 수 있는 요청의 수
      • X-Ratelimit-Retry-After : 한도 제한에 걸리지 않으려면 몇 초 뒤에 요청을 다시 보내야 하는지 알림

 

  • 처리율 제한 규칙은 디스크에 보관. 작업 프로세스는 수시로 규칙을 디스크에서 읽어 캐시에 저장
  • 클라이언트가 요청을 서버에 보내기 전 처리율 제한 미들웨어에 도달
  • 처리율 제한 미듈웨어는 제한 규칙을 캐시에 가져와서, Redis 캐시에서(카운터, 마지막 요청의 타임스탬프) 정보를 가져온다.
    • 처리율 제한 걸림 : 클라이언트에게 429 too many request error 
    • 처리율 제한에 걸리지 않음 : API 서버로 요청 전달

 

분산 환경에서의 처리율 제한 장치의 구현

  • 여러 대의 서버와 병렬 스레드에서 2가지 문제 해결 필수
    • 경쟁 조건(race condition)
    • 동기화(synchronization)

 

경쟁 조건

  • 병행성이 심한 경우, 경쟁 조건 이슈 발생 확률이 있다.
  • 레디스의 저장된 카운터가 3일 경우, 각각 counter(3) + 1으로 4가 레디스에 기록되야 한다. 하지만 counter가 5가 되어 레디스에 기록되어야 한다.
  • 경쟁 조건 문제를 해결하기 위해서 락(lock)을 사용한다. 하지만 시스템의 성능을 많이 떨어뜨리는 문제가 생긴다.
  • 아래의 설계에서는 락 대신 해결책 2가지 존재
    • 루아 스크립트(Lua script) : 명령형/절차적 언어
    • 정렬 집합(sorted set)이라 불리는 레디스 자료구조 사용

 

동기화 이슈

  • 처리율 제한 장치 서버를 여러 대 둘 경우 동기화 필요
  • 웹 계층은 무상태이기 때문에 각기 다른 제한 장치로 요청 전송 가능
  • 동기화 처리를 하지 않으면, 제한 장치 1이 클라이언트 2에 대한 정보가 없기 때문에, 처리율 제한을 제대로 수행할 수 없다.

  • 동기화 이슈 해결
    • 고정 세션(sticky session) 사용 : 같은 클라이언트부터의 요청을 항상 같은 처리율 제한 장치로 보낼 수 있도록 한다. 하지만 확장 불가능, 유연성 저하로 추천 X
    • 중앙 집중형 데이터 저장소(Redis) 사용 

 

 

성능 최적화

  • 데이터센터 지원 고려 : 데이터 센터에서 멀리 떨어진 사용자를 지원하다가 지연시간(latency)가 증가할 위험이 있다.
  • 제한 장치 간 데이터 동기화에 최종 일관성 모델(eventual consistency model) 사용 

 

모니터링

  • 채택된 처리율 제한 알고리즘이 효과적인지 확인
  • 정의한 처리율 제한 규칙이 효과적인지 확인

4단계 : 마무리

  • 처리율 제한 알고리즘 : 토큰 버킷, 누출 버킷, 고정 윈도 카운터, 이동 윈도 로그, 이동 윈도 카운터
  • 경성(hard) 또는 연성(soft) 처리율 제한 : 경성(임계치 절대 넘기 불가능), 연성(임계치를 잠시 넘을 수 있다.)
  • 다양한 계층에서의 처리율 제한 : 애플리케이션 계층 말고 다른 OSI 7 계층에서도 사용 가능
  • 처리율 제한 회피 방법
    • 클라이언트 측 캐시를 사용하여 API 호출 횟수 감소
    • 처리율 제한 임계치 이해하기. 짧은 시간동안 많은 메시지 보내지 않기
    • 예외나 에러 처리 코드를 도입하여 복구 용이
    • 재시도 로직을 구현할 때 충분한 백오프 시간 두기

효과적 면접을 위한 4단계 접근법

 

1단계 : 문제 이해 및 설계 범위 확정

  • 생각 없이 바로 답을 내놓지 않는다.
  • 요구사항을 정확히 이해하고, 생각하고 질문하여 답을 한다.
  • 필요 질문 예시 
    • 구체적으로 어느 기능을 만드는지?
    • 제품의 사용자 수는?
    • 회사의 규모는 얼마나 빨리 커질 것으로 예상하는지? x 년 이후의 규모는?
    • 회사의 기술 스택은 무엇인지?
  • 예제
    • 모바일 앱, 웹 앱 어느쪽 지원?
    • 가장 중요한 기능은?
    • 뉴스 피드는 시간 역순인지, 정렬기준이 있는지
    • 한 사용자가 최대 몇명의 사용자와 친구를 맺을 수 있는지?
    • 사이트로 오는 트래픽 규모는?
    • 피드에 이미지, 비디오도 가능한지? 아니면 그저 텍스트인지?

 

2단계 : 개략적인 설계안 제시 및 동의 구하기

  • 핵심 컴포넌트를 포함하는 다이어그램을 그린다.
    • 클라이언트(모바일/웹), API, 웹, 서버, 데이터 저장소, 캐시, CDN, 메시지 큐 등등
  • 최초 설계안이 시스템 규모에 관계된 제약사항을 만족하는지 개략적으로 계산하기
  • 예제 - 뉴스 피드 시스템 설계
    • 피드 발행 : 사용자가 포스트를 올리면 관련된 데이터가 캐시/데이터베이스에 기록되고, 해당 사용자의 친구 뉴스피드에 뜬다.
    • 피드 생성 : 어떤 사용자의 뉴스 피드는 해당 사용자 친구들의 포스트를 시간 역순으로 정렬하여 만든다.
     

 

 

 

3단계 : 상세 설계

  • 설계 대상 컴포넌트 사이의 우선순위 정하기
  • 시스템 성능 특성에 대한 질문에는?
    • 시스템의 병목 구간이나 자원 요구량 추정치에 초점 맞추기
  • 단축 URL 생성기 설계 문제에는?
    • 해시 함수 설계를 구체적으로 설명하기
  • 채팅 시스템에 대한 문제는?
    • 어떻게 하면 지연시간(latency)를 줄이고 사용자의 온/오프라인 상태를 표시할 것인지
  • 예제 - 뉴스 피드 시스템
    • 피드 발행
    • 뉴스 피드 가져오기

 

4단계 : 마무리

  • 오류가 발생하면 무슨 일이 생기는지(서버 오류, 네트워크 장애 등)
  • 운영 이슈 논의 - 메트릭은 어떻게 수집하고 모니터링과 로그는 어떻게? 배포는 어떻게 할 것인지?
  • 규모 확장을 어떻게 해나갈 것인지? 

개략적인 규모 추정을 위해서는 규모 확장성 표현에 능숙해야 한다.

  • 2의 제곱수
  • 응답 지연(latency) 값
  • 고가용성

 

2의 제곱수

  • 데이터 최소 단위 : 1 byte = 8bit
  • ASCII 문자 하나 메모리 크기 : 1 byte

 

모든 프로그래머가 알아야 하는 응답지연 값

  • 메모리는 빠르지만 디스크는 아직 느리다.
  • 디스크 탐색(seek) 가능한 피하기
  • 단순한 압축 알고리즘은 속도가 빠르다.
  • 데이터를 인터넷으로 전송하기 전에 가능하면 압축하기
  • 데이터 센터는 여러 지역에 분산되어 있고, 센터들 간에 데이터를 주고 받는 시간은 꽤 걸린다.

 

가용성에 관계된 수치들

  • 고가용성(high availability) : 시스템이 오랜 시간동안 지속적으로 중단 없이 운영될 수 있는 능력
  • SLA(Service Level Agreement) : 서비스 사업자(service provider)와 고객 사이에 맺어진 합의
    • 서비스 사업자가 제공하는 서비스의 가용시간(uptime)이 공식적으로 기술되어 있다.

 

예제 : 트위터 QPS와 저장소 요구량 추정

  • 월간 능동 사용자 3억명
  • 50% 사용자가 트위터를 매일 사용
  • 평균적으로 각 사용자는 매일 2건의 트윗을 올린다.
  • 미디어를 포함하는 트윗은 10%
  • 데이터 5년 보관

 

  • 미디어 저장을 위한 저장소 요구량
    • 1.5억 X 2 X 10% X 1MB = 30TB
    • 5년 미디어 보관을 위한 저장소 요구량 : 30TB X 365 X 5 = 약 55PB

컴퓨터

  • 하드웨어 : 컴퓨터를 구성하는 기계적 장치
  • 소프트웨어 : 하드웨어의 동작을 지시하고 제어하는 명령어 집합

 

하드웨어

  • 중앙처리장치(CPU) : 비교와 연산을 담당하는 ALU와 명령어의 해석을 담당하는 제어장치, 빠른 속도의 데이터 기억장소인 레지스터로 구성
  • 주기억 장치(Main Memory) : 프로그램, 데이터, 연산의 중간 결과를 저장하는 장치
  • 입출력 장치(I/O devices)
  • CPU, MM, I/O 장치는 시스템 버스로 연결되어 있으며, 시스템 버스는 데이터와 명령 제어 신호를 각 장치로 실어나르는 역할을 한다.
    • 용도에 따라 데이터 버스, 주소 버스, 제어 버스로 나뉜다.

 

소프트웨어

  • 시스템 소프트웨어 : 사용자를 위해 응용 프로그램 간의 하드웨어 사용을 제어하고 조정하는 기능을 수행하는 프로그램
    • 운영체제, 컴파일러
  • 응용 소프트웨어 : 사용자의 여러 요구사항을 해결하기 위해 제공되는 프로그램
    • 워드프로세서, 스프레드시트

 

데이터 버스

  • CPU와 기타 장치 사이의 데이터를 전달하는 통로
  • 양방향 버스

 

주소 버스

  • 데이터를 정확하게 전달하기 위해서 기억장치 주소를 정해줘야 한다.
  • 단방향 버스(CPU -> I/O)

 

제어 버스

  • CPU, Main Memory, I/O 장치에 제어 신호를 전달하는 통로
  • 제어 신호 종류 : 기억장치 읽기 및 쓰기, 버스 요청 및 승인, 인터럽트 요청 및 승인, 클락, 리셋 등
  • 양방향 버스

중앙처리장치(CPU) 

  • 연산장치
    • 산술 연산과 논리 연산 수행. (레지스터 -> 필요한 데이터 -> ALU -> 연산 결과 -> 레지스터)
  • 제어 장치
    • 명령어를 순서대로 실행할 수 있도록 제어하는 장치
    • 주기억 장치 -> 프로그램 명령 -> 제어장치에서 해독 -> 기억장치 or 연산장치 or 입출력장치로 보냄
  • 레지스터
    • 명령어 주소, 코드, 연산에 필요한 데이터 등등 데이터들을 임시로 저장

 

CPU 동작 과정

1. 주기억 장치는 입력 장치에서 입력받은 데이터 or 보조기억장치의 프로그램을 읽어온다.

2. CPU는 프로그램 실행을 위해 CPU에 저장된 프로그램 명령어와 데이터를 읽어와 처리하고 다시 주기억장치에 저장한다.

3. 주기억 장치는 처리 결과를 보조 기억장치에 저장하거나 출력 장치로 보낸다.

단일 서버

  • 웹 앱, 데이터베이스, 캐시 등이 전부 서버 한 대에서 실행된다.

 

사용자 요청 처리 흐름

1. 사용자는 도메인 이름(api.mysite.com)을 이용해서 웹사이트에 접속한다. 이 접속을 위해서는 도메인 이름을 DNS에 질의하여 IP 주소로 변환하는 과정이 필요하다.

2. DNS 조회 결과로 IP 주소가 반환된다. (웹 서버의 주소)

3. 해당 IP 주소로 HTTP 요청이 웹 서버에 전달된다.

4. 요청을 받은 웹 서버는 HTML 페이지나 JSON 형태의 응답을 반환한다.

 

두 가지 종류의 단말으로부터 요청

  • 웹 애플리케이션
    • 서버 구현용 언어(자바, 파이썬) : 비즈니스 로직, 데이터 저장 처리
    • 클라이언트 구현용 언어(HTML, JS) : 프레젠테이션용
  • 모바일 앱
    • HTTP 프로토콜 이용 : 모바일 앱과 웹 서버 간 통신 
    • JSON 데이터 포맷 사용

 


데이터베이스

  • 사용자가 증가할 경우, 하나의 서버로는 부족해진다. 여러 서버를 두어야 한다.
  • 아래 그림은 웹/모바일 트래픽 처리(웹 계층)와 데이터베이스(데이터 계층) 용을 따로 분리했다.

 

 

데이터베이스의 종류

  • 관계형 데이터베이스(Relational Database)
    • MySQL, Oracle, PostgreSQL
    • 테이블, 열, 칼럼
    • join 지원
  • 비-관계형 데이터베이스(NoSQL)
    • CouchDB, Neo4j, Cassandra, HBase, Amazon DynamoDB
    • NoSQL의 4가지 분류
      • 키-값 저장소(key-value store) 
      • 그래프 저장소(graph store)
      • 칼럼 저장소(column store)
      • 문서 저장소(document store)
    • join 지원 X

 

NoSQL 활용 예시

  • 아주 낮은 응답 지연시간(latency) 요구되는 경우
  • 다루는 데이터가 비정형(unstructured)이라 관계형 데이터가 아니다.
  • 데이터(JSON, YAML, XML 등)를 직렬화하거나(serialize) 역직렬화(deserial-ize)할 수 있기만 하면 된다.
  • 아주 많은 양의 데이터를 저장해야 하는 경우

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

  • 수직적 확장 : 서버로 유입되는 트래픽 양이 적을 때

 

스케일 업(scale up)

  • 수직적 규모 확장 프로세스
  • 서버에 고사양 자원(더 좋은 CPU, 더 많은 RAM)을 추가하는 행위
  • 단점
    • 확장의 한계, 한 대의 서버에 CPU나 메모리를 무한대로 증설 불가능
    • 장애에 대한 자동복구나 다중화 방안을 제시하지 않는다. -> 장애 시 웹 사이트의 완전 종료

 

스케일 아웃(scale out)

  • 수평적 규모 확장 프로세스
  • 더 많은 서버를 추가하여 성능 개선하는 행위
  • 수직적 규모 확장 프로세스의 단점으로 대규모 애플리케이션을 지원하는 데 수평적 규모 확장 프로세스를 사용한다.

 

로드밸런서(load balancer)

  • 부하 분산 집합에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할
  • 너무 많은 사용자가 접속하거나 웹 서버가 한게 상황에 도달하면 응답 속도가 느려지거나 서버 접속이 불가능해질 수 있다. -> 로드밸런서 도입
  • 사용자는 로드밸런서의 공개 IP 주소로 접속해 웹 서버는 클라이언트의 접속을 직접 처리하지 않는다.
  • 보안 향상을 위해 서버 간 통신에는 사설 IP 주소를 이용함으로싸, 인터넷을 통해서 접속하지 못하게 한다. 로드밸런서는 웹 서버와 통신하기 위해 이 사설 주소를 사용한다.
  • 로드 밸런서는 자동적으로 트래픽을 분산해주기 때문에 서버1이 다운되면, 모든 트래픽은 서버2로 전송한다.

 

 

데이터베이스 다중화

  • 데이터 계층의 문제 해결 방법
  • 서버 사이에 주(master)-부(slave) 관계를 설정하고 데이터 원본은 주 서버에, 사본은 부 서버에 저장하는 방식
    • 주 서버 : 쓰기 연산, insert, delete, update
    • 부 서버 : 주 서버의 사본을 전달받고, 읽기 연산만 지원 
  • 대부분의 애플리케이션은 쓰기 연산 < 읽기 연산 
  • 주 서버보다 부 서버의 수가 더 많다.

  • 다중화의 장점 
    • 더 나은 성능 : 주-부 다중화 모델에서 쓰기 연산은 주 데이터베이스 서버로, 읽기 연산은 부 데이터베이스 서버로 분산된다. 병렬로 처리될 수 있는 질의(query) 수가 늘어나 성능이 향상된다.
    • 안정성 : 데이터베이스 서버 가운데 일부가 파괴되도 데이터의 보존이 가능하다. 
    • 가용성 : 여러 지역에 데이터를 복사해서, 하나의 데이터가 장애가 발생해도 다른 서버에서 복구 가능
    • 주 서버가 다운될 경우?
      • 부 서버가 일시적으로 주 서버가 되고, 부 서버에 보관되었던 데이터가 최신 상태가 아닐 수 있을 경우에는 복구 스크립트(recovery script)를 돌려서 부족한 데이터를 추가해준다.

  • 사용자는 DNS에서 로드밸런서의 public IP를 발급
  • 사용자는 해당 IP 주소로 로드밸런서에 접속
  • HTTP 요청은 서버 1 or 서버 2로 전달
  • 웹 서버는 읽기 연산을 부 데이터베이스 서버로
  • 웹 서버는 쓰기 연산을 주 데이터 베이스로 전달

캐시(Cache)

  • 실행이 오래걸리는 연산이나 자주 참조되는 데이터를 메모리 안에 두고, 요청이 보다 빨리 처리될 수 있도록 하는 저장소
  • 애플리케이션의 성능은 데이터 베이스를 얼마나 자주 호출하느냐에 따라 크게 달라진다.
  • 응답 시간 개선 : 캐시(cache)를 붙이고 정적 콘텐츠를 콘텐츠 전송 네트워크(Content Delivery Network, CDN)으로 이동

 

캐시 계층(Cache tier)

  • 데이터가 잠시 보관되는 곳. 데이터베이스보다 빠르다.
  • 데이터베이스 부하를 줄일 수 있고, 캐시 계층의 규모를 독립적으로 확장 가능
  • 읽기 주도형 캐시 전략(read-through caching strategy) : 웹 서버는 캐시에 응답이 있는지 확인 후, 데이터가 있으면 반환한다. 없으면 데이터베이스에 query로 데이터를 찾아 캐시에 저장한 후 클라이언트에 반환

  • 캐시 서버 이용 방법 - memcached API 사용
SECONDS = 1
cache.set('myKey', 'hi there', 3600 * SECONDS)
cache.get('myKey')

 

캐시 사용 주의 사항

  • 참조가 빈번하게 일어나는 경우
  • 캐시는 휘발성 메모리이기 때문에, 중요 데이터는 지속성 저장소(persistent data store)에 저장
  • 캐시 만료 기준 : 적절한 정책으로 만료 기한을 설정한다.
  • 일관성(consistency) : 데이터 저장소의 원본과 캐시 내의 사본이 같은지? 
    • 저장소의 원본을 갱신하는 연산 = 캐시를 갱신하는 연산이 단일 트랜잭션으로 처리되어야 한다.
  • 캐시 서버를 하나만 둘 경우, 단일 장애 지점(Single Point of Failure, SPOF)이 되어버릴 수 있다. 전체 시스템이 동작 중지가 될 수 있기 때문에 여러 지역에 걸쳐 캐시 서버를 분산해야 한다.
  • 캐시 메모리를 너무 작게 잡을 경우, 데이터가 캐시에 자주 밀려나는 문제가 생긴다. 이 경우 캐시 메모리를 과할당(overprovision)한다.
  • 데이터 방출 정책을 적절하게 적용
    • LRU(Least Recently Used) : 사용이 가장 오래된 데이터부터 내보낸다.
    • LFU(Least Frequently Used) : 사용 빈도가 가장 낮은 데이터부터 내보낸다.
    • FIFO(First In First Out) : 가장 먼저 들어온 데이터를 가장 먼저 내보낸다. 

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

  • CDN : 정적 콘텐츠를 전송하는 데 쓰이는 지리적으로 분산된 서버의 네트워크
  • 동적 콘텐츠 캐싱 : request path, query string, request header, 쿠키 등의 정보에 기반하여 HTML 페이지를 캐시하는 것

 

CDN 동작 과정

  • 사용자가 웹사이트 방문시, 사용자에게 가까운 CDN 서버가 정적 콘텐츠를 전달한다.
  • 정적 콘텐츠 : js, css, 이미지 등등

1. 사용자 A 가 이미지 URL으로 image.png에 접근한다. (URL 도메인은 CDN 서비스 사업자가 제공)

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

3. 원본 서버가 파일을 CDN 서버에 반환. (응답 HTTP header에 파일이 언제까지 캐시될 수 있는지 TTL(Time-To-Live)값이 있다.)

4. CDN 서버는 파일을 캐시하고 사용자 A에게 반환. 이미지는 TTL에 명시된 시간까지 캐시

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

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

 

 

CDN 사용 고려 사항

  • 비용 : CDN은 보통 제 3 사업자(third-party providers)가 운영한다. CDN에 들어가고 나오는 데이터의 전송 양에 따라 비용을 내기 때문에, 자주 사용되지 않는 콘텐츠는 CDN에서 뺸다.
  • 적절한 만료 시한 설정 : 시의성이 중요한(time-sensitive) 콘텐츠는 만료 기간을 잘 정해야 한다. 
  • CDN 장애에 대한 대처 방안 : CDN 자체가 죽을 경우, 웹사이트/애플리케이션이 어떻게 동작해야 하는지 고려하기 -> 원본 서버로부터 직접 콘텐츠를 가져오도록 클라이언트 구성
  • 콘텐츠 무효화(invalidation) 방법 : 아직 만료되지 않은 콘텐츠를 CDN에서 제거할 때 사용
    • CDN 서비스에서 제공하는 API 사용
    • 콘텐츠의 다른 버전을 서비스하도록 오브젝트 버저닝(object versioning) 이용 -> image.png?v=2

 

CDN + Cache

  • CDN : 정적 콘텐츠는 웹 서버를 통해 서비스하지 않고, 성능 개선
  • Cache : 데이터베이스 부하 감소 


무상태(stateless) 웹 계층

  • 웹 계층을 수평적으로 확장하기 위해서는 상태 정보(사용자 세션 데이터 등등)를 웹 계층에서 제거해야 한다.
  • 무상태 웹 계층 : 상태 정보를 RDBMS, NoSQL 같은 지속성 저장소에 보관하고, 필요할 때 가져온다. 

 

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

  • 상태 정보 보관 서버 : 클라이언트 정보(상태 유지)로 요청들 사이에 공유
  • 사용자 A의 정보는 서버 1에 저장되어 있고, 사용자 A를 인증하려면 HTTP 요청이 서버 1으로 전송해야 한다.
  • 같은 클라이언트의 요청은 같은 서버로 전송되어야 하는 문제점 때문에 로드밸런서의 고정 세션(sticky session) 기능을 사용하지만, 부담을 줄 수 있고 확장성에 좋지 않다.

 

무상태 아키텍처

  • 사용자로부터 HTTP 요청은 어떤 웹 서버로도 전달될 수 있기 때문에 상태 정보가 필요한 경우 공유 저장소(shared storage)로부터 데이터를 가져온다.
  • 단순한 구조, 안정적, 규모 확장 용이

 

기존 설계 + 무상태 아키텍처


데이터 센터

  • 여러 지역의 사용자가 쾌적하게 사용할 수 있도록 지원해야 할 때 사용한다.
  • 지리적 라우팅 : 사용자에게 가장 가까운 데이터 센터로 안내되는 것
  • geoDNS는 사용자의 위치에 따라 도메인 이름을 어떤 IP 주소로 변환할지 결정해주는 DNS 서비스

 

다중 데이터센터 아키텍처 고려사항

  • 트래픽 우회 : 올바른 데이터 센터로 트래픽 보내는 방법 찾기
  • 데이터 동기화(synchronization) 
  • 테스트와 배포 : 여러 위치에서 테스트 해보기

메시지 큐(message queue)

  • 시스템을 더 큰 규모로 확장하기 위해 시스템의 컴포넌트를 분리하여 각각 독립적으로 확장될 수 있도록 해야 한다.
  • 메시지의 무손실(durability)을 보장하는, 비동기 통신을 지원하는 컴포넌트
  • 메시지의 버퍼 역할을 하며, 비동기적으로 전송
  • 입력서비스(생산자/발행자)가 메시지를 만들어 메시지 큐에 발행(publish)
    • 소비자 프로세스가 다운되도 메시지 발행 가능
  • 큐에는 서비스 or 서버(구독자/소비자)가 연결되어 있는데, 메시지를 받아 그에 맞는 동작을 수행한다.
    • 생산자 서비스가 가용한 상태가 아니어도 메시지 수신 가능

 

메시지 큐 사용 예시

  • 사진 보정 애플리케이션에서 보정은 시간이 오래 걸릴 수 있는 프로세스이다. -> 비동기적으로 처리하기
  • 웹 서버는 사진 보정 작업을 메시지 큐에 넣고
  • 사진 보정 작업 프로세스는 메시지 큐에서 꺼내면서 비동기적으로 완료한다.

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

  • 로그
    • 에러 로그 모니터링은 시스템의 오류와 문제들을 쉽게 찾아낼 수 있다. 
  • 메트릭
    • 잘 수집된 메트릭은 사업 현황에 유용한 정보를 얻을 수 있고, 시스템의 상태를 쉽게 파악 가능하다.
    • 호스트 단위 메트릭 : CPU, 메모리, 디스크 I/O
    • 종합 메트릭 : 데이터베이스 계층의 성능, 캐시 계층의 성능
    • 핵심 비즈니스 메트릭 : 일별 능동 사용자, 수익, 재방문
  • 자동화
    • 시스템이 복잡해질 때, 개발 생산성을 높이기 위해 사용

 

기존 설계 + 메시지 큐, 로그, 메트릭, 자동화


데이터베이스 규모 확장

  • 수직적 규모 확장법, 수평적 규모 확장법

 

수직적 확장(Scale up)

  • 고성능 자원(CPU, RAM, 디스크) 을 증설하는 방법

 

수평적 확장(sharding)

  • 더 많은 서버를 추가해 성능 향상
  • 샤딩 : 대규모 데이터베이스를 샤드(shard) 단위로 분할하는 기술
  • 샤드는 같은 스키마를 사용하지만, 보관되는 데이터는 중복 X

 

샤딩 전략 고려사항

  • 샤딩 키를 어떻게 정하는지?
  • 데이터 재샤딩
    • 데이터가 너무 많아 하나의 샤드로 불가능한 경우
    • 샤드 간 데이터 분포가 균등하지 않은 경우 -> 샤드 소진 현상 발생 -> 샤드 키 계산 함수를 변경한다, 안정 해시 기법
  • 유명인사 문제 : 특정 샤드에 질의가 집중되어 서버에 과부하 되는 문제
    • 유명인사 각각에 샤드를 하나씩 할당하거나 더 잘개 쪼개주어야 한다.
  • 조인과 비정규화 
    • 하나의 DB를 여러 샤드로 쪼개면, JOIN이 어렵다는 문제가 생긴다.
    • DB를 비정규화 하여 하나의 테이블에서 질의가 수행될 수 있도록 해준다.

 

기존 설계 + RDBMS가 필요 없는 기능 -> NoSQL 이전


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

  • 웹 계층은 무상태 계층
  • 모든 계층에 다중화 도입
  • 가능한 많은 데이터 캐시
  • 여러 데이터 센터 지원
  • 정적 콘텐츠는 CDN으로 서비스
  • 데이터 계층은 샤딩을 통해 규모를 확장하기
  • 각 계층은 독립적 서비스로 분할
  • 시스템을 지속적으로 모니터링하고, 자동화 도구를 활용하기

테스트 주도 개발 (Test-Driven Development)

  • 설계 이후 코드 개발 및 테스트 케이스를 작성하는 것이 아니라
  • 테스트 케이스 작성 후, 실제 코드를 개발하여 리팩토링 하는 절차

 

TDD 방식의 장점

  • 객체 지향적 코드
  • 재설계 시간의 단축
  • 디버깅 시간의 단축
  • 테스트 문서 대체 가능
  • 추가 구현 용이

 

TDD 방식의 단점

  • 생산성 저하

RESTful API

  • 월드 와이드 웹(WWW)와 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식으로
  • 자원을 정의하고 자원에 대한 주소를 지정하는 방법 전반에 대한 패턴
  • REST(Representational State Transfer) 
    • 기본 원칙을 성실히 지킨 디자인을 RESTful 하다고 표현할 수 있다.
    • 하나의 아키텍처로 표현 가능하다.
    • Resource Oriented Architecture : API 설계의 중심에 자원(Resource)이 있고, HTTP Method를 통해 자원을 처리하도록 설계하는 것

 

URL(Uniform Resource Locator) : 실제 위치, 컴퓨터 네트워크에서 리소스가 어디에 있는지 알려주기 위한 규약 

URI(Uniform Resource Identifier) : 자원의 위치 + 자원에 대한 고유 식별자, 특정 리소스를 식별하는 통합 자원 식별자

REST 구성

  • 자원(resource) 
    • 표현 방법 : HTTP URI
    • ex. http://localhost:8080/main
    • 명사로 표현
  • 행위(Verb) : 자원의 행위
    • 표현 방법 : HTTP METHOD
    • GET, POST, PUT, DELETE
  • 표현(Representations)  : 응답 자원의 상태
    • 표현 방법 : HTTP Message Pay Load
    • ex. JSON, XML

 

REST 6가지 원칙

  • Uniform Interface(유니폼 인터페이스)
    • URI으로 지정한 리소스에 대한 조작을 통일되고, 한정적인 인터페이스로 수행하는 아키텍처 스타일
    • HTTP 표준만 맞으면, 어떤 기술도 가능하다.
      • REST API 정의가 HTTP + JSON 이면, 어떤 언어에 종속되지 않고 모든 플랫폼에 사용 가능
  • Stateless(무상태성)
    • 작업을 위한 상태정보를 저장하고 관리하지 않는다. 세션 정보나 쿠키 정보를 관리 X
    • Request만 Message로 처리하고, context 정보를 신경쓰지 않아도 되서 구현 단순
    • API 실행중 실패 발생시 Transaction 복구를 위해 기존의 상태를 저장할 필요가 있다.
    • API 서버는 들어오는 요청만 단순 처리 한다.
  • Caching(캐시 가능)
    • REST는 HTTP(기존 웹표준)을 그대로 사용하기 때문에, HTTP가 가진 캐싱 기능 적용을 할 수 있다. 
  • Code on demand
    • 서버는 고객에게 실제 실행 가능한 코드를 전송해줄 수 있다.
    • applet이나 스크립트 전송으로 클라이언트의 기능 확장이나 커스터마이즈 가능
  • Hierarchical system(계층형 시스템)
    • 다층 계층으로 구성되어, 로드 밸런싱, 보안, 암호화 계층을 추가해 구조상의 유연성을 얻을 수 있다.
  • Client-Server 구조
    • REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을 직접 관리하는 구조
    • 각각의 역할이 확실하게 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간의 의존성이 줄어들게 된다.

 

RESTful API 디자인

  • 리소스와 행위를 명시적이고 직관적으로 분리
    • 리소스(URI)가 가리키는 것은 명사로 표현
    • 행위는 HTTP Method로 표현 - GET(조회), POST(생성), PUT(수정), PATCH(일부 수정), DELETE(삭제)
  • Message는 Header와 Body를 명확하게 분리해서 사용
    • Entity는 Body에 담아 사용
    • 애플리케이션 서버가 행동할 판단의 근거가 되는 컨트롤 정보인 API 버전 정보, 응답받고자 하는 MIME 타입은 header에 담아 사용
      • MIME 유형 : Content-Type
    • header, body는 http header와 http body로 나눌 수 있다.
    • http body에 들어가는 json 구조 분리 가능
  • API 버전 관리
    • 하위 호환성 보장
  • 서버와 클라이언트가 같은 방식으로 사용해서 요청
    • 브라우저는 form-data 형식으로, 서버에서는 Json 형태로 보내지 않고 하나의 형태로 통일한다.
  • URL에 케밥케이스(kebab-case) 사용
[GET] /userInfo
[GET] /user_Info

[GET] /user-Info

 

  • Path Variable에 카멜케이스(camelCase) 사용
[GET] /user/{user_id}

[GET] /user/{userId}

 

 

+ Recent posts