글 작성자: Key Ryung

개요

기획한 기능들을 모두 완성하고 nGrinder를 통해 처음 Load Test를 진행했습니다. 

<처음 Test 당시 서버 인프라 구조>

위의 그림과 같이 nGrinder의 Controller와 Agent는 다른 서버로 분리했지만 CI/CD 툴로 Jenkins, Application Server, MySQL까지 하나의 인스턴스 안에 들어있는 구조입니다. Docker Out Of Docker라는 방식을 사용해서 빌드와 배포까지 진행하는 구조입니다. 정말 간단하게 테스트를 진행해서 병목을 찾을 수 있다고 생각했기 때문에 가장 저렴한 방식으로 구성했습니다.

 

Docker Out Of Docker란 Docker Host와의 통신하여 Jenkins Docker 외부에 Docker를 실행시키는 방법입니다.

 

이런 구조가 문제가 될 것이라는 것은 테스트 이전까지 알지 못했습니다. 

DooD 구조에서 테스트

Dood 구조에서 로그인 API Test

목표한 TPS는 1250인데 24.8이라니?!🥲  게다가 반환되는 응답들의 HttpStatus Code가 200으로 반환되지 않아 Error로 처리되는 것을 확인할 수 있었습니다.

nGrinder Test 결과에서 보이는 에러들

먼저 에러들이 왜 발생하는지 원인부터 찾기 위해 APM 툴인 Pinpoint를 통해 StackTrace를 확인해봤습니다. 다음과 같이 붉은색과 초록색으로 정상적인 응답이 오는지 확인할 수 있습니다.

Pinpoint StackTrace

StackTrace를 보면 HikariDataSource에서 Time-out시간인 30초를 초과하여 예외를 던지는 것을 확인할 수 있었습니다.

쿼리 수행시간이 300ms나 걸리는 결과

더불어 SELECT 쿼리 수행 시간이 300ms 이상이 걸리는 것을 볼 수 있습니다.

(이 부분은 다음 포스트에서 개선하는 과정을 포스팅하겠습니다.👏)

 

먼저 타임 아웃이 발생하는 원인부터 파악하는 것이 순서였겠지만 이미 테스트를 진행하면서 원인은 파악되었습니다. 테스트를 한 번 진행한 뒤로 서버의 SSH 연결뿐만 아니라 Jenkins까지 접속까지 안 되는 현상이 있었기 때문에 인프라 구조에 문제가 있다는 것을 알 수 있었습니다. 다시 테스트를 진행하기 위해서는 서버 인스턴스의 재부팅과 Docker Restart까지 진행해야 되는 너무나 강렬한 시그널을 보내고 있었기 때문에 과감히 인프라를 개선해야 겠다고 생각했습니다.

서버 인프라 개선하기

개선된 인프라

추후 더 많은 테스트를 예상해서 모든 Docker들을 각각 하나의 서버 인스턴스에 배정했습니다. Jenkins와 Application 서버도 분리하여 DooD라는 구조 대신 SSH를 통해 배포하는 방식을 적용했습니다. 위와 같이 서버 인프라를 개선하고 테스트를 다시 진행했습니다.

 

인프라 변경 후 테스트 결과

개선후 로그인 테스트

이전에 비해서 TPS가 큰 폭으로 상승한 것을 볼 수 있습니다. 이로써 병목 지점이 인프라 부분이라는 것을 다시 점검할 수 있었습니다. 그럼 Pinpoint 결과도 다시 봐보겠습니다. 아직 목표한 성능에는 못미치지만 첫번째 그래프를 보았을 때 고르게 분포하는 것을 볼 수 있습니다.

Pinpoint Transaction

추가적으로 Pinpoint Inspector를 통해 현재 어플리케이션 서버의 상태 또한 확인할 수 있습니다. 초기에 요청이 들어올 때 CPU 사용량이 급증하다가 서서히 감소해나가는 모습도 볼 수 있고 Heap Usage 그래프를 통해서 GC가 잘 수행되고 있는지도 볼 수 있었습니다.


고민을 위한 여지

  • 왜 초기에 CPU 사용량이 급증했다가 서서히 감소할까?
  • 다른 GC 였다면 어떤 패턴으로 그래프가 그려졌을까?(현재는 G1 GC - Java11)
  • 다음으로 성능을 개선하기 위한 행동으로 무엇이 적절할까?

 

해당 프로젝트는 네이버 클라우드를 활용하여 진행했습니다.