Ordinary
About

대규모 서비스를 지탱하는 기술 (1 ~ 2)

profileordilov / 2022. 3. 14
대규모 웹 서비스 개발 오리엔테이션

이 책에서 배우는 것

  • 대규모 웹 서비스 개발이란?
  • 대규모 데이터를 다룰 때의 과제, 다루기 위한 기본적인 사고방식
  • 알고리즘과 데이터 구조의 중요성
  • RDBMS로 모두 다룰 수 없는 규모의 데이터 처리 방법
  • 대규모 서비스를 될 것을 전제로 한 서버/인프라 시스템의 예외 개념

대규모 서비스 규모

일일 100만명 이상의 사용자, 일일 액세스 로그가 기본적으로 GB, DB서버는 테라바이트 수준의 서비스입니다. 데이터를 처리하는 서버는 하드웨어적으로 500대 이상으로 가상화로 다루는 호스트의 수는 1000대 이상입니다.

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

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

대량의 액세스가 있는 서비스에서는 서버 1대로 처리할 수 없는 부하를 어떻게 처리할 것인지가 가장 큰 문제입니다. 횡적으로 늘리는 스케일 아웃 구조가 최근에 해결하는 트렌드입니다. 저가의 하드웨어를 여러 개 이용하는 것이 고성능 하나보다 저렴하기 때문에 선택합니다. 하지만 분산되어 있기 때문에 생길 수 있는 문제들이 있습니다.

  • 사용자의 요청을 어떻게 분배할 것인가? (로드 밸런서)
  • 데이터 동기화는 어떻게 할 것인가? (DB 분산)
  • 네트워크 통신의 지연 시간 (통신의 오버헤드)

다중성 확보

시스템은 특정 서버가 고장나거나 성능이 저하되더라도 서비스를 계속할 수 있도록 구성할 필요가 있습니다. 서버 대수가 늘어나면 고장률도 필연적으로 올라가는데 이 중 하나가 고장났다고 전체가 고장나서는 안됩니다. 시스템이 고장나면 끝인 구조와 다른 시스템이 처리를 인계 받는 시스템 구축 간에는 큰 차이가 있습니다.

효율적 운용 필요

서버가 여러대라면 어떤 서버가 무슨 역할을 하고 있는지, 어떤 상황인지 파악하기 힘듭니다. 부하나, 고장, 디스크 용량, 보안 설정 등 살펴볼 부분이 많습니다. 이를 자동화하고 효율적으로 운용할 수 있는 방법이 필요합니다.

개발자 수, 개발방법의 변화

대규모 서비스라면 여러 기술자가 역할을 분담해지는데 표준화가 필요해집니다. 어떤 라이브러리, 프레임워크를 사용하고, 코딩 규약, 버전 관리 등 조정이 필요합니다.

대규모 데이터량에 대한 대처

데이터가 많으면 데이터를 모두 메모리에서 처리할 수 없어지고, 캐시 미스로 I/O 처리가 많이 발생합니다. 어떻게 하면 데이터를 적게 가져가서 최리할 수 있을지 고민이 필요합니다.

계속 성장하는 서비스와 대규모화의 벽

대규모화되면서 어려워지는 다른 점은 서비스 자체도 계속해서 성장하고 규모가 확대해나가는 점입니다. 서비스가 사용자가 늘다보면 새로운 서비스도 릴리즈하게 됩니다. 그 과정에서 작은 서비스에서는 오픈 소스와 방법을 찾아서 비용 절감을 하고 시행 착오를 겪습니다. 이후 규모가 커지면서 시스템 병목지점을 찾고 I/O 처리가 많이 필요한 쪽은 메모리를, CPU 부하는 CPU 성능을 중요시하게 구성합니다. 그리고 가상화를 도입해서 서버 가동률과 유지 보수성을 높여 갑니다. 서버 인프라, DB 스키마 검색 엔진등을 처리해나가며 개발과 품질 개선을 수행나갑니다.

소규모일 때부터 대규모를 가정해서 완벽하게 부하분산을 처리할 수 있는 시스템을 설계하면 비용이 너무 많이 나갑니다. 불완전하게 시작하는 경우가 당연히 훨씬 많으며 문제가 복잡해지기 시작했을 때 수정하는 경우가 많습니다.

대규모 데이터 처리 입문

대규모 데이터로의 쿼리

데이터가 커지면 큰 데이터를 조회하면 쿼리를 던져도 결과가 타임아웃 내에 반환하지 못할 수 있습니다. 이는 엄청나게 부하를 많이 주는 것 뿐만 아니라, 서비스에도 장애를 일으킵니다.

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

어려운 점 중 하나는 '메모리 내에서 계산할 수 없다' 입니다. 메모리 내에서 계산할 수 없으면 디스크를 계속 읽어나가면서 검색해야 합니다. 당연히 I/O 처리는 큰 병목 지점이 됩니다. 메모리와 디스크의 속도 차이는 대략적으로 10^5 ~ 10^6 으로 10만 배에서 100만 배 정도 차이납니다.

디스크는 왜 늦을까?

메모리는 전기적인 부품이기 때문에 물리적 구조와 탐색 속도와 그다지 상관없습니다. 하지만 디스크는 헤드를 이동시켜서 읽어낼 부분을 움직이는 물리적인 시간이 필요합니다. 따라서 메모리에 전부 올릴 수 있다면 데이터 탐색 시 오버헤드가 거의 없습니다.

OS 레벨에서의 연구

OS에서 디스크 속도를 조금씩 읽어오면 느리기 때문에 4KB 정도씩 한번에 읽어옵니다. 이렇게 해서 디스크의 회전횟수를 최소화합니다.

전송속도, 버스의 속도차

탐색할 때도 속도의 차이가 있지만 CPU로 데이터를 보내는 버스에서도 속도의 차이가 있습니다. 메모리에서 CPU로 보낼때는 7.5GB/s 정도라면 디스크는 58MB/s로 전송 속도에도 큰 차이가 납니다. 따라서 SSD를 사용해서 탐색속도가 줄더라도 버스 속도를 생각하면 병목이 발생할 수 밖에 없습니다.

Linux 단일 호스트의 분하

하나의 서버에서 처리할 수 없을 때 복수의 호스트를 사용하는 것이기에, 하나를 충분히 사용할 수 있어야 합니다. 성능을 끌어내는 방법은 서버를 얼마나 사용할 수 있는지 정확하게 파악해야 합니다. 여기서 중요한 점은 추측하지 말고 계측해야 하는 것입니다.

병목 규명작업의 기본적인 흐름
Load Average 확인

top이나 uptime으로 시스템의 부하상황을 load average가 낮은데 문제가 있는 경우 외부의 원인을 찾아봅니다.

CPU, I/O 중 병목 원인 조사

load average가 높은 경우 CPU와 I/O 중 어디에 원인이 있는지 확인합니다.

  • top이나 sar로 프로그램이 문제인지, 시스템 프로그램이 원인인지 확인합니다.
  • ps로 프로세스나 CPU 사용시간 등을 보며 원인 프로세스를 찾습니다.
  • 프로세스를 찾은 후 상세하게 조사할 경우 strace나 oprofile로 프로파일링합니다.

CPU에 부하가 있는 경우는 두 가지 중 하나입니다.

  • 디스크나 메모리등 밖의 부분이 원인이 아닙니다.
  • 프로그램에서 CPU에 필요이상의 부하가 걸립니다.

I/O 부하가 있는 경우

  • 특정 프로세스가 극단적으로 메모리를 소비하고 있는지 ps로 확인합니다.
  • 프로그램의 오류로 메모리를 지나치게 사용하고 있는 경우 개선합니다.
  • 자체적으로 메모리가 부족한 경우 메모리 증설을 검토합니다.

OS 튜닝이 기본 성능을 더 뛰어나게 한다기보다 부하 작업을 개선시키는 것으로 보는 것이 좋습니다.

규모 조정의 요소

웹 어플리케이션을 확장시킨다고 하면 CPU 부하의 확장성을 확보하기는 쉽습니다. 간단하게 프록시 서버에서 AP서버 그리고 DB 서버로 요청이 이동한다고 생각합니다. DB 서버에선 I/O 부하가 발생하고 AP 서버는 CPU 부하만 발생합니다. 따라서 AP 서버 호스트가 동일하게 처리만 하면 분산할 수 있고 요청을 분산해줄 로드 밸런서를 구성하면 됩니다.

하지만 I/O 부하의 경우에는 데이터를 쓸 때 어떻게 동기화를 시킬지의 문제가 생깁니다.

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

대규모 데이터는 메모리에서 처리하기 어렵고 디스크는 느리며, 분산 작업 처리는 어렵습니다. 이럴 때 어떻게 해결해나갈지 두 가지 관점이 있습니다.

  • 프로그램의 작성할 때의 요령
  • 프로그램 개발의 근간이 되는 기초라는 점에서 전제로서 알아두었으면 하는 것

대규모 데이터를 다루는 세가지 급소

첫 번째 요령은 '어떻게 하면 메모리에서 처리를 마칠 수 있을까?" 라는 점입니다. 단순한 것으로는 알고리즘을 이용해 탐색 횟수를 줄이는 것입니다. 다음으로는 데이터를 압축하거나 검색 기술을 이용해 읽는 횟수를 최소화합니다. 이렇게 줄어들게 되면 메모리에 캐싱하기도 쉬워집니다.

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

프로그램을 만드는 입장에서 위의 기술들이 중요하다면 그 근간에 필요한 지식들이 있습니다.

  • OS 캐시
  • 분산을 고려한 RDBMS의 운용 방법
  • 대규모 환경에서 사용하는 알고리즘과 데이터 구조

AP 서버의 경우는 늘리면 늘릴수록 속도가 빨라지지만 DB 서버는 늘리더라도 의미가 없는 경우가 자주 있습니다. 따라서 환경에 따라서 어떻게 운용할지 알고 있어야 합니다.

Load average

sar(System Activity Reporter) 명령어를 사용하면 시간대별 CPU 사용률과 I/O 대기 비율을 확인할 수 있습니다. %user는 사용자 모드의 CPU 사용률을, %system은 시스템 모드에서의 CPU 사용률입니다. I.O의 경우 %iowait로 확인 가능합니다.