티스토리 뷰

728x90
반응형

개요

본 포스팅은 WAS Thread수와 Instance수를 산정하는 방법에 대한 가이드이다. WAS에서 Thread는 성능을 측정하는데 있어서 매우 중요한 부분이다. Thread의 수에 따라 어플리케이션이 할당되고, 호출 되고 실제로 Working 하는 요소가 바로 Thread이기 때문이다. 다만, 무작정 Thread를 늘려 놓게 되면, WAS Process에 악영향을 키칠수도 있고, 또는 불필요한 Resource 낭비를 초래 할 수도 있다. 이에 적당한 수의 Thread를 산정하는 것은 매우 중요하다고 볼수 있다.
Thread 수를 산정하기에 앞서 먼저 성능 산정에 대한 몇가지 기본 Parameter에 대해서 알아보도록 하자. 먼저 Response Time과 Think Time이다.
일반적인 웹시스템에 대해서 생각해 보면 다음과 같다.

  • 사용자는 Form에 아이디와 비밀번호를 넣고, 로그인을 클릭한다.
  • 아이디와 비밀번호는 네트워크를 통해서 서버에 전송된다.
  • 서버에서는 이 아이디와 패스워드를 이용해서 사용자 정보를 조회한후 각 사용자에게 알맞는 페이지를 다시 네트워크를 통해서 사용자에게 전송한다.
  • 사용자는 전송되어 있는 페이지를 읽어보고, 공지사항을 클릭한다.

여기서 몇가지 용어를 정의해 보도록하자.

  • Response Time이란 사용자가 request한 시점 (즉 Click한 시점)에서 시스템이 Response를 할 때까지의 시간을 의미한다. 이 시간에는 사용자의 요청이 서버 시스템으로 전송되는 네트워크 시간(Request Network Time)과, 서버에서 생성된 응답 내용이 네트워크를 통해서 사용자에게 전송되는 시간(Response Network Time)을 포함한다. Reponse Time중에서 실제로 서버가 부하를 받는 시간은 Transaction Time이라고 정의한다.
  • Think Time이란 사용자에게 전달된 정보는 사용자가 그 내용을 인지하고 다음 동작을 취할때까지의 생각하는 시간이 필요하다. 이를 Think Time이라고 정의한다.
  • Request Interval이란 Response Time과 Think Time 둘을 합친것을 의마한다. 이 시간은 사용자가 클릭을 해서 시스템으로부터 정보를 받아서 인지할때 까지의 시간을 나타낸다.
  • Visit Time이란 하나의 사용자에 대해서 Request Interval의 집합을 Visit Time이라고 정의한다. 이 값은 사용자가 시스템에 접속해서 사용한 시간을 정의한다.

※ 상기의 값들은 access.log 파일을 웹마이닝툴을 이용해서 분석하면 그 값을 추출해낼 수 있다.


Concurrent Uset (동시 사용자수)

다음으로 Concurrent User (동시 사용자수)에 대해 알아보자.
동시 사용자의 개념은 매우 모호하다 할 수 있다. 웹 시스템의 경우에는 Session 유지 시간이 일반적으로 30분이기 때문에, 10분전에 사용을 끝낸 사용자도 세션은 유지될 경우, 시스템에 영향을 둔다. 반대로 시스템을 사용중인 사용자라도 response를 받은 후에 정보를 읽고 있는 Think time 중에 있다면 시스템에 영향을 주지 않는다. 이에 MainFrame이나 C/S 시스템과 다르게 웹시스템에서의 동시 사용자의 개념은 매우 모호하다 할 수 있다.
그렇다면 우리는 동시 사용자의 개념을 어떻게 정의할것인가에 대해 고민해 봐야한다. 즉 동시 사용자를 지금 시스템을 사용하기 위해서, 단말기 앞에 앉아있는 사람 즉 동시 단말 사용자 라고 정의해보도록 하자.
이 숫자는 단위시간 동안에, 현재 사이트를 방문하고 있는 사용자수로 판단할 수 있다. 그렇다면, 이 단위 시간을 정의하는것이 중요한데, 보통 10분단위정도의 단위로 측정을 하며, 측정 시간대에 즉 PEAK TIME에 측정했느냐 아니면 작업이 없는 오후 시간대에 측정했느냐에 따라 시스템의 동시 사용자수가 차이가 날 수 있다.

시스템의 동시 사용자를 측정하기 위해서는 access.log를 이용해서 각 시간대별로 동시 사용자를 파악하는게 중요하고, 특히 최대 동시 사용자수를 구하는 것이 시스템 용량 산정에 있어서 가장 중요한 요인이 된다.


Active User

다음으로 Active User에 대해 알아보자.
앞에서 산출한 동시 사용자 모두가 시스템에 영향을 주는것이 아니다. 어떤 사용자는 시스템에서 나온 정보를 읽고 인지하는 과정 (Think Time)에 있는 사용자도 있을 수 있을 것이다. 이런 사용자를 제외하고, 실제로 현재 시간에 시스템을 사용하고, 시스템에서 트랜젝션을 수행하고 있는 사용자를 Active User라고 정의한다.
Active User는 실제 시스템에서 Transaction을 수행하고 있는 User수이고, 실제로 서버에서 Thread가 돌고 있는것으로 판단할 수 있기 때문에, 이 Active User의 수가, 즉 서버의 Working Thread수가 된다.


TPS

다음으로 TPS (Throughput Per Second)에 대해 알아보자.
해당 요소는 성능을 측정하는 주요 지표라고 할수 있다. TPS는 초당 시스템의 처리량 (Throughput)을 나타낸다. TPS는 시스템의 처리량을 측정 시간으로 나누면 되는데, access.log에서의 경우에는 response의 수는 정확하게 기록하기가 어렵기때문에, 해당 서비스에 대한 request수를 시간으로 나눈것을 TPS로 계산한다.
WAS의 경우에는 이 Throughput 값을 기준으로 모니터링이 가능하며, 여러 방법을 이용해서 TPS를 측정할 수 있다.


Thead 산정 기준

자 그럼 WAS의 Working Thread수를 직접 산정해 보자. 앞에서 성능에 관련된 여러 변수에 대해서 정의해 보았다. 그럼 이제 변수들을 이용해서 WAS의 Working Thread수를 구해보도록 하자.

대체로 사용자 워크로드를 분석하기 위해서는 먼저 AccessLog를 기반으로 분석하는 경우가 많다.

AccessLog의 시간대 별 데이터를 카운트 하여 최빈시간의 요청량을 기준으로 TPS를 산정하고, 각 워크로드 별 호출빈도에 따라 부하모델을 수립할 수 있다.

<시간대별 카운트 세기>

통합 문서1.xlsx
0.01MB

  • =COUNTIF($B$2:$B$15,"<="&(F2+(1/24)))-COUNTIF($B$2:$B$15,"<"&F2)-COUNTIF($B$2:$B$15,F3)
  • =COUNTIFS($B$2:$B$15,">="&F2,$B$2:$B$15,"<"&F3)

위와 같이 엑셀 COUNTIF를 사용하여 시간대별 카운트를 산정할 수 있다.

<최빈시간 데이터 건수 세기>

  • 시간순 정렬 > 컬럼 추가 생성 > 최빈시간 내 UNIQUE > COUNTIF(RANGE,조건) > 전체건수 대비 비율 산정

특히 TPS는 최빈 시간 1시간 이내의 전체 데이터를 기준으로 산정하는 것을 기본으로 한다. 이는 부하모델의 TPH와 동일해야 한다.

Working Thread = Active User 즉 우리는 Active User의 수를 구하면 되는데 TPS산정 공식에서 TPS는 시스템의 처리량을 측정 시간으로 나누었기 때문에, TPS = Concurrent User / Request Interval과 같다.

  • 공식 1 : Active User = TPS * (Average Response Time)

이값을 공식 1에 대입하면 공식 2가 된다.

  • 공식 2 : Active User = (Concurrent User ) / (Request Interval) * (Average Response Time)

Request Interval = Response Time + Think Time이기 때문에, 이를 공식 1, 2에 각각 대입하면 공식 3-1, 3-2가 된다.

  • 공식 3-1 : Active User = (Concurrent User) / (Average Response Time + Average Think Time) * (Average Response Time)
  • 공식 3-2 : TPS = Concurrent User / Request Interval(Average Response Time + Average Think Time)
  • 공식 3-3 : Average Response Time = Concurrent User / TPS - Average Think Time

공식 3을 이용하면, 개발하고자 하는 목표 시스템의 목표 동시 사용자수(Concurrent User), 목표 응답 시간(Average Response Time)과 목표되는 평균 Think Time(Average Think Time)을 산정하면 시스템이 실제로 사용해야하는 Thread수를 산정할 수 있다.
예를 들어, 동시에 300명이 사용하고, 응답시간은 3초이내이며 Think Time이 15초인 인터넷 시스템이 있다면, 이 시스템의 Activer User = 300*3/(3+15) = 50 명으로 해당 시스템의 총 Thread수는 50개가 적정이 된다.
또한, Think Time과는 구별되는 Pacing Time을 산정하기 위한 기준으로 Pacing Time = Average Response Time / 0.9를 공식 1에 대입하면, 위와 같이 공식 4를 도출할 수 있다.

  • 공식 4 : Pacing Time(Average Response Time) = Concurrent User / TPS * 0.9

Thread 산정시 고려사항

WAS의 Thread 수 검증과 테스트를 수행해 보자.
앞에서 제시한 공식 3은 보기에는 완벽해 보이는 공식이지만, 실세계에서 개발 운용되는 애플리케이션은 불행이도 우리의 예상을 벗어나는 경우가 많다.
평균 응답시간과 평균 Think Time은 어디까지나 평균 값일 뿐이며 애플리케이션의 구조에 따라서 PEAK TIME에서의 그 값이 현저하게 차이가 날 수 있고, 그 결과로 해당 THREAD가 모자르는 현상을 초래할 수도 있다. 즉 공식 3에서 얻어진 값은 Working THREAD는 최소 값 내지는 Tuning에 있어서 기본값으로 판단하는 것이 현명하다.
이 값을 기본으로 Working Thread의 최적의 숫자를 산정해야하는데 이는 스트레스트 테스트와 운영중의 로그를 기반으로 결정하게 된다.
그렇다면 WAS의 적정 쓰레드 수는 어떻게 산정 될까?
WAS의 구성을 설계하다보면 가장 문제가 되는 부분중에 하나가 몇개의 JVM 인스턴스를 띄울것인가부터 고민하게 된다.
하나의 BOX에 하나의 JVM 인스턴스를 띄우는것과 여러개의 인스턴스를 띄우는것에는 일반적인 경우에는 성능상에 큰 차이는 나지 않는다. (하나의 인스턴스가 더 성능은 좋다.)
OS에서 각 Process에 CPU 자원을 Scheduling정책에 따라서 지정하기 때문이다. 그러나, 몇가지 요인으로 인해 WAS을 여러개의 인스턴스로 나누어서 기동하도록 권고하고 있다. WAS Node(BOX) 당 인스턴스의 수를 결정하는 주요 FACTOR는 다음과 같다.

  • 메모리 크기에 따라 결정합니다.
  • 전체 쓰레드수에 따라 결정합니다.
  • GC PAUSE시간과 횟수에 따라 결정합니다.
  • FAIL OVER에 따라 결정합니다.
  • CPU수에 따라 결정합니다.

먼저 메모리 크기에 따른 결정방법이다. JVM 인스턴스당 HEAP SIZE는 1GB이내가 적당하다. JVM에 따라서 대용량 메모리를 사용할경우에는 별도의 설정이 필요한 경우가 있고, 1GB가 넘는 대용량 메모리의 경우에는 FULL GC 시간이 많이 걸려서 시스템의 PAUSE TIME이 길게 나와서, 시스템을 정지시킨것처럼 보일 수 있기 때문에 1GB단위로 JVM 인스턴스를 나누는것이 좋다.
다음으로 전체 쓰레드수에 따른 결정방법이다. WAS에서는 쓰레드를 Pooling을 이용해서 사용하고 있기 때문에, 쓰레드 수를 늘린다는것은 쓰레드를 위해서 메모리등의 자원이 그만큼 많이 할당된다는것을 의미이다. 또한 JVM에서 OS의 쓰레드와 JAVA의 쓰레드를 맵핑하는 방법에 따라서 문맥교환이 발생하며 성능에 차이가 나게 된다.
일반적으로 한 인스턴스당 최대의 성능을 낼 수 있는 쓰레드수는 50~100개 사이라고 했을때 목표로 하는 Active user 수 (목표 Thread수)가 100개 이상인경우, 하나의 JVM 인스턴스를 100개의 쓰레드 단위로 나누어서 기동하는것이 좋다.
예를 들어, 목표 Active User가 300인경우에는 300개의 쓰레드를 가지고 있는 하나의 JVM 인스턴스가 아니라 100개의 쓰레드를 가지고 있는 3개의 JVM 인스턴스 또는60개의 쓰레드를 가지고 있는 5개의 JVM 인스턴스를 기동하는것이 적절하다.
100개짜리 3개나, 60깨짜리 5개냐는 각 인스턴스의 성능을 테스트를 통해서 측정한 내용과, 관리상의 편의성, 메모리양, GC상황등을 고려해서 기동해야 한다.
다음으로 GC PAUSE 시간과 횟수에 대한 결정방법입니다. JVM의 Full GC의 경우 Java Application을 순간적으로 멈추게 하기 때문에 Full GC에 소요되는 시간과 횟수는 WAS운용에 있어서 큰 변수로 작용한다. Full GC는 웹시스템을 기준으로 하루 5회 미만, 1회당 3~4초 정도가 적정한 수치이다.
인스턴스 수를 늘리면 각각의 인스턴스에서 일어나는 Full GC의 횟수는 당연히 줄어들게 된다. Full GC 내용 역시 인스턴스 수를 결정하는 요인이 된다.
다음으로 Fail Over에 따른 결정방법이다. JVM 인스턴스를 나누는 주요한 요인중의 하나가 JVM 인스턴스에 대한 장애시에 Fail Over이다. 전체 시스템을 하나의 인스턴스로 구성하는것보다 최소 2개 이상의 instance로 구성해서 장애에 대비할 필요가 있다.
마지막으로 CPU수에 따른 결정방법이다. 보통 하나의 JVM 인스턴스를 기동하는데는 1~2개 정도의 CPU를 사용하는게 최적화된 환경이다. 즉 8CPU 머신의 경우 4~8개의 JVM 인스턴스가 적정하다. CPU수보다 많은 JVM 인스턴스를 기동할경우에는 각각의 JVM 인스턴스에 CPU가 배정 되는 시간이 느려지기 때문에 성능 저하로 이어질 가능성이 높다.


결론

정리를 해보자면 WAS에서 생성 한 각각의 JVM 인스턴스를 나누는 기준은 다음과 같다. 하나의 도메인에 대해서 2개 이상의 인스턴스를 사용해서 장애에 대처해야 하며, 하나의 인스턴스는 1GB이하의 Heap을 가지며, 50~100개 사이의 Thread를 가진다. Full GC 는 하루에 5회 미만으로 일어나며, Full GC 시간은 3~4초 이내가 적당하다.
성능을 튜닝해야 하는 많은 요소들 중 WAS에 대한 튜닝은 직접적으로 어플리케이션의 성능과 연관되어 있다고 볼 수 있다. 주요한 성능 지표를 기준으로 적정치의 Thread를 산정하여 최적의 어플리케이션이 서비스되는 환경을 만들어 보도록 하자.

728x90
반응형