[웹 개발자를 위한 대규모 서비스를 지탱하는 기술]Chapter 1, Chapter 2

zzarbttoo·2021년 8월 4일
0

이 글은 절판도서 "웹 개발자를 위한 대규모 서비스를 지탱하는 기술" 을 개인적인 용도로 정리한 글입니다. 모든 내용을 정리한 것이 아니라 필요한 부분만 정리했다는 점 양해 부탁드립니다

문제/오류가 있을 시 댓글로 알려주면 감사하겠습니다

Chapter1, 대규모 웹 서비스 오리엔테이션


| 하테나 서비스의 규모

  • 당시 서버 500대, 호스트 1000개를 사용해 트래픽을 처리하는 규모였음(피크 시 트래픽은 430Mbps)
  • 일일 엑세스 로그는 기가 바이트
  • DB 서버가 저장하는 데이터 규모도 대략 기가바이트 ~ 테라바이트였다
  • 참고로 구글, 페이스북은 서버 대수가 수백만대 , 처리 데이터는 테라바이트 ~ 페타바이트의 초대규모였다

| 소규모 서비스와 대규모 서비스의 차이

확장성 확보, 부하분산 필요

  • 스케일업 : 하드웨어의 처리 성능을 높여 처리 능력을 높인다(하나에 CPU, RAM 등을 몰빵)

  • 스케일아웃 : 서버의 역할을 분담하거나 대수를 늘림으로써 시스템의 전체적인 처리 능력을 높여 부하를 분산(서버를 횡으로 늘림)

  • 데이터 동기화, 네트워크 통신 지연시간(이더넷 이용 시 지연 시간 발생) 등 고려

  • 다중성 확보 필요 : 스케일 아웃으로 서버가 여러대이면 고장 확률 높아짐, 시스템 고장 시 다른 시스템이 자동적으로 처리를 인계받는 구축 필요

  • 효율적 운용 필요 : 서버 대수가 사람이 관리하기 어려운 수준으로 많아지면, 감시용 소프트웨어 등을 이용해 자동화 필요

  • 개발자 간 개발 표준화, 팀 매니지먼트, 버전관리 등 필요

  • 대규모 데이터량에 대한 대처 : 데이터는 디스크 -> 메모리 -> 캐시 메모리 -> CPU와 같은 단계를 경유해 처리가 나는데 하드웨어간 속도 차이가 많이 난다. 데이터가 많아지면 캐시 미스가 많이 발생하고 디스크 I/O가 많이 발생한다. 이에 대한 고려 필요

| 하테나의 성장에 따른 시스템 확장

  • 기존 Linux 박스의 저가의 라우터, 아파치 mod_rewrite로 http 분산, MYSQL 레플리케이션으로 DB 분산(서버 추가도 불가)
    -> 병목 지점 측정 후 I/O 부하 높은 서버는 메모리 중시, CPU 부하기 높은 서버는 CPU 중시 형태로 서버를 교체 + OS 가상화를 이용한 유지보수성 높임 + 로직/ DB 스키마 재검토

  • 처음부터 완벽한 부하 분산 시스템을 구축하면 돈이 많이 들기 때문에 불완전하게 시작하는 것이 나을 수도 있다

  • 어느 정도 수용 능력 관리나 서비스 설계 시에 필요 이상으로 데이터를 증가시키지 않는 설계를 포함하는 것이 좋다


    Chapter2, 대규모 데이터 처리 입문

    메모리와 디스크, 웹 애플리케이션과 부하


| 데이터 처리의 어려운 점

| 대규모 데이터 예시

 
 select count(*) from relword;
  • 위 검색을 할 때 3억 레코드 이상 반환되는 테이블이 있다
  • 이러한 데이터에 대해 select * from relword; 를 하면 응답이 반환되지 않을 수 있다(너무나도 대규모)
  • 아무 생각 없이 던진 쿼리에 응답하지 않을 수 있고, 디버깅 시에도 부하가 엄청 걸릴 수 있다

| 대규모 데이터 처리의 어려운 점

메모리 내에서 계산할 수 없다

  • 메모리 내에서 계산이 가능하다면 계산이 빠르겠지만, 데이터가 너무 많아서 메모리에서 데이터를 두고 쓰는게 아니라 디스크에 두고 특정 데이터를 검색하게 된다

1) 탐색 속도 차

  • 디스크는 메모리에 비해 상당히 느리다 (디스크는 IO 시간이 걸린다)
  • 메모리와 디스크의 속도 차는 10^5 (10만)~ 10^6t(100만) 배 차이가 난다
  • 디스크에서 데이터를 읽을 때 헤드의 이동, 디스크의 회전 등의 이유로 탐색 속도가 느려지게 된다(그밖에도 데이터의 산발적 저장 여부, 탐색 알고리즘의 효율성 등등의 이유가 있음)
  • 데이터가 산발적으로 저장되는 것을 막기 위해 OS가 연속된 데이터를 같은 위치에 쌓고 데이터를 4KB 정도를 한꺼번에 읽도록 해 디스크 회전횟수를 최소화 하도록 한다

2) 전송 속도, 버스의 속도 차

  • 메모리와 디스크 모두 CPU 버스로 연결되어있다
  • 메모리와 디스크는 전송 속도에서도 100배 이상 차이가 난다
  • 메모리 : 7.5GB/초, 디스크 : 58MB/초

| Linux 단일 호스트의 부하

  • 단일 호스트의 성능을 끌어내기 (추측 x 계측 o)
  • 병목 규명 작업을 하자

1) Load Average

  • top, uptime 명령어로 Load Average 확인
  • Load Average는 시스템 전체의 부하 상황을 나타내는 지표
  • 이것을 시초로 병목 지점에 대한 조사 시작
  • Load Average가 낮은데, 시스템 전송량이 오르지 않을 경우 소프트웨어 설정, 오류, 네트워크, 원격 호스트 측에 문제가 없는지 확인

2) CPU, IO 병목 원인 조사

  • sar, vmstat으로 시간 경과에 따른 CPU 사용률이나 IO 대기율의 추이 확인을 할 수 있으며 이를 이용해 규명
CPU 부하 조사 
- 사용자 프로그램 처리 병목 여부 or 시스템 프로그램 원인 확인(top, sar 명령어)
- ps로 프로그램 상태, CPU 사용시간을 보면서 원인인 프로세스 확인
- 프로세스를 찾은 후 strace나 oprofile로 추적/프로파일링 해 병목 지점을 좁혀감 

원인 & 대처
- 디스크, 메모리 용량 등 그밖의 부분에서는 병목이 되지 않은 이상적 형태 -> 서버 증설, 프로그램 로직/ 알고리즘 개선 
- 혹은 프로그램이 폭주해서 CPU 에 필요 이상의 부하가 걸리는 것 -> 오류를 제거해서 프로그램이 폭주하지 않도록 함 

IO 부하 조사 
- 프로그램 입출력이 많거나 스왑이 발생해서 디스크 엑세스가 발생하는 상황 
- ps로 특정 프로세스가 극단적 메모리 소비를 하는지 확인 
- 프로그램 오류로 메모리를 지나치게 먹는 프로그램이 있는지 확인 
- 탑재된 메모리가 부족한 경우 메모리 증설, 메모리 증설 불가능할 경우 분산 검토 


- 스왑이 발생하지 않고 디스크로의 입출력이 빈번하게 발생하는 상황은 캐시에 필요 메모리가 부족한지 확인 
- 메모리 증설로 캐시 영역을 확대시킬 수 있는 경우 메모리 증설 
- 메모리 증설로 대응할 수 없는 경우는 데이터의 분산이나 캐시 서버 등을 검토 
- 프로그램을 개선해서 I/O 빈도를 줄이는 것 검토 

  • OS 튜닝은 부하의 원인을 알고 제거하는 것
  • 메모리 증설해서 캐시 영역을 확보해 대응할 수 있는가
  • 원래 너무 데이터량이 많지 않은가
  • 애플리케이션의 IO 알고리즘을 변경할 필요가 있는가
    등을 이용해 대응을 하면 된다

| 규모 조정의 요소

| 규모 조정의 요소

  • 스케일 아웃을 하면 CPU 부하의 확장성을 확봐하기 쉽다
  • HTTP 요청을 받아 DB에 질의하고 DB로부터 응답받은 데이터를 가공해서 HTML로 클라이언트에 반환할 때 기본적으로 CPU 부하만 소요된다 (프록시, APU 서버가 담당할 일)
  • DB에서는 I/O 부하가 걸린다

| 웹 어플리케이션과 부하

  • 프록시 -> AP 서버 -> DB -> 클라이언트 응답
  • AP 서버는 CPU 부하만 걸려서 분산이 간단하다. 데이터를 분산해서 갖고 있는 것이 아니기 때문에 동일한 호스트가 동일하게 작업만 처리하면 된다(대수만 늘리면 됨)
  • 요청을 균등하게 분산하는 것은 로드밸런서가 해준다
  • DB 동기화 때문에 IO 부하는 문제가 발생한다

| DB 확장성 확보의 어려움

  • 디스크 I/O를 많이 발생시키는 구성으로 되어 있으면 속도차 문제가 생긴다
  • 데이터가 커지면 커질수록 메모리에서 처리 못하고 디스크상에서 처리할 수 있는 요건이 늘어남
  • I/O 부하를 분담하고 있는 서버는 애초에 분산처리가 어렵다
  • 그래서 서비스가 무거우니 서버를 늘리자라는 말은 함부로 해선 안되는 말이다

| 두종류의 부하와 웹 애플리케이션

  • top에는 Load Average(평균 부하) 라는 수치가 있다
  • 평균적으로 어느 정도의 태스크가 대기상태로 있었는지를 보고하는 수치다
  • Load Average의 부하는 처리하려고 해도 실행할 수 없어 대기하는 프로세스의 수를 말한다
  • 구체적으로는 PCU 권한이 부여되기를 기다리는 프로세스, 디스크 IO가 완료하기를 기다리고 있는 프로세스를 말한다

| 대규모 데이터를 다루기 위한 기초지식

| 프로그램 작성 요령

  1. 어떻게 하면 메모리에서 처리를 마칠 수 있을까?
  • 디스크 seek 횟수 최소화
  • 국소성을 활용한 분산실현
  1. 데이터량 증가에 강한 알고리즘을 수행한다
  • 선형 검색 -> 이분 검색
  • O(n) -> O(logn)
  1. 데이터 압축이나 검색 기술들을 사용해보자

| 프로그램 개발 한층 아래 기초

  1. OS 캐시
  2. 분산 고려
  3. 대규모 환경에서 알고리즘과 데이터 구조

| Load Average 다음은 CPU 사용률과 IO 대기율

  • sar로 CPU 사용률, IO 대기율 확인 : 시스템 상황 리포트 도구

  • Load Average가 높고 CPU 사용률 수치가 높다면 대기하고 있는 프로세스의 부하 원인은 CPU 리소스 부족이라고 판단할 수 있음

  • 반대로 IO 사용률 수치가 높다면 부하의 원인은 IO

  • 메모리 사용률이나 스왑 발생 상황등을 참조하도록 한다

  • 수치와 프로세스 상태까지 top-down 중심으로 살펴보자

  • sar -P를 이용하면 멀티 CPU에 대한 값을 볼 수 있다

  • 멀티 CPU여도 디스크가 하나면 IO 부하는 분산되지 않는다

  • 멀티코어 환경에서는 CPU 상태를 개별적으로 확인해야한다

profile
나는야 누워있는 개발머신

0개의 댓글