티스토리 뷰
Performance Engineering의 정의와 범위
Performance Engineering은 시스템의 목표 성능 (응답 시간과 동시 접속자수)을 정의 하고, 이를 달성하기 위해서, 시스템의 구조를 반복적으로 개선하는 작업을 이야기 한다. 좁게 생각하면, 코드상의 병목을 잡고, 시스템의 설정(Configuration)을 바꿔서 성능을 올리는 튜닝으로 생각할 수 있지만, 성능 목표의 정의에서 부터, 최적의 성능을 내기 위한 디자인 및 구현과 같은 개발 초기의 설계 부분와 개발후의 운영단계에서 모니터링 까지 전과정을 포함한다.
| Performance Engineering은 언제 해야 하는가? |
Performance Engineering은 전체 소프트웨어 개발 과정에 걸쳐서 크게 4단계에 걸쳐서 일어난다. 이 개발 모델은 전형적인 Water fall model이다. 개발프로세스 챕터에서도 설명하였지만, 스크럼과 같은 애자일 방법론을 사용하더라도 큰 범위에서 개발 사이클은 Waterfall 모델과 크게 다르지 않게 된다. (각 단계별을 SPRINT 단위로 수행한다.) |
1. | 분석단계 |
초기 요구 사항 분석 및 시스템 기획 단계에서는 성능에 대한 목표를 정해야 한다. 목표 응답시간은 어떻게 되는지, 시스템을 사용할 총 사용자수와 동시에 시스템을 사용하는 동시접속자 수가 어떻게 되는지와 같은 성능 목표를 정의한다. 또한 고려해야 하는 사항중의 하나는 성능 모델이다. 시스템에 부하가 어떤 패턴으로 들어오는지를 정의할 필요가 있다.
예를 들어 일반적인 웹컨텐츠 사이트의 경우 사용자가 들어와서 페이지 컨텐츠를 1~3분 내에 읽고 다른 페이지로 이동하다가, 20 여분 후에는 로그아웃하거나 다른 사이트로 이동한다. 즉 한 사용자의 체류 시간은 20분정도되며, 총 평균 20 페이지를 보는 트렌젝션을 발생 시키고 나간다고 할 수 있다. 한글로 만든 사이트이고, 육아나 주부를 대상으로 한 사이트라고 가정하면, 시스템의 부하는 한국 시간으로 아이들이 학교나 유치원을 간후인 10시~11시와, 저녁시간대인 10시~12시 사이에 몰린다고 가정할 수 있다.
다른 예로 게임 시스템을 예로 들어보자, 주로 초등학생을 타켓으로 한 게임이라면, 방과후 시간인 3시~5시 대에 부하가 가장 몰릴 것이며, 게임의 종류에 따라 다르겠지만, 스타크래프트와 같은 게임의 경우 한번 플레이에 40분 정도 소요가 되고, 한 사용자가 하루에 두번정도 게임을 한다 가정 아래, 사용자당 체류 시간은 2시간, 게임 횟수는 2회/일. 그리고 주요 부하는 3~5시 오후대 라는 성능 모델을 만들 수 있다.
초기 성능 정의는 서비스의 종류(웹,게임,기업 시스템,쇼핑,뱅킹등) 나, 서비스를 사용하는 사용자층, 그리고 서비스를 사용하는 지역. 즉 전세계를 서비스하는 시스템이라면 시스템의 부하는 365일,24시간 거의 다 걸린다고 봐야 한다. 그러나 한국만을 대상으로 서비스 하는 한국어로 된 사이트인 경우, 새벽 시간에는 일반적으로 로드가 없는 것과 같은 한국의 시간대에 영향을 받을 뿐만 아리나 명절,휴일,휴가와 같은 한국이라는 국가 특성에 따라 시스템의 부하가 영향을 받는다.
2. | 디자인 단계 |
다음으로는 디자인 단계에서는 목표 성능과 용량을 달성할 수 있는 규모의 시스템으로 설계를 진행한다. 성능 관점에서 시스템 디자인은 항상 Peak Time (최대 성능)에 맞춰서 디자인이 된다. 최대 성능을 기반으로 전체 시스템이 받아낼 수 있는 용량과 응답 시간을 고려해야 한다. 특히 성능과 용량은 애플리케이션 디자인 뿐만 아니라 Technology selection에도 많은 영향을 받는다. 어떤 하드웨어를 사용할 것인지, 어떤 미들웨어나 프레임웍을 사용할 것인지이에 따라 용량과 성능의 차이가 많이 발생하기 때문에, 디자인 단계에서 부터 성능과 용량을 감안해서 시스템을 설계해야 한다.
하드웨어 관점에서는 예전에는 성능 모델을 산정한 후에, Peak Time 기준 (최대 성능 요구)으로 시스템을 설계하고, 하드웨어를 구매 하였으나, 근래에는 클라우드를 이용하여 필요시에만 하드웨어를 탄력적으로 사용하는Auto Scale Out 모델을 많이 사용한다.
기업 내부의 업무 처럼 (예를 들어 이메일), 부하가 일정하고 예측이 가능한 경우에는 Fixed 된 사이즈의 하드웨어를 사용하도록 설계 하고, 출시 이벤트 행사 사이트와 같이 부하가 갑자기 몰리는 시스템의 경우 클라우드를 고려해보는 것도 권장할만 하다. 또한 빠른 응답 시간이 필요할 경우 SSD 디스크를 사용하거나, RAID 구성도 5보다는 1+0 등을 고려하는 등, 성능 모델에 따라서 적절한 하드웨어 선정과 구성 설계가 필요하다.
미들웨어나 프레임웍 관점에서도 정의된 성능 모델에 따라 적절한 제품군과 설계 구조를 채택해야 한다. 100,000 사용자 정도의 시스템 규모에서는 RDBMS 를 사용해도 성능이나 용량상에 문제가 없다. 그러나 50,000,000 사용자 정도를 지원해야 하는 시스템의 경우 그냥 RDBMS 를 사용할 수 없다. Sharding이나, NoSQL과 같은 다른 차원의 접근이 필요하다. 또한 빠른 응답 시간을 요구하는 경우 Redis나 Memcached와 같은 Cache 솔루션을 적극적으로 활용하거나, 미들웨어 부분에서는 Tomcat과 같은 일반적은 Web Application Server 보다는 Netty나 Vertex와 같은 고성능 미들웨어를 고려해볼 수 있다.
이러한 성능이나 용량에 관련된 제품 선정이나 설계는 돌려 보지 않으면 사실 확신을 가지기 어렵다. 그래서 가능하면, Technology selection 후에, 간단한 프로토타입을 구현한후에 시나리오가 단순한 대규모의 성능 및 용량 테스트를 해보는 PoC (Proof Of Concept)과 같은 작업을 이 단계에서 수행하는 것을 권장한다.
3. | 개발 단계 |
개발 단계는 개발프로세스 챕터에서 설명하였듯이, risk 가 높은 부분과 아키텍쳐에 관련되는 부분, 난이도가 높은 부분, 핵심 기능등을 개발 초기의 스프린트에서 개발한다. 초기 스프린트가 끝나고 릴리즈가 되서 성능 테스트가 가능한 QA나 스테이징 환경으로 시스템이 이전되면, Performance Engineering 역량을 이 단계에 집중하여, 시스템의 아키텍쳐와 모듈들이 성능 목표를 달성할 수 있는지 지속적으로 테스트하고 튜닝을 수행한다. 초기 단계에 성능 목표의 달성 가능 여부가 판단되어야, 아키텍쳐 변경이 가능하고, 주요 성능 이슈들을 초반에 발견해야, 발견된 성능 문제들에 대해서는 같은 문제가 발생하지 않도록 디자인 가이드나 코딩 가이드를 개발자들에게 배포하여 성능에 대한 위험도를 줄일 수 있다.
4. | 최종 테스트 단계 |
앞의 단계에서 성능과 용량을 고려해서 설계가 되었고, 개발 초기 단계에서 성능과 용량 부분을 검증을 제대로 하였다면, 최종 테스트 단계에서는 개발된 최종 시스템에 대한 성능과 용량 부분의 측정과 미세 튜닝 (애플리케이션의 병목을 찾아서 부분적으로 수정하거나, 하드웨어나 미들웨어의 Configuration 하는 수준)을 하는 정도로 마무리가 되어야 한다.
이 과정에서는 실수로 잘못한 설정(configuration) 이나 잘못된 코딩으로 된 부분에 대해서 검증이 이뤄지는데, 이 경우에는 보통 2배에서 크게는 10배까지의 성능 향상이 이루어진다. 이런 경우는 대부분 실수에 의한 것이고 성능이 터무니 없이 낮게 나오기 때문에 찾기가 쉽다.
예를 들어 로그 파일을 NFS와 같은 리모트 디스크에 쓴다던지, Intel 계열의 CPU에서 하이퍼쓰레딩을 ON을 안했다던지와 같이 실수에 의한 경우가 많다. 이런 오류성의 문제들이 해결되면 실제 미세 튜닝에 들어가게 되는데, JVM 튜닝이나 톰캣의 설정 튜닝, SQL 튜닝들이 이루어지는데, 이 미세 튜닝을 통해서는 비약적인 성능향상은 이루어나지 않는다. 보통 20% 내외 정도 성능이 올라간다고 보면 된다.
5. | 운영단계 |
마지막으로 시스템이 운영 단계로 넘어가게 되면, 테스트시에 발견되지 않은 성능적인 문제가 있을 수 있기 때문에, 모니터링 도구를 사용하여 지속적으로 성능을 모니터링 하고, 성능상에 문제가 있는 부분을 지속적으로 수정해야 한다. 웹서버의 access로그에서 응답 시간을 모니터링 하거나, 제니퍼와 같은 전문적인 APM (Application Performance Monitoring)툴이나, Ganglia와 같은 시스템 모니터링 도구를 사용하면, 시스템의 성능 상태를 잘 알 수 있다.
더불어 용량 부분에 대해서도 운영단에서는 고민을 해야 하는데, 일반적으로PEAK Time의 시스템 용량이 (CPU) 80% 정도에 다다르면, 시스템 용량 증설을 고려해야 한다. 그리고 업무에 특성에 맞게 미리미리 용량을 준비해놓는게 좋다. 예를 들어 대학의 수강 신청 시스템의 경우, 학기 시작하는 날에 부하가 폭주하기 때문에, 클라우드 기반일 경우 수강신청 전에 시스템 수를 미리 늘려놓는다던지, 클라우드가 아닌 경우, 수강 신청 기간을 앞뒤로 서버를 임대해서 용량을 늘려놓는 등의 대책을 미리 세워놓을 수 있다.
마지막으로, 운영 단계에서 Performance Engineering 관점으로 챙겨야 하는 부분은 운영 로그의 수집이다. 성능 및 용량 목표 설정은 매우 중요한 과정이다. 특히 용량 목표의 경우에는 기존의 업무 시스템의 사용 패턴을 분석 하는 것이 가장 효율적이기 때문에 운영 시스템의 로그를 수집하고 분석하여 운영 중인 업무 시스템의 성능 모델을 분석 및 보유 해놓는 것이 좋다.
| 시스템 용량 산정(Capacity Planning) |
|
더 자세한 설명에 들어가기 앞서서, 성능에 관련된 용어와 함께 시스템의 목표 용량 산정 방법에 대해서 이야기 해보도록 하자. 이 용어는 이 글에서 정의하는 의미의 용어이며, 다른 성능 이론에서 언급되는 용어와 다소 다를 수 있다.
Response Time(응답 시간) |
사용자가 서버에 요청을 한 시간에서 부터, 응답을 받을 때 까지의 모든 시간을 포함한다. 이 응답시간은 내부적으로 다음과 같이 조금 더 세분하게 분리된다.
Network Time (또는 Latency time). 서버에 요청을 했을때, Request를 보내고 받을 때 소요되는 네트워크 시간을 의미한다.
Transaction Time : 서버에서 실제 트렉젝션이 처리되는 시간을 의미 한다.
Think Time : 사용자가 요청에 대해서 응답을 받은 후에, 웹페이지를 보거나 화면을 보는 등의 작업을 하는 시간의 의미한다.
예를 들어 보면 한국의 사용자가 미국이 페이스북을 사용한다고 했을때, 사용자가 웹 브라우져에서 클릭을 하면, 요청이 서버로 도달할때 까지 걸리는 시간 Network time (Request), 서버가 요청을 받아서 처리를 하고, 응답을 하는 시간(Transaction Time), 그리고 그 응답이 사용자의 브라우져 까지 도착하는 시간이Network time (Response) 이다. 이 전체 시간을 합친 것이 Response Time이 된다.
응답을 받은 후에는 사용자가 페이스북 내용을 보는데 소요 되는 시간이 Think Time이 된다.
Think Time 까지 포함하여 다음 요청이 발생하기 까지의 전체 시간을Request Interval 이라고 한다.
Concurrent User (동시 사용자) |
시스템을 현재 사용하고 있는 사용자를 정의한다. 웹사이트를 사용하기 위해서, 현재 브라우져를 열어놓고 웹사이트를 보고 있는 것과 같이 현재 시스템을 사용하고 있는 사용자 수를 의미 한다.
5명의 사용자 A~E가 있다고 가정했을 때, 단위 시간 10분동안에 Transaction Time과 Think Time중에 있는 사용자는 A,B,C 총 3명으로 해다 시간 10분간의 Concurrent User는 3명이 된다.
Active User (액티브 사용자) |
현재 시스템에 트렌젝션을 실행하여 부하를 주고 있는 사용자를 정의한다.
기존에는 Concurrent User와 Active User간의 차이가 없었다. 이 개념은 웹이 생기면서 구체화된 개념인데, 웹 사이트를 사용하기 위해서 컴퓨터 앞에 앉아 있는다고 하더라도, 웹 페이지가 로딩 되는 순간에만 서버는 부하를 받고, 페이지가 웹 브라우져로딩 된 후에는 부하를 받지 않고 사용자는 로딩된 페이지를 보는데 시간이 발생한다. 이 시간동안에는 서버는 부하를 받지 않는다. 즉 시스템을 사용하기 위해서 웹 사이트를 열어 놓고 있는다 하더라도 지속적으로 서버에 부하를 주는 것이 아니기 때문에 Concurrent User와 Active User 의 개념 차이가 발생한다.
Active User는 클릭을 발생시켜서 그 시간 당시에 서버에 트렌젝션을 발생 시키는 사용자를 의미한다. Active User의 수는 서버에서 순간 실행되고 있는 Thread 수 (쓰레딩 기반의 자바 서버의 경우) 나 Process의 수와 같다. 이Active User의 수는 실제로 서버가 동시에 처리할 수 있는 트렌젝션의 양을 판단할 수 있는 기준이 되기 때문에 매우 중요한 성능 Factor가 된다.
위의 그림에서 특정 순간에 있는 사용자는 총 5 명으로 Concurrent User 는 5명이지만, Transaction Time 구간중의 있는 사용자는 A,B,C 로, 총 Active User는 3명이 된다.
Transaction (트렌젝션) |
Transaction이란, 사용자로 부터의 요청을 다루는 단위를 정의 한다.
성능 모델링이나 성능 테스트 시 이 Transaction의 정의에 따라서 시스템의 성능이 매우 다르게 정의 된다. 예를 들어서 사용자가 웹 페이지를 클릭했을때, 그 페이지에 대한 응답을 받는 것 까지를 하나의 트렌젝션이라고 정의 하자. 이 때, 웹페이지에는 서버에서 생생된 HTML 이외에, 여기서 참고 하는 리소스 즉, 이미지나 동영상, 자바 스크립트들이 들어있을 수 있다. 이 경우 트렌젝션에 대한 응답 시간을 측정할때, HTML 생성 이외에 이러한 리소스들을 로딩 하는 것 까지 하나의 트렌젝션으로 정의 해야 하느냐를 고려해야 한다.리소스에 로딩을 트렌젝션의 범위로 넣게 되면 전체 시스템의 응답 시간은 떨어지게 된다.
이러한 트렌젝션의 정의는 무엇을 판단 기준으로 할것인가에 따라 결정이 되는데, 예를 들어 리소스를 톰캣과 같은 WAS에서 처리하지 않고 앞단의 CDN이나 웹서버에서 처리할 경우 톰캣은 리소스에 대한 트렌젝션 요청을 받지 않기 때문에, 전체 시스템에서 비지니스 로직에 대한 처리 성능을 측정하고자 할 때는 리소스에 대한 로딩 시간을 계산하지 않고 트렌젝션을 정의 한다. 또한 리소스에 대한 로딩은 비지니스 로직에 대한 처리에 비해서 부하가 상대적으로 매우 적고, 일반적으로 브라우져에 캐쉬되기 때문에 보통 서버의 성능 측정시 이러한 리소스 로딩에 대한 부하는 트렌젝션의 단위로 처리하지 않는 경우가 많다.
TPS(Transaction Per Second) |
초당 처리할 수 있는 트렌젝션의 양을 정의 한다. 주로 서버의 성능 평가 기준이 된다.
Active 사용자가 순간 Transaction을 처리한다고 하면, 이를 목표 응답시간 (Response Time)으로 나눈 값이 목표 TPS가 된다. 예를 들어, Active User가 50 명이고, 개당 Response Time이 2초 라고 하면, 이 시스템의 TPS는 25 TPS가 된다.
HPS(Hit Per Second) |
시스템이 처리할 수 있는 모든 웹request의 초당 처리량이다. TPS가 비지니스 트렌젝션에 대한 처리 시간만을 정의 한다면, HPS는 리소스 (이미지, 자바스크립트)에 대한request 처리량을 포함하기 때문에, TPS에 비해서10~20 배 정도 높게 나온다.
Peak Time(피크 타임) |
서버가 순간적으로 가장 부하를 많이 받는 순간을 정의 한다. 보통 서버의 용량 산정이나 성능 설계는 이 시간의 부하량을 기준으로 한다. 일반적인 업무 시스템의 경우, 출근 9시~9시30분 사이가 가장 부하가 높다. 이 때 Peak (최고 정점)을 찍는 순간의 동시 사용자 수와 기준 응답 시간을 목표로 성능 목표를 정의 하는 것이 일반적이다.
※ 위의 개념을 정리해서 공식화 해보자 |
① TPS = (Active User) / (Average Response Time) – F1
② TPS = (Concurrent User) / (Request Interval) – F2
③ Active User = TPS * (Average Response Time) – F3
④ Active User = (Concurrent User) * (Average Response Time) / (Request Interval) – F4
⑤ Active User = (Concurrent User) * (Average Response Time) / [ (Average Response Time) + (Average Think Time) ] – F5 |
예를 들어 Concurrent User가 300명이고, 목표 응답시간이 3초 이내이며, Think Time이 15초 인 시스템의 경우, F5 공식에 따라서 Active User는 300*3/(3+15) = 50 이 되며, 시스템의 Thread 또는 적정Process 양은 50개가 된다. 목표 TPS는 약 16.6 TPS가 된다.
위의 공식은 어디까지나 이론적인 공식이다. Network Latency 값은 가변적이며, Think Time 또한 유동적이다.
그러나 용량 산정에는 어느 정도의 산정 기준이 필요하기 때문에, 이 공식을 사용하면 대략적인 시스템에 대한 요구 용량을 예측할 수 있다. |
| Performance Engineering의 절차 |
|
그러면 어떤 절차로 성능과 용량을 측정하고 개선하는 절차에 대해서 알아보도록 하자.
1. | 성능 목표와 모델의 정의 |
먼저 주요 업무 패턴이나, 튜닝의 대상이 되는 시나리오에 대한 개별 성능 목표를 정의 한다. 예를 들어 전체 성능 목표가 1,000 동시 사용자에 대해서 응답 시간 1초내의 시스템이 전체 성능 목표라고 가정하고, 전체 성능 목표를 대략 1,000 TPS (Transaction Per Second)라고 하자. 이것이 바로 성능 목표가 된다.
다음으로 성능 모델을 정의 해야 하는데, 해당 시스템의 주요 사용자 시나리오가 여러개 있을 때, 각 시나리오별의 사용 비중을 정의 해야 한다. 예를 들어 사진을 저장하는 클라우드 서비스 시나리오가 있다고 하면, 이 서비스의 주요 사용자 시나리오는
① 로그인 |
③ 사진 업로드 |
⑤ 사진 다운로드 |
② 사진 리스트 |
④ 사진 보기 |
⑥ 로드 아웃 |
등이 된다. 이 중에서 한 사용자가 실행하는 비율을 따져야 한다. 즉 사용자가 로그인 한후, 리스트 보기를 10번, 업로드를 2번, 보기를 5번, 그리고 다운로드를 1번 한후에 로그 아웃 한다고 하자. 그러면 비율은 다음과 같이 된다. (전체 트렌젝션 횟수 1+10+2+5+1+1 = 20회)
성능 모델 :로그인의 비율 5%, 리스트 보기 50%, 업로드 10%, 보기 25%, 로그아웃5%
이 비율을 기준으로 복합 시나리오 (전체 시나리오를 함께 돌리는) 부하테스트를 수행하였을때, 1000 TPS가 나와야 하고, 각 개별 시나리오에 대해서 최소한, 로그인의 경우 1000 TPS의5%인 50 TPS, 리스트 보기는 500 TPS를 상회 해야 한다.
2. | 부하생성 |
성능 모델이 정의 되었으면, 이 모델에 따라서 부하를 생성해야 한다.
부하 생성 도구는 여러가지가 있다. 간단한 도구로는 Apache AB 라는 명령어 기반의 도구가 있으며, 복잡한 스크립트를 지원할 수 있는 도구로는grinder나 apache JMeter 등이 있으며, NHN에서 grinder를 enhancement해서 만든 (GUI가 지원되는) nGrinder라는 도구가 있다.
성능 모델이 단순하고, 테스트 시나리오가 간단할 경우에는 Apache ab 등으로도 가능하지만, 스크립트가 복잡해지는 경우에는 nGrinder와 같은 도구가 유리 하다. 또한 부하 생성에 사용되는 스크립트는 복잡도가 생각보다 높고, 향후 regression(회귀) 테스트에도 재 사용되기 때문에, 반드시 형상 관리 시스템을 통해서 (VCS) 관리 하는 것을 권장한다.
※ 클라우드 컴퓨팅과 부하 테스트 툴 라이센스 모델에 대해서 |
예전에는 부하 테스트가 사내에서 사내에 있는 시스템을 대상으로 했었기 때문에 큰 문제가 없었다. 그러나 근래 들어서 클라우드 컴퓨팅을 사용하는 사례가 늘어남에 따라, 서비스 시스템이 회사 밖에 즉, 클라우드에 있는 경우가 많아 졌다. 상용 부하 테스트툴의 경우에는 부하 발생기의 위치와 툴 사용자에 대해서 제약을 두는 경우가 있는데, 툴을 구매했다 하더라도, 부하 테스터의 controller (부하 발생기 제외)는 반드시 사내에 있어야 하며, 사용자 역시 그 회사의 내부 직원으로만 한정하는 경우가 있다. 예를 들어, 내가 부하 테스트 도구를 서울에 있는 회사에서 구매하여, 이 툴을 Amazon 클라우드 미국에 설치하고 부하 테스트를 미국 지사 직원을 통해서 진행하는 것이 불가능 하다. 이 경우 부하 테스트 툴의 Controller는 한국 서울 사무소에 설치하고, 부하 생성기만 Amazon에 설치한후 한국 서울 사무소 직원을 통해서만 사용해야 한다. 간혹 (이럴리는 없어야 하겠지만) 부하 테스트 툴의 판매 회사 영업 사원이 이러한 사실을 제대로 통보하지 않아서, 툴을 잘 쓰다가 갑자기 영업 사원이 변경되거나, 부하 테스트 툴의 이전을 요청 하였을때, 갑자기 벤더로 부터, 추가 라이센스 구매 요청을 받을 수 있으니, 구매 전에 반드시 구매 조건에 사용 시나리오와 Controller 위치, 사용 주체 및 테스트 대상 시스테들에 대해서 명시적으로 기재 하고 구매 계약을 추진 하는 것이 좋다. |
3. | 테스트및 모니터링 |
Application |
Middleware |
Infrastructure |
애플리케이션 관점
가장 기본적으로 애플리케이션 즉 시스템의 성능을 측정 해야 한다. 주요 모니터링 Factor는 다음과 같다.
Response Time : Request 별 응답 시간
미들웨어 관점
미들웨어는 애플리케이션이 동작하기 위한 기본적인 솔루션이다. Apache와 같은 웹서버나 Tomcat과 같은 Web Application 서버, RabbitMQ와 같은 Message Queue, MySQL과 같은 데이타 베이스 등이 이에 해당한다.
각 성능 시나리오별로, 거쳐 가는 모든 미들웨어들을 모니터링해야 하는데, 이를 위해서는 각 솔루션에 대한 개별적인 깊은 이해가 필요하다. 웹서버의 경우 거의 성능 문제가 되는 부분은 없다. 성능 문제가 발생하는 부분은 대부분 Network outbound io (bandwidth)쪽이 되는 경우가 많다. 웹서버가 설치된 하드웨어의 network out bound bandwidth를 모니터링 하는 것이 유용하다.
대부분의 성능 문제는 실제 애플리케이션 로직이 수행되는 Tomcat과 같은application server와 데이타 베이스단에서 많이 발생하는데, application server의 경우에는 Thread의 수와 Queue의 길이가 1차 모니터링 대상이 된다. 서버가 용량을 초과 하게 되면, Idle Thread수가 떨어지게 되고, Idle Thread가 0이 되면 request message가 앞단의 queue에 저장되게 된다. 그래서 이 두 개를 모니터링 하면 시스템이 병목 상태인지 아닌지를 판단할 수 있다. 이 값들은 JMX (Java Management Extension) API를 이용하여 모니터링 하면 된다. DB의 경우에는 slow query를 모니터링하면 특히 느리게 수행되는 쿼리들을 잡아서 튜닝할 수 있다.
인프라 관점 : CPU, Memory, Network IO, Disk IO
4. | 개선(Tuning) |
- 문제의 정의
Break down
다음으로는 문제가 발생하는 부분이 어떤 부분인지를 판단해야 한다. 시스템은 앞단의 로드밸런서나 미들웨어, 데이타 베이스와 같은 여러 구간에서 발생을 한다. 그렇기 때문에, 성능 저하의 원인이 정확하게 어느 부분인지를 인지하려면, 먼저 성능 시나리오가 어떤 어떤 컴포넌트를 거치는지를 명확하게 할 필요가 있다. 이 과정을 break down이라고 한다. 이 과정을 통해서 전체 성능 구간중, 어느 구간이 문제를 발생 하는지를 정의한다.
Isolate
다음으로는 다른 요인들을 막기 위해서, 문제가 되는 구간을 다른 요인으로 부터 분리 (고립) 시킨다. 물론 완벽한 분리는 어렵다. 애플리케이션이 동작하기 위해서는 데이타 베이스가 필수적으로 필요하다. 이 경우에는 데이타 베이스를 분리할 수 는 없다. 그러나 예를 들어 시나리오 자체가 로그인 시나리오이고 Single Sign On을 통해서 로그인 하는 시나리오라서 SSO 시스템과 연동이 되어 있다면, SSO 연동을 빼고 다른 mock up을 넣어서 SSO와의 연결성을 끊고 테스트를 하는 것이 좋다. 이렇게 문제에 대한 다른 요인과의 연관성을 최대한 제거 하는 작업이 isolation이다.
Narrow down
문제를 isolation을 시켰으면, 근본적인 문제를 찾기 위해서 문제의 원인을 파 내려간다. Profiling을 하거나, 코드에 디버그 정보를 걸어서 문제의 원인을 분석하는 과정을 narrow down이라고 한다. 특히나 이 narrow down 과정은 분석을 위한 여러가지 기법이나 도구들을 사용해야 하고, 현상에 대한 이해를 하기 위해서는 해당 솔루션이나 기술 분야에 대한 전문성은 필수적으로 필요하다.
Bottleneck 발견
Narrow down을 해서 문제의 원인을 계속 파해쳐 나가면 병목의 원인이 되는 근본적인 문제가 판별이 된다.
해결
일단 병목의 원인을 찾으면 해결을 해야 하는데, 찾았다고 모두 해결이 되는건 아니다. 데이타 베이스 index를 걸지 않아서 index를 걸어주면 되는 간단한 문제도 있을 수 있지만, 근본적인 솔루션 특성이나 설계상의 오류로 인해서 문제가 발생하는 경우도 있다. 하드웨어를 늘려서 해결하는 방법도 있지만, 비지니스 시나리오 자체를 바꾸거나 UX 관점에서 해결 하는 방법도 고려할 수 있다. 예를 들어 로그인 화면이 넘어가는데 시간이 많이 걸린다고 했을때, 이 문제가 근본적으로 솔루션의 특성이라면 애플리케이션이나 솔루션 수정으로는 해결이 불가능하다. 이런 경우에는 모래 시계 아이콘이나 progress bar등을 넣어서 UX 관점에서 사용자로 하여금 체감되는 응답 시간에 대해서 느리지 않고 몬가 진행이 되고 있다고 보여주는 형태로 접근을 해서 문제를 해결할 수 도 있다.
5. | 반복 |
튜닝이 끝났으면 다시 “테스트 및 모니터링” 항목으로 돌아가서 성능 목표에 도달할때까지 위의 작업을 계속해서 반복해서 수행한다.
| Performance Engineering을 위해 필요한 것들 |
|
부하 테스트기
가장 기초적으로 필요한 것은 부하 발생 도구 이다. HP Load Runner와 같은 상용 도구에서 부터, nGrinder와 같은 오픈 소스 기반의 대규모 부하 발생 도구를 사용할 수 도 있고, SOAP UI같은 micro benchmark 테스트 툴을 이용해서 소규모 (50 사용자 정도)를 발생 시키거나 필요에 따라서는 간단하게 Python등의 스크립트 언어로 부하를 발생시킬 수 도 있다.
모니터링 도구
다음으로는 모니터링 도구이다. 어느 구간이 문제가 있는지 현상이 어떤지를 파악하려면 여러 형태의 모니터링 도구들이 필요하다.
프로파일링 도구
그리고, 문제되는 부분을 발견했을때, 그 문제에 대한 근본적인 원인을 찾기 위해서 프로파일링을 할 수 있는 도구들이 필요하다.
우리가 일반적으로 이야기 하는 프로파일링 도구들은 IDE와 같은 개발툴에서debug 용도로 사용은 가능하지만, 대부분 대규모 부하 환경에서는 사용이 불가능한 경우가 많다.그래서 그런 경우에는 해당 시스템의 상태에 대한 스냅샷을 추출 할 수 있는 dump 도구들을 많이 사용하는데, unix process의 경우에는 ptrace를 통해서 system call을 모니터링 하거나, pmap을 이용하여 메모리 snapshot등을 추출할 수 도 있고, 자바의 경우에는 thread dump를 추출해서 병목 당시 애플리케이션이 무슨 동작을 하고 있었는지를 찾아낼 수 있다.
역량
당연한 것이겠지만, 기술적인 역량은 필수적이다. netstat를 통해서 TCP 소켓이 FIN_WAIT가 발생하였는데, 이 FIN_WAIT가 의미하는 것이 무엇인지 모르면 아무리 모니터링을 잘해도 소용이 없다. 기본적인 엔지니어로써의 컴퓨터와 프로그래밍, OS등에 대한 넓은 이해는 필수적이다.
하드웨어 인프라, 미들웨어 , 애플리케이션에 대한 지식
다음은 사용하는 특정 솔루션에 대한 전문적인 지식이다. 톰캣의 내부 구조가 어떻게 되어 있으며, JVM의 동작원리가 어떻게 되는지와 같은 특정 지식인데, 사실 이러한 지식은 오랜 경험이나 습득할 시간이 없으면 가지기가 어렵다. 이런 경우는 해당 솔루션 제품 엔지니어를 통해서 지원을 받는 방법도 고려해볼만 하다.
그리고 경험
성능 엔지니어링에 대한 경험인데, 대략 시스템의 상태마 봐도 어느 부분이 의심이 되는지 경험이 많은 엔지니어는 쉽게 접근을 한다. 성능 문제는 넓어보이기는 하지만, 결국 발생되는 패턴이 거의 일정하다. 그리고 특정 솔루션에 대한 지식이 없다하더라도, 문제에 대한 접근 하는 방법이나 모니터링 방법, 툴등은 사용법이 다르다 하더라도 그 의미하는 방법은 거의 비슷하기 때문에, 다른 기술로 구현되어 있는 시스템이라고 하더라도, 경험이 있는 엔지니어는 문제를 접근해서 풀어나가는 방식이 매우 익숙하다.
마지막으로 인내심
그리고 마지막으로 강조하고 싶은 점이 인내심인데, 사실 성능 엔지니어링은 상당히 지루한 작업이다. 반복적인 테스트와 모니터링 및 분석을 거쳐야 하고, 해당 솔루션에 대한 전문적인 지식이 없을 경우에는 보통 제품 문제라고 치부하고 하드웨어 업그레이드로 가는 경우가 많은데, 어짜피 솔루션이라고 해도 소스코드로 만들어진 프로그램이다. 디컴파일을 하건, 덤프를 추출하건, 꾸준히 보고, 오픈 소스의 경우 소스코드를 참고해서 로직을 따라가다 보변, 풀어낼 수 있는 문제가 대부분이다. 결국은 시간과 인내심의 싸움인데, 꾸준하게 인내심을 가지고 문제를 접근하고 풀어나가는 것을 반복하면 문제는 풀린다.
'dev' 카테고리의 다른 글
vi/vim 단축키 정리 (0) | 2017.11.24 |
---|---|
jMeter를 이용한 웹 프로그램 부하 데스트 (0) | 2017.11.09 |
톰캣 윈도우 서비스 등록 / 설정 변경 (0) | 2017.11.02 |
sonatype 넥서스 설치 방법 (0) | 2017.11.02 |
Intellij - Can't update maven repository 에러 해결 방법 (0) | 2017.11.01 |