항해99/개발일지

20220402 개발일지 #메인페이지 Polling 부하테스트

paran21 2022. 4. 4. 02:06

프로젝트 진행하면서 멘토링 시간에 개발자는 우리 서비스가 언제 고장이 날지를 알고 있어야 한다는 말을 들은 적이 있다.

그래서 Jmeter도 설치하고, 이것저것 값도 넣어보고, 구글링도 열심히 해봤는데 사실 잘 와닿지는 않았다.

 

사실 중간발표 때 테스트를 할 때는 목적이 있어야 된다는 말이 더 인상적이었다.

어떤 목적을 가지고, 서비스의 어떤 지점을 개선하기 위한 목적에서 테스트를 하는 지에 따라 테스트 방법도, 시나리오도 달라질 것이다.

 

그런데 이번에 배포하고 에러를 수정하면서 우리 서비스에서도 부하가 오는 지점이 있다는 것을 알았다.

바로 메인페이지에서 방 정보를 업데이트 하기 위해 1초에 한번씩 api 요청을 보내는 부분이다.

 

프론트에서 작업하시면서 이전에 걱정된다고 언급하시기도 했었는데,

이번에 배포 직후 CPU가 90%까지 올라간 것도 이 메인페이지 때문인 것 같다.

 

구글 애널리틱스를 통해 볼 때 40명 이상은 들어온 것 같고, 배포 후 얼마 안되서 DB에 생성된 유저 수는 계속 20명 전후를 유지했다.

그런데 CPU 사용량은 점점 내려갔었다.

나중에 생각해보니 처음에 메인페이지에 접속자가 몰리면서 api 요청이 집중되서 부하가 온 것 같고, 시간이 약간 지나 대기페이지나 게임페이지로 분산된 후에는 다시 CPU 사용량이 내려간 것 같다.

 

실전프로젝트로 게임을 하다보니 몇 명까지 감당이 되는지 질문을 받았었는데, 게임의 특성 상 오히려 게임 중에는 api 요청이 많지 않아서 부하가 많이 오지는 않는 것 같고 메인페이지가 폴링 때문에 서비스에서 가장 부하가 많은 지점인 것 같다.

 

그래서 메인페이지에서 현재 몇 명 까지 접속자를 감당할 수 있는지 테스트를 해보고, 개선 방법을 찾아보기로 했다.

CPU를 2개로 늘려서 이미 부하는 많이 내려간 상태이지만 코드 단에서 개선할 방법을 찾아보려고 했다.

 

우선 spring의 코드를 찾아보면 해당 api는 전체 방 리스트를 조회하는 api로 Room과 User를 조회하는 쿼리가 포함되어있다.

복잡한 쿼리문이 나가는 것이 아니고, 최소한 Room과 User는 조회가 필요하다고 생각해서 spring 코드 자체에서 개선할 부분은 찾지 못했다.

다음으로 생각한 방법은 폴링 간격을 늘리는 것이었다.

지금 1초 간격으로 요청하고 있는데, 2초로만 바꿔도 실제 요청은 1/2로 줄어들 것이다.

 

서버 부하 테스트를 위해 먼저 Jmeter를 사용해보려고 시도했다.

메인페이지의 접속자가 한 번에 많이 들어올 수도 있고, 일정 시간 안에 점점 많이 들어올 수도 있지만 결국 부하가 가장 큰 지점은 메인페이지에 동시에 많은 유저가 접속해 계속 폴링을 보낼 때라고 생각했다.

그래서 Ramp-up period는 1로, Loop Count는 100으로 고정을 하고 Threads만 계속 늘려서 테스트를 해보았다.

매번 조금씩 값이 달라지기는 하지만 350 정도를 넘어가면 에러율이 갑자기 올라가는 것을 확인했다.

 

그런데 문제는 폴링을 1초에서 2초로 늘린 걸 Jmeter에서 어떻게 적용할 지였다.

실제 요청이 반으로 줄어드니까 Loop Count를 50으로 바꾸거나, Ramp-up Period를 2로 바꾸기도 해봤는데 폴링 자체가 클라이언트에서 지속적으로 요청으로 보내는 것이고, Jmeter는 서버에 직접 요청을 보내는 것이라 테스트 방법이 맞는지 확신할 수 없었다.

그리고 400정도만 되도 바로 에러가 뜨는데, 테스트 방법이 잘못된 건지 정말 서버가 감당을 못하는 것인지 알 수가 없었다.

이 Threads로는 실제 유저의 수를 판단할 수는 없고, 비교만 할 수 있을 텐데 폴링 1초와 2초라는 조건을 Jmeter로 구현이 잘 된 것인지도 판단이 되지 않았다.

 

찾아보다가 EC2의 CPU 사용량을 실시간으로 보여주는 명령어를 알게 됬는데, 에러율이 낮아도 어느 시점부터는 CPU 사용률이 엄청 높아져서 부하의 기준을 어디로 삼아야 하는지도 햇갈렸다.

또, 실시간 CPU는 늘어도 EC2 CPU 사용량은 많이 증가하지 않았다.

TPS가 줄어들 줄 알았는데 요청이 많아져서 그런지 오히려 증가하는 구간도 있었고 같은 조건을 넣어도 값이 계속 변하는 지점도 있었다.

 

한참 고민하다가, 그럼 직접 클라이언트로 테스트를 시도해봤다.

CPU 사용률을 실시간으로 보면서 창을 계속 띄워서 10씩 증가시켜봤는데 CPU 사용량이 점점 증가하는 것이 바로 관찰되었다.

그래서 폴링 조건을 변경해서 서버 부하를 비교하기 위해서는 클라이언트로 직접 테스트를 하기로 했다.

 

먼저 현재 1초로 폴링했을 때는 70명 정도에서 200 중 180% 이상으로 사용량이 올라가는 것을 볼 수 있었다.

1.5초에서는 생각보다 차이가 없었고, 2초에서는 차이가 나긴 했는데 한 100~120부터 계속 180%대에서 유지되다가 200 가까이되서 not found 에러가 뜨는 것을 확인했다.

 

실제 서비스에서는 다른 요청도 같이 들어갈 거라서 CPU 사용량이 증가하는 양상을 계속 보다가 급격히 증가하면서 180%까지 사용되는 지점을 기준으로 잡기로 했다.

EC2에서도 90%정도 까지 CPU 사용량이 올라가는 것을 확인했다.

 

다시 테스트를 진행해서 얻은 값은 1초 70명, 2초 100명이다.

2초라서 거의 2배 가깝게 더 버틸 수 있을 줄 알았는데 꼭 그런 것 같지는 않다.

테스트를 몇 번 더 해보면 또 값이 달라질 수도 있겠지만 보수적으로 접근하는 편이 낫다고 생각했다.

 

이렇게 놓고 나니 생긴 다른 문제는, 30명을 더 수용하기 위해 폴링을 2초로 하는 게 좋은 선택인가, 였다.

2초로 해놓고 업데이트 체감이 어떻게 되는지 테스트를 해봤는데, 이미 게임을 시작 혹은 삭제된 방에 들어가지는 경우가 있었다.

물론 이 경우 프론트에서 따로 처리를 해서 alert를 띄우고 메인페이지로 다시 보낼 수 있지만 이런 상황 자체가 좋은 유저 경험은 아니라고 생각했다.

또, 현재 서비스 수준에서 70명 이상 동시 접속할 가능성이 얼마나 되는지도 생각해봤다.

배포 첫날에 많이 잡아야 50명인 것 같고, 발표 날에 항해 사람들 중 새로 접속해서 볼 사람은 많지 않을 것 같았다.

실제 100명까지 들어올 가능성은 낮은데 이를 위해 유저 경험을 나쁘게 하는 것보다 현재로 유지하고, 만약에 서비스가 확대되서 문제가 된다면 폴링 말고 이벤트를 쓰는 등 아에 다른 방법을 시도해보는게 더 나을 것 같았다.

 

그래서 결국 그대로 1초로 유지하기로 했다.

Jmeter는 여전히 어렵지만, 이렇게 여러 방면으로 시도를 해보고 팀원들과 같이 논의를 해서 결론을 낸 것 자체가 값진 경험이었다.

 

배포 후에 뭐라도 성능테스트를 해야할 것 같다는 압박감이 있었는데 Jmeter를 쓰지 않아도 우리 서비스에서 부하가 오는 지점을 확인하고 개선방안을 도출하기 위해 시도해봤다는 것 자체로도 충분한 것 같다.

 

이번주 배포하면서 정신이 없었는데 나름 잘 마무리한 것 같아서 뿌듯하다!