본문 바로가기

아키텍처

[조대협 대용량 아키텍처]성능 엔지니어링

성능 엔지니어링(Performance Engineering) : 시스템의 목표 성능(응답 시간과 동시 접속자 수)을 정의하고 이를 달성하기 위해서 시스템의 구조를 반복적으로 개선하는 작업

 

성능 엔지니어링은 언제 해야 하는가?
  • 분석 단계
  • 디자인 단계
  • 개발 단계
  • 테스트 단계
  • 운영 단계
분석 단계

초기 요구 사항 분석 및 시스템 기획 단계에서는 성능에 대한 목표를 정해야 한다.

  • 목표 시간은 어떻게 되는지
  • 시스템을 사용할 총 사용자 수와 시스템을 사용하는 동시 접속자 수가 어떻게 되는지

와 같은 성능 목표를 정의한다. 또한 고려해야 하는 사항 중의 하나는 성능 모델이다. 시스템에 부하가 어떤 패턴으로 들어오는지를 정의할 필요가 있다.

 

예를 들면 게임 시스템으로 가정하자 게임 종류마다 다르겠지만 리그 오브 레전드(롤)이라고 가정하자 롤은 플레이 한 번에 30분 정도 소요되고 한 사용자가 하루에 두 게임 정도를 한다고 가정하면 사용자당 체류 시간은 약 2시간 게임 횟수는 2회/일 그리고 주요 부하 시간이 6~9시간이라고 한다면 오후 6~9시간대라는 성능 모델을 만들 수 있다.

 

초기 성능 정의는 서비스의 종류(웹, 게임, 기업 시스템, 쇼핑, 뱅킹 등)나 사용자 층, 그리고 지역이다 전 세계를 서비스하는 시스템이라면 시스템의 부하는 365일, 24시간 거의 다 걸린다고 봐야 한다.

 

디자인 단계

목표 성능과 용량을 달성할 수 있는 규모로 시스템 설계를 진행한다.

성능 관점에서는 시스템 디자인은 항상 피크 타임(최대 성능)에 맞춰서 디자인된다. 최대 성능을 기반으로 전체 시스템이 감당할 수 있는 용량과 응답 시간을 고려해야 한다.

 

특히 성능과 용량은 애플리케이션 디자인뿐만 아니라 기술을 결정하는데도 많은 영향을 준다. 

  • 어떤 하드웨어를 사용할 것인지
  • 어떤 미들웨어나 프레임워크를 사용할 것인지

따라 용량과 성능의 차이가 많이 발생하기 때문에 디자인 단계부터 성능과 용량을 고려해서 시스템을 설계해야 한다.

 

하드웨어 관점에서는 성능 모델을 산정하고 피크타임을 기준으로 시스템을 설계하고 하드웨어를 구매하였으나 요즘은 클라우드를 이용하여 필요시에만 하드웨어를 탄력적으로 사용하는 Auto Scale out 모델을 많이 사용한다.

  • 기업 내부의 업무처럼 부하가 일정하고 예측할 수 있을 때에는 고정된 사이즈의 하드웨어를 사용
  • 출시 이벤트 행사 사이트와 같이 부하가 갑자기 몰리는 시스템은 클라우드를 고려하는 것을 권장

미들웨어나 프레임워크에서도 정의된 성능 모델에 따라 적절한 제품군과 설계 구조를 채택해야 한다.

100,000명 정도가 사용하는 규모의 시스템에서는 RDBMS를 사용해도 성능이나 용량에 문제가 없지만 100,000,000명 정도의 사용자를 지원해야 하는 시스템이라면 일반적인 RDBMS보다 샤딩이나 NoSQL과 같은 다른 차원의 접근이 필요하다. 또한 빠른 응답 시간을 요구하는 경우 Redis나 Memcached와 같은 캐시 솔루션을 활용하거나 미들웨어 부분에서는 톰캣과 같은 일반적인 웹 애플리케이션보다 Netty나 Node.js와 같은 고성능 미들웨어를 고려해볼 만하다.

 

이러한 성능이나 용량에 관련된 제품 선정이나 설계는 돌려 보지 않으면 사실 확신하기 어렵기 때문에 가능하면 사용할 기술을 선택한 다음 간단한 프로토타입을 구현하고 시나리오가 단순하 대규모 성능 및 용량 테스트를 해보는 PoC(Proof of Concept) 같은 작업을 이 단계에서 수행하는 것을 권장한다.

 

개발 단계

리스크가 높은 부분과 아키텍처에 관련되는 부분, 난도가 높은 부분, 핵심 기능 등을 개발 초기의 스프린트에서 개발한다

 

초기 스프린트가 끝나고 릴리즈가 돼서 성능 테스트가 가능한 QA나 스테이징 환경으로 시스템이 이전되면 성능 엔지니어링 역량을 이 단계에서 집중하여 시스템의 아키텍처와 모듈들이 성능 목표를 달성할 수 있는지 지속적으로 테스트하고 튜닝을 수행해야 한다.

 

초기 단계에 성능 목표의 달성 가능 여부가 판단되어야 아키텍처 변경이 가능하고 주요 성능 이슈들을 초반에 발견해야 성능에 대해서 같은 문제가 발생하지 않도록 디자인 가이드나 코딩 가이드를 개발자들에게 배포하여 위험도를 줄일 수 있다.

 

최종 테스트 단계

앞의 단계에서 성능과 용량을 고려하여 설계했고 개발 초기 단계에서 성능과 용량 부분의 검증을 제대로 하였다면 최종 테스트 단계에서는 개발된 최종 시스템에 대한 성능, 용량 부분의 측정, 미세 튜닝(애플리케이션의 병목을 찾아 부분적으로 수정하거나 하드웨어나 미들웨어를 설정하는 수준)을 하는 정도로 마무리되어야 한다.

 

이 과정에서 실수로 잘못한 설정이나 코딩의 검증이 이뤄지는데, 이 경우에는 보통 2배에서 크게는 10배까지의 성능 향상이 이루어진다. 이런 경우는 대부분 실수에 의한 것이고 성능이 터무니없이 낮게 나오기 때문에 찾기가 쉽다.

 

운영단계

테스트 시에 발견되지 않은 성능적인 문제가 있을 수 있기 때문에 모니터링 도구를 사용하여 지속적으로 성능을 모니터링하고 성능상에 문제가 있는 부분을 지속적으로 수정해야 한다.

 웹 서버의 access 로그에서 응답 시간을 모니터링하거나 제니퍼와 같은 전문적인 APM(Application Performance Monitoring) 도구나 Ganglia와 같은 시스템 모니터링 도구를 사용하면 시스템의 성능 상태를 알 수 있다. 또한 용량 부분에 대해서도 고민을 해야 한다. 일반적으로 피크 타임의 시스템 용량이 CPU 80% 정도에 다다르면 시스템 용량 증설을 고려해야 한다.

 

마지막으로 운영 단계에서는 성능 엔지니어링 관점으로 챙겨야 하는 부분은 운영 로그의 수집이다.

성능 및 용량 목표 설정은 매우 중요한 과정이다. 특히 용량 목표는 기존 업무 시스템의 사용 패턴을 분석하는 것이 가장 효율적이기 때문에 운영 시스템의 로그를 수집하고 분석하여 성능 모델을 분석 및 보유해두는 것이 좋다.

 

 

시스템 용량 산정

성능에 관련된 용어와 함께 시스템의 목표 용량 산정(Capacity Planning) 방법에 대해서 알아보자

 

Response Time(응답시간)


사용자가 서버에 요청을 한 시간부터 응답을 받을 때까지의 모든 시간을 포함한다. 이 응답 시간은 내부적으로 다음과 같이 조금 더 세분화하여 분리된다.

 

조대협의 서버사이드 대용량 아키텍처와 성능 튜닝 그림 8 - 2

 

Network Time(또는 Latenct Time)

서버에 요청을 보내고 받을 때 소요되는 네트워크 시간을 의미한다.

 

Transaction Time

서버에서 실제 트랜잭션이 처리되는 시간을 의미한다.

 

Think Time

사용자가 보낸 요청에 대한 응답을 받고 웹 페이지를 보거나 화면을 보는 시간을 의미한다.

 

예를 들면 한국의 사용자가 미국의 페이스북을 사용한다고 했을 때 사용자가 웹 브라우저에서 클릭하면 요청이 서버로 도달할 때까지 걸리는 시간이 Network Time(Request), 서버가 요청을 받아서 처리하고 응답하는 시간이 Transaction Time, 그 응답이 사용자의 브라우저까지 도착하는 시간이 Network Time(Response)이다. 이 전체 시간을 합친 것이 Response Time이다.

응답을 받고 나서 사용자가 페이스북을 보는데 걸리는 시간이 Think Time이 된다.Think Time까지 포함하여 다음 요청이 발생하기 까지의 전체 시간을 Request Interval이라고 한다.

 

Concurrent User(동시 사용자)

현재 시스템을 사용하는 사용자를 말한다.

 

 

Active User(액티브 사용자)

현재 시스템에  트랜잭션을 실행하여 부하를 주는 사용자를정의한다.

기존에는 Concureent User와 Active User 간의 차이가 없었다. 시스템을 사용하기 위해서 지속적으로 서버를 부하를 주느냐 주지 않느냐에 따라 Concureent User와 Active User 개념의 차이가 발생한다. 

Active User는 클릭을 통해 그 시간에 서버에 트랜잭션을 발생시키는 사용자를의미한다. Active User의 수는 서버에서 순간 실행되고 있는 스레드 수나 프로세스의 수와 같다.

 

Transaction(트랜잭션)

사용자로 부터의 요청을 다루는 단위를 말한다. 

성능 모델링이나 테스트 시 이 트랜잭션의 정의에 따라서 시스템의 성능이 매우 다르게 정의되기 때문이다.

 

TPS(Transaction Per Second)

초당 처리할 수 있는 트랜잭션의 양을 말한다. 주로 서버의 서능 평가 기준이 된다.

Active User가 순간 트랜잭션을 처리한다고 하면 이를 목표 응답 시간(Response Time)으로 나눈값이 목표 TPS가 된다.

 

HPS(Hit Per Second)

시스템이 처리할 수 있는 모든 웹 요청의 초당 처리량이다.

TPS가 비즈니스 트랜잭션에 대한 처리 시간만을 정의한다면 HPS는 리소스(이미지,자바스크립트)에 대한 요청 처리량을 포함하기 때문에 TPS보다 약 10~20배 높게 나온다

 

Peak Time(피크 타임)

서버가 순간적으로 가장 부하를 많이 받는 순간을 말한다.

보통 서버의 용량 산정이나 성능 설계는 이 시간의 부하량을 기준으로 한다. 일반적인 업무 시스템은 출근 9시~9시30분 사이가 가장 부하가 높다. 이 때 peak를 찍는 순간의 동시 사용자 수와 기준 응답 시간을 성능 목표로 정의하는 것이 일반적이다.

 

위의 개념을 정리해서 공식화하면 아래와 같다.

1. TPS = [Active User] / [Average Response Time]
2. TPS = [Concurrent User] / [Response Interval]
3. Active User = Tps * [Average Response Time]
4. Active User = [Concurrent User] * [Average Response Time] / [Response Interval]
5. Active User = [Concurrent User] * [Average Response Time] / [ [Response Interval] + [Average Think Time] ]

 

위의 공식은 이론적인 공식이다. Network Latency 값은 가변적이며 Think Time 또한 유동적이다. 그러나 용량 산정에는 어느 정도의 산정 기준이 필요하기 때문에 이 공식을 사용하면 대략적인 시스템의 요구 용량을 예측 할 수 있다.

 

다음 글

[조대협 대용량 아키텍처]성능 엔지니어링 절차

 

[조대협 대용량 아키텍처]성능 엔지니어링 절차

이번 시간에는 성능과 용량을 측정하고 개선하는 절차에 대해서 알아보도록 하자 목표와 모델의 정의 주요 업무 패턴이나 튜닝의 대상이 되는 시나리오의 개별 성능 목표를 정의해보자 예를 들면 전체 성능 목표가..

alsyean.tistory.com


더보기

이 글은 조대협의 서버사이드 대용량 아키텍처와 성능 튜닝 책을 참고하여 작성되었습니다.

이 글은 코드 프레소 DevOps Roasting 코스를 수강하면서 작성한 글입니다.