본문 바로가기

Stress Test

[부하 테스트] 분석 (2차)

이번 장에서는 [부하 테스트] 결과 (2차) (링크)의 결과를 분석해보고 동접자 200명을 넘기지 못한 원인을 파악해본다.
결과에 따르면 100명까지는 서버가 정상적으로 버텨주었으므로 200명부터 500 Internal Server Error가 발생한 원인을 파악해본다.


분석

부하 테스트 1차와 달리 2차 테스트에서는 Docker Container가 Kill되지 않았다. 이러한 점을 보았을 때 리소스가 부족하지 않았을 것으로 예상된다.
실제로 Resource 사용량을 확인해본다.

CPU 사용량의 경우 테스트 전 구간에서 10%를 넘기지 않았다. (최초 60%를 넘긴 부분은 컨테이너 초기화를 위해 서비스를 재기동한 부분이다.)

Memory 사용량의 경우 테스트 전 구간에서 2GB를 넘기지 않았다.

CPU와 메모리가 부족한 상황은 아니며 500 Code의 원인은 다른 곳에 있을것으로 예상된다.
다음으로 500 Code가 발생하기 시작한 시점을 파악하기 위해 요청 및 응답 기록을 확인해본다.
nmonchart로 생성된 html파일에서 Charts -> Throughput -> Codes Per Seconds를 확인해본다.

500 에러 발생시점

테스트를 시작한 시점에는 500 Code가 발생하지 않았다.
하지만 테스트 이후 1 ~ 2분 이내에 발생하기 시작한 것으로 확인된다.
발생한 시점을 보면 504 Code가 발생함과 동시에 500 Code가 발생한 것을 확인할 수 있다.

원인

원인은 DB Connection Pool의 부족이었다.
JPA를 사용하는 시스템에서 데이터 저장(= entityManager.save(entity))을 요청하면, 기본적으로 DB에 2개의 커넥션이 필요하다.

  1. 요청 커넥션
  2. 기본키 생성(조회)용 커넥션
    (자세한 설명은 HikariCP Dead lock (링크)을 읽어보도록 한다.)

혹시라도 위의 링크를 읽기 귀찮은 사람들을 위해서 필자가 간략하게 정리하겠다.
JPA를 사용하여 데이터를 저장하면 아래와 같은 로직으로 데이터를 저장하게 된다.

  1. 신규 데이터를 저장해달라는 요청이 들어오면 요청 Transaction이 시작되고 DB Connection 한 개를 가져온다.
  2. 신규 데이터의 Primary Key를 구하기 위해 Primary Key 생성용 Transaction을 시작하고 DB Connection 한 개를 가져온다.
  3. 신규 데이터 Primary Key를 구하는 쿼리 select ....for update하는 시점에서 2번 과정에서 생성한 Connection이 Lock이 생성되고 다른 Connection들은 Key Table에 접근할 수 없다.
  4. Primary Key를 가져왔다면 2번 단계에서 생성한 Transaction을 종료한다.
  5. 신규 데이터를 저장하고 Client에 결과 값을 전달한 후 1번 단계에서 생성한 Transaction을 종료하며 DB Connection을 반납한다.

3번 과정에서 Table Lock이 발생한다.
이러한 이유라 JPA는 Key 테이블에 대한 Connection을 빨리 반납하기 위해 신규 데이터를 저장하는 경우 2개의 Connection을 만드는 것이다.

결과를 뽑아내기까지 오랜 시간이 걸리는 조회용 쿼리가 있다고 가정한다.
조회 요청은 Connection Thread를 반납하지않고 오랜 시간을 유지하고 있을 것이다.
이러한 요청들이 많아져서 HikariCP의 최대 갯수를 모두 사용하게 되면 새로운 요청들은 더 이상 DB Connection을 가질 수 없게 된다.
이러한 경우 IOException이 발생하게 된다.


이번 장에서는 [부하 테스트] 결과 (2차)의 결과를 분석해보았다.
DB COnnection을 늘릴 수 없는 상황에서 Query를 수정하지 않는 이상 최대 동접자를 확인하는 부하 테스트는 무의미해졌다.
부하 테스트는 이번장으로 마무리하고 다음 장에서는 Tomcat Max Connection 수를 수정하면서 오류가 나지 않는 선에서
가장 높은 TPS를 뽑아내기위한 벤치마크를 진행해본다.

'Stress Test' 카테고리의 다른 글

[Benchmark] Datasource 분리  (0) 2022.01.22
[Benchmark] HikariCP 설정  (0) 2022.01.22
[부하 테스트] 결과 (2차)  (0) 2022.01.22
[부하 테스트] 분석 (1차)  (0) 2022.01.22
[부하 테스트] 결과 (1차)  (0) 2022.01.22