제이미터(JMeter)로 테스트 환경 구성 및 테스트하기_2

2024. 3. 25. 10:37개발

반응형

2024.03.22 - [개발] - 제이미터(JMeter)로 테스트 환경 구성 및 테스트하기_1

 

제이미터(JMeter)로 테스트 환경 구성 및 테스트하기_1

JMeter 세팅과 관련해서는 해당글을 참고하면 됩니다. 2024.03.22 - [개발] - 제이미터(JMeter)로 테스트 세팅 및 사용법 정리. 제이미터(JMeter)로 테스트 세팅 및 사용법 정리. 테스트를 해본다면? JMeter로

lollaziest.tistory.com

 

이전글에서 이어집니다..

실질적인 테스트 조건들을 정리한 뒤 2차 테스트를 수행했고 그 내용에 대해서 정리하기 시작했다.

톰캣설정으로 인한 성능차이가 발생 할 수 있는지를 확인 하기위해 아래 조건들을 대상으로 잡았다.

 

  1. 메모리가 높으면 더 빠른 속도가 나오는지 테스트 (1G) (2G)
    1. 기본조건
      1. 스레드100개
      2. 커넥션 15
      3. keepAliveTimeout 3
      4. maxKeepAliveRequests 50
      5. MetaspaceSize 256M
    2. 변경조건
      1. 메모리 1G ,메모리 2G 각 3회 테스트
  2. 위에서 나온 결과를 확인하고 MetaspaceSize 여부가 속도에 영향을 주는부분이 있을지 테스트.
    1. 기본조건
      1. 메모리 1G
      2. 스레드100개
      3. 커넥션 15
      4. keepAliveTimeout 3
      5. maxKeepAliveRequests 50
    2. 변경조건
      1. MetaspaceSize지정 3회, MetaspaceSize 미지정 3회
  3. 위에서 나온 결과를 확인하고 keepAliveTimeout과 maxKeepAliveRequests 여부가 속도에 미치는 영향이 있는지 테스트한다.
    1. 기본조건
      1. 스레드100개
      2. 메모리 1G
      3. 커넥션 15
      4. MetaspaceSize 미지정
    2. 변경조건
      1. keepAliveTimeout
      2. maxKeepAliveRequests
  4. 위에서 나온 결과를 확인하고 스레드 갯수에 따른 속도 차이를 확인한다. (최소 각 3회)
    1. 기본조건
      1. 스레드100개
      2. 메모리 1G
      3. 커넥션 15
      4. MetaspaceSize 미지정
      5. keepAliveTimeout 제거
      6. maxKeepAliveRequests 제거
    2. 변경조건
      1. 스레드 30개
      2. 스레드 50개
      3. 스레드 100개
      4. 스레드 200개(default)
  5. 위에서 나온 결과를 확인하고 db커넥션에 따른 속도차이를 확인한다.(최소 각 3회)
    1. 기본조건
      1. 스레드 100개
      2. 메모리 1G
      3. MetaspaceSize 미지정
      4. keepAliveTimeout 제거
      5. maxKeepAliveRequests 제거
    2. 변경조건
      1. 커넥션 15개
      2. 커넥션 20개
      3. 커넥션 30개

간략하게 정리하면 다음과 같다.

1번

톰캣 메모리 설정에 따른 성능차이.

2번

MetaspaceSize 값을 지정해주는것에 따른 성능차이가 혹시 있는지..

(MetaspaceSize의 경우에는 JDK 8 기준이라 자동으로 늘어나는 형태라 성능상에 문제는 없다고 한다. 자세한건 다른 블로그들에서 잘 설명되어있으니…참고를 하시면 될 것 같다.)

3번

keepAliveTimeout 와 maxKeepAliveRequests 설정 여부에 따른 성능차이.

(해당 옵션값을 지정하여 사용중이였기 때문에 이 부분에서 문제가 있는지 확인이 필요했다.)

4번

max 스레드 갯수를 지정해줌에 따른 속도차이 확인.

5번

DB 커넥션 갯수를 조절함에 따른 속도 차이.

 

2차 테스트

1번 테스트

  1. 메모리

 

수행조건  수행날짜  평균(ms)  90%(ms)  95%(ms)  99%(ms)  에러(%)  처리속도(/sec)
1G 2024-03-05 2241 4623 5736 8960 0.00 36.1
1G 2024-03-05 1845 3788 4926 7752 0.00 36.5
1G 2024-03-05 1904 3938 5103 8194 0.00 36.6
2G 2024-03-05 1663 3420 4522 7461 0.00 36.8
2G 2024-03-05 2247 4646 6021 8839 0.04 36.1
2G 2024-03-05 2146 4533 5508 8772 0.04 36.1

결론

메모리를 다 차지하는것도 아니였고 메모리를 늘려준다고 더 빨라지는건 아닌것 같다. (실질적으로 Visualvm을 사용하여 확인하거나 했을때도 메모리 영역을 더 사용하거나 하는것도 아닌듯 보였다.)

2번 테스트

  1. MetaspaceSize
수행조건  수행날짜 평균(ms)   90%(ms)  95%(ms)  99%(ms)  에러(%)  처리속도(/sec)
MetaspaceSize지정 2024-03-05 2241 4623 5736 8960 0.00 36.1
MetaspaceSize지정 2024-03-05 1845 3788 4926 7752 0.00 36.5
MetaspaceSize지정 2024-03-05 1904 3938 5103 8194 0.00 36.6
MetaspaceSize미지정 2024-03-05 1895 3854 5094 8418 0.00 36.5
MetaspaceSize미지정 2024-03-05 2125 4505 5613 8106 0.00 36.3
MetaspaceSize미지정 2024-03-05 1971 4222 5285 8149 0.00 36.2

결론

MetaspaceSize가 속도에 영향은 주지 않지만 특정 영역만큼만 지정해주는게 좋다고 한다.
(만약 잘못짜여진 프로그램이라고 가정하면 지정하지 않는경우 동적으로 얼마든지 늘어나기 때문에 운영체제의 메모리를 모두 차지하는걸 방지하는데 사용된다고 한다.)

3번 테스트

  1. keepAliveTimeout
  2. maxKeepAliveRequests

 

수행조건  수행날짜 평균(ms)   90%(ms)  95%(ms)  99%(ms)  에러(%)  처리속도(/sec)
maxKeepAliveRequests
keepAliveTimeout
2024-03-05 1895 3854 5094 8418 0.00 36.5
maxKeepAliveRequests
keepAliveTimeout
2024-03-05 2125 4505 5613 8106 0.00 36.3
maxKeepAliveRequests
keepAliveTimeout
2024-03-05 1971 4222 5285 8149 0.00 36.2
없음 2024-03-05 2194 4475 5925 9034 0.00 36.2
없음 2024-03-05 2107 4347 5483 8648 0.00 36.2
없음 2024-03-05 1951 4164 5272 7592 0.00 36.3

결론

속도차이는 없어보인다.

4번 테스트

수행조건  수행날짜  평균(ms)  90%(ms)  95%(ms)  99%(ms)  에러(%)  처리속도(/sec)
30개 2024-03-05 2212 3659 3900 4423 0.00 28.8
30개 2024-03-05 2324 4004 4281 4809 0.00 35.9
30개 2024-03-05 1770 2879 3108 3634 0.00 36.7
50개 2024-03-05 2515 4408 4966 6246 0.00 35.8
50개 2024-03-05 1860 3505 4047 4893 0.00 36.3
50개 2024-03-05 2092 3748 4374 5650 0.00 36.2
100개 2024-03-05 2194 4475 5925 9034 0.00 36.2
100개 2024-03-05 2107 4347 5483 8648 0.00 36.2
100개 2024-03-05 1951 4164 5272 7592 0.00 36.3
200개(default) 2024-03-05 1739 3696 4802 7489 0.00 36.6
200개(default) 2024-03-05 1765 3689 4848 7698 0.00 36.5
200개(default) 2024-03-05 2280 4983 6680 10585 0.00 36.0

결론

속도상으로는 30개가 더 준수하고 스레드 사용율 또한 좋다. 그러나 해당 스레드 들이 모두 일하는 중이라면 뒤에 대기중인 요청이 일정 수 이상 넘어 갈 수 있고, 그에 따른 요청 거부가 발생할수 있음.

코어수 늘리고 스레드 기준 50 or 100정도로 올린다면 준수한 속도를 보여줄것 같음. (보통은 서버 코어의 배수로 올리는게 좋다고함 4코어면 4의 배수)

참고 문헌

어느 순간에 사용가능한 Thread의 수보다 connection가 더 많으면 어떤 일이 발생하나요? Thread에 의해 실행되지 않는 connection은 어떻게 되나요?

Thread에 의해 실행되지 않는 connection은 worker thread가 사용가능해질 때까지 기다립니다.

Tomcat은 연결을 받아들인 후 "accept queue"를 통해 worker thread로 보냅니다. 이것을 조절하는 Tomcat config 파라미터는 다음과 같습니다.

acceptCount: 모든 요청을 처리하는 Thread가 사용중일 때, 들어오는 connection request를 저장한 queue의 최대 크기. 이 queue가 꽉 찼을 때 발생하는 모든 request는 거절됩니다. 기본 값은 100입니다.

(출처 https://tomcat.apache.org/tomcat-8.0-doc/config/http.html)

 

Apache Tomcat 8 Configuration Reference (8.0.53) - The HTTP Connector

This Connector supports all of the required features of the HTTP/1.1 protocol, as described in RFC 2616, including persistent connections, pipelining, expectations and chunked encoding. If the client (typically a browser) supports only HTTP/1.0, the Connec

tomcat.apache.org

5번 테스트

스레드 100개

메모리 1G

기타설정 모두 제외처리.

수행조건 수행날짜   평균(ms)  90%(ms)  95%(ms)  99%(ms)  에러(%) 처리속도(/sec)
커넥션15 2024-03-05 2194 4475 5925 9034 0.00 36.2
커넥션15 2024-03-05 2107 4347 5483 8648 0.00 36.2
커넥션15 2024-03-05 1951 4164 5272 7592 0.00 36.3
커넥션20 2024-03-05 3632 6979 8036 11044 0.00 34.5
커넥션20 2024-03-05 4137 7715 9009 12191 0.00 34.1
커넥션20 2024-03-05 3637 7093 8294 11434 0.00 34.4
커넥션30 2024-03-05 5260 9419 10573 12599 0.00 33.1
커넥션30 2024-03-05 5026 9256 10189 12324 0.00 33.4
커넥션30 2024-03-05 4454 8161 9157 12377 0.00 33.8

 

 

생각의 방향 전환 시작.

WAS문제로 접근하고 설정들을 바꿔봐도 변화가 없어서 다른 방향으로 접근해보기 시작했다.

그럼 API 요청이 들어올때마다 요청정보와 기타 응답에 대한 값을 보기위해 남기는 로그 때문에 속도가 느려진건가 싶었다...? (요청건수가 많다면 그 수만큼 로그가 쌓일것이기 때문에…)

API 서비스 LOG 여부에 따른 속도차이 계산해보기로 했다. 로그 insert하는 부분만제거 한 다음 확인했다.

속도자체는 조금 줄어들었다. 그러나 명확하게 그 부분 때문에 느려진다거나 획기적으로 차이가 나진 않는다고 판단되었다.

수행조건  수행날짜  평균(ms)  90%(ms)  95%(ms)  99%(ms)  에러(%)  처리속도(/sec)
로그 O 2024-03-12 1845 3899 4906 7832 0.00 36.6
로그 O 2024-03-12 1685 3527 4648 7673 0.00 36.7
로그 O 2024-03-12 1693 3601 4709 7247 0.00 36.7
로그 X 2024-03-12 1572 3166 3951 6153 0.00 37.0
로그 X 2024-03-12 1431 3118 4013 6210 0.00 37.0
로그 X 2024-03-12 1415 2920 3796 6243 0.00 37.0

 

개발DB쪽의 cpu가 너무 높게 사용되는듯 보여서 DB를 스펙up 해 보았다.

실제 운영시에 동작하는 DB 1대와 동일하게 4core 8G를 맞춰준다음 체크를 시작한다.
(메모리는 딸리지만 innodb buffer pool에 사용하는 부분이 작을뿐이지 테스트의 경우 한개의 API요청을 계속 동작하게 하는거라 크게 차이는 없을것으로 판단했다.

2300건의 경우 너무 스무스하게 처리됨.

 

수행조건  평균(ms) 90%(ms)  95%(ms)  99%(ms)  에러(%)  처리속도(/sec)
1G 100 119 126 140 0.00 38.4
1G 99 117 124 137 0.00 38.4

기존에 2300건에서 밀려서 딜레이가 발생하던게 사라졌다.

그럼 운영과 동일한 스펙의 DB라고 가정하고 문제가 되었던 상황인 1분당 평균 3000건에 대해서 어떻게 처리가 되는지 확인하기로 했다.

불필요한 테스트는 제거하고 필요한 옵션들에 대해서 was설정에 따라 속도가 얼마나 변경가능한지 확인을 해보고 싶었다.(WAS쪽 튜닝을 위해)

 

1번 테스트

  1. 메모리
수행조건 평균(ms)   90%(ms)  95%(ms)  99%(ms)  에러(%)  처리속도(/sec)
1G 1304 2793 3908 6302 0.00 48.0
1G 1462 3200 4323 7097 0.00 47.9
1G 1615 3335 4583 6921 0.00 47.9
2G 1978 4106 5376 8739 0.00 47.5
2G 1582 3617 4493 6802 0.00 47.9
2G 1581 3515 4503 6911 0.00 47.7

3번 테스트

수행조건  평균(ms)  90%(ms)  95%(ms)  99%(ms)  에러(%)  처리속도(/sec)
30개 2722 4368 4620 5058 0.00 46.4
30개 1562 2911 3101 3549 0.00 47.6
30개 1537 2826 3016 3394 0.00 47.6
50개 1950 3142 3545 4799 0.00 47.7
50개 971 1908 2289 3456 0.00 48.5
50개 1319 2660 3034 3884 0.00 47.9
50개 1729 2963 3407 4338 0.00 48.0
50개 1512 2625 3076 4078 0.00 48.0
100개 836 1995 2672 4262 0.00 48.6
100개 1376 2875 3856 5793 0.00 48.1
100개 1376 3049 4039 6061 0.00 47.8
100개 1402 3231 4285 6214 0.00 47.7
200개(default) 1304 2793 3908 6302 0.00 48.0
200개(default) 1462 3200 4323 7097 0.00 47.9
200개(default) 1615 3335 4583 6921 0.00 47.9

4번 테스트

수행조건  평균(ms)  90%(ms)  95%(ms)  99%(ms)  에러(%)  처리속도(/sec)
커넥션15 1376 2875 3856 5793 0.00 48.1
커넥션15 1376 3049 4039 6061 0.00 47.8
커넥션15 1402 3231 4285 6214 0.00 47.7
커넥션20 2242 4342 5355 7520 0.00 47.1
커넥션20 2416 4687 5781 8438 0.00 46.6
커넥션20 2303 4487 5543 7823 0.00 46.8
커넥션30 2217 4418 5318 7242 0.00 47.4
커넥션30 1897 4241 5222 6962 0.00 46.8
커넥션30 2311 4798 5691 8115 0.00 46.4

여러가지 옵션값을 변경해보아도 피크타임때 견뎌야하는 3000건을 빠르게 소화하지못하고 밀리는 모습을 보이며, DB서버의 CPU사용량을 체크 해 보았을때 80~90% 가까이 찍히는 모습을 보였다…!

DB서버가 2core에서 4core로 올라왔을뿐인데 피크타임에 들어오는 조회에 대한 처리량이 차이가 난다.

 

수행조건  평균(ms)  90%(ms)  95%(ms)  99%(ms)  처리속도(/sec)
2600건 104 126 135 152 43.4
2800건 151 246 274 337 47.5
2850건 176 320 358 431 47.6
2900건 166 304 354 443 47.6
3000건 982 1965 2601 4137 49.8
3000건 1439 3118 3962 6346 47.8

그렇다면 문제가 발생했던 상황을 무난하게 넘기는 속도가 나오려면 현재 운영DB의 스펙인 4core보다 순간적인 처리를 더 할 수있도록 8core로 가야하는건가..?

(동일하게 1분에 3000건이 넘어가는 경우 cpu사용량이 80~90% 까지 오르기 시작했다.)

테스트를 해 보기로 했다.

DB서버의 스펙을 변경을 해 보았다.

실질적으로 4core때 보다 8core일때 동일한 요청에 대해서 처리 할 수 있는 순간적인 처리량인 TPS가 늘어났다….!

수행조건  평균(ms)  90%(ms)  95%(ms)  99%(ms)  처리속도(/sec)
3000건 84 96 100 110 49.9
3600건 84 94 98 110 58.7
5000건 88 99 105 164 83.2
5500건 785 1621 2083 3237 88.9
6000건 2381 4952 5518 6719 91.5

최종…? 결론..?

일단 운영환경의 경우 MaxScale을 사용하여 select + insert의 경우 master로 select만 수행하는경우 slave로 분산처리가 되고 있기 때문에 단순하게 DB서버 1대의 스펙인 4core 32G로 바라볼순 없다.

그러나 테스트를 수행해본 4core 8G의 DB스펙 기준으로 테스트를 해본결과.

수치상으로만 봤을때는 분당 3000건에 대해서 평균적으로 발생한 요청을 처리 할 때 DB처리량이 밀리기 시작하는게 맞는듯 보이고… 분산처리가 되어있었기 때문에 그나마 밀리더라도 처리가 된게 아닐까 싶다…

동일한 상황이 발생하더라도 해당 요청들이 빠르게 처리가 되면서 다른 서비스들에 무리가 안 생기려면 8core로 스케일업을 수행한 다음 그 이후 발생하는 문제들에 대해서 추가적인 튜닝이 들어가야 하지 않을까…?(순간적으로 몰릴때는 최대 4300건까지 처리가 되야하기 때문이다.)

어느곳에서 병목지점이 생기는지 모니터링 시스템이 잘 되어 있었다면 좀 더 빨리 접근 할 수 있었을것 같은데 ㅠㅠ 해당 결과를 도출해서 도착하는데 시간이 너무 오래 걸린것 같다.

1차적으로 APM Tool인 Pinpoint를 개발서버에 적용해보고 그 이후 실질적인 개발라인으로 보고 후 운영서버에도 적용해봐야겠다. (어디서 병목지점이 발생하는지 UI상으로 쉽게 확인이 가능해보였다.)

반응형