배포한 프로젝트 서버 성능 올리기 (처리량, 응답시간)
서버 성능 올리기 (처리량, 응답시간)
서버 성능을 말할 때 다양한 지표가 있다. 그 중에 대표적인 지표 2가지는 응답시간과 처리량이다.
응답 시간
응답 시간은 클라이언트가 어떤 요청을 해서 그 요청에 대한 처리 결과를 받을 때 까지의 시간을 의미한다. 응답 시간은 서버에서 요청을 처리하는 시간 + 클라이언트와 서버 간의 데이터 전달 시간(대기 시간)으로 구성되어 있다.
처리량
처리량은 흔히 TPS(Transaction Per Second; 초당 처리할 수 있는 요청 개수)라는 수치로 많이 표현하는 데, 이 수가 높을 수록 많은 요청을 처리한다고 보면 된다.
TPS를 높이는 방법
1. 서버 늘리기
가장 쉬운 방법은 서버를 늘리는 방법이다. 단순하게 서버 1대가 10 TPS면, 2대면 20 TPS가 된다.
2. 쓰레드 풀+ DB 커넥션 풀 늘리기
비슷한 방법으로 쓰레드 풀 + DB 커넥션 풀을 늘리는 방법도 있다. 그러면 동시에 처리할 수 있는 요청 개수가 늘어나게 된다.
- 쓰레드 풀 5개일 때 처리 시간이 1초면 5 TPS이고,
- 쓰레드 풀 10개일 때 처리 시간이 1초면 10 TPS이 나오게 된다.
서버 늘리기/ 쓰레드 풀 늘리기 한계
서버를 늘리거나 풀의 개수를 늘려서 간단하게 계속해서 TPS를 높이면 좋으나 이러한 방식에도 어느 수준에 도달하면 한계에 부딪힌다.
무조건 서버 1, 2, 3대로 늘린다고 해도 성능이도 1, 2, 3배 비례해서 증가하지는 않는다. 어느 시점이 되면 DB의 부하가 견딜 수 있는 임계치를 넘어가면 먹통 증상이 발생한다. 그래서 실제로
- DB CPU 70~80%가 넘는 상황 발생 → DB 쿼리 시간 증가 → 처리 시간 길어짐 → 오히려 서버를 늘려도 요청만 더 쌓여서 TPS 떨어짐
그래서 TPS가 높이기 위해서는 서버를 높이는 것도 필요하지만 가장 기본적으로 처리 시간 자체를 줄일 필요가 있다.
- 처리 시간 1초, 쓰레드풀 10개 기준으로 10 TPS가 나올 때
- 처리 시간을 0.5초를 줄이면 20 TPS가 나오게 된다.
처리 시간 줄이는 방법
처리 시간에서 비중이 높은 대상을 찾아 줄여야 한다. 비중이 높은 대상으로는 세 가지가 있다.
- DB 연동
- API 호출
- 데이터 집계/ 계산
DB 연동 처리 시간 줄이기
DB와 관련된 처리 시간을 줄이는 방법은 여러가지가 있는 데 보통 세 가지 방식을 사용한다.
1. 쿼리 튜닝
첫 번째는 가장 기본적인 쿼리 튜닝 방법이다. 쿼리만 잘 튜닝해도 응답 시간이 획기적으로 줄어드는 경우가 많다.
2. 캐시
메모리의 데이터를 담아두고 DB 쿼리를 실행하지 않고 캐시 데이터를 사용하는 방법이 있다.
3. 장비빨
돈이 들지만 확실한 방법이다.
- 쓰기/읽기용 DB를 나눠서 트래픽이 증가하면 읽기용 DB를 증가시켜서 요청을 분산시켜준다. 응답 시간을 일정하게 유지시켜주는 효과가 있다.
- 흔히 스케일-업이라하는 하드웨어 업그레이드를 시켜준다. CPU 성능 올려주고 메모리 늘리고, DB에 SSD도 꽂고 이런 식으로 하면 정말 온갖 튜닝을 하는 것 없이도 굉장히 높은 성능을 얻을 수 있다.
API 호출 처리 시간 줄이기
내가 호출하는 API에 응답 시간이 증가하면 처리 시간이 증가하게 되는 거니깐 API 호출할 때도 처리 시간을 줄일 필요가 있다. 흔히 두 가지 방식이 있다.
1. 캐시
DB와 같은 방식이다. 외부 API 호출해서 뭔가 데이터를 읽어오는 경우에 캐시를 사용해서 읽어오는 빈도 횟수를 줄이는 방법이 있다.
2. 호출 제거
호출 자체를 제거하는 방법이 있다. 데이터를 외부 시스템에 전달해야 할 때 주로 사용한다. 직접 외부 시스템을 호출해서 데이터를 전달하기 보다는 Kafka, RabbitMQ같은 메시징을 이용해서 비동기로 외부 시스템을 전달하는 방법이다. 그러면 외부 호출 연동 자체가 사라지니깐 처리 시간도 같이 줄어드는 효과를 볼 수 있다.
데이터 집계/계산 처리 시간 줄이기
데이터 집계나 계산을 그때그때 매번 실시간으로 하게 되면 이 역시 DB에 많은 부하를 줄 수 있다. 그래서 집계나 계산하는 류는 미리 계산해서 캐시나 DB에 보관해준다. 그러면 역시 불필요한 처리 시간을 줄일 수 있다.
- 통계류 (좋아요 수, 조회 수, 팔로우 수 등)
대기 시간 줄이기 (응답시간 = 대기 시간 + 처리 시간)
응답 시간은 대기 시간(Latency Time) + 처리 시간(Processing Time)으로 되어있으니 전체적으로 응답 시간을 줄이기 위해서는 처리 시간도 물론 중요하지만 대기 시간을 줄여줄 수 있으면 줄이는 게 좋다.
대역폭
대역폭(최대로 전송할 수 있는 데이터 양)이 작으면 서버에 연결하는 클라이언트 개수가 증가할 때 주고 받는 속도가 급격히 느려진다. 고속도로에 차가 증가하면 속도가 느려지는 것과 유사하다. 이를 해결하는 방식으로 세 가지를 고려해 볼 수 있다.
1. 응답 크기 줄이기
응답 자체를 압축한다거나 이미지 품질을 조금 낮춰서 파일 크기를 줄여서 응답 크기 자체를 줄여서 보내준다. 고속도로에 대형차를 출입시키는 대신에 경차를 출입시킨다고 보면 된다.
2. 트래픽 분리하기
이미지, JS와 같은 정적 파일을 서버에서 제공하지 않고 외부 CDN을 통해 제공하도록 변경해준다. CDN은 이러한 정적 파일을 제공하는 데 특화된 서비스이다 보니 대역폭 자체가 넓다. 그래서 이는 다른 방식으로의 응답 크기를 줄이는 방법으로, 이미지 파일의 품질이나 응답 크기 자체를 압축시키지 않아도 된다.
3. 대역폭 늘리기
또 하나는 대역폭 자체를 늘리는 것(인스턴스 사양 올리기)인데, 이 방식은 비용이 많이 든다. 상대적으로 CDN이 유리하다.
정리
서버 성능과 관련된 다양한 지표가 있겠지만 초보가 알아두면 좋을 처리량, 응답시간을 줄이는 방법을 다뤄봤다.
- 처리량을 높이려면
- 가장 기본적으로 서버가 요청을 처리하는 시간 자체를 줄여야 함 (제일 중요. 이게 안되면 나머지는 소용 없음)
- 스케일-아웃으로 장비 추가하기 (비용 듬)
- 쓰레드 풀/ 커넥션 풀의 개수도 중요하다. 이 수가 적절하지 않으면 성능이 잘 나오지 않을 수 있다.
- 처리 시간을 줄이려면
- DB 쿼리를 튜닝하거나 장비빨(스케일 아웃, 스케일 업)으로 DB 연동 시간을 줄여야 함
- 캐시 사용해서 데이터 읽는 횟수 줄이기
- 데이터 집계를 실시간으로 하지말고 미리 계산해서 DB/ 캐시에 보관하기
- 대기 시간을 줄이려면 (대역폭과 관련된 처리를 하면 좋다)
- 응답 크기 자체 줄이기 (압축)
- 이미지나 JS같은 정적 파일들을 CDN과 같은 곳에 둬서 트래픽 분리하기
- 비용 측면에서 효과적이지 않지만 대역폭 자체를 늘리기 (서비스가 커지면 필수로 늘려야 하긴 함)
돈 안들고 쉽게 처리할 수 있는 방법 순서대로 정리
처리 시간 줄이기
1. API 성능 개선 - 캐시(Redis) 사용, 비동기 메시지 처리(Kafka, RabbitMQ)
- 캐시 사용 방식 - 기본적으로 자주 사용하는 데이터(유저 정보, 인증), 데이터 집계/ 계산한 데이터(좋아요 수, 여부)는 캐시에 저장하여 DB 읽기 횟수를 줄이자.
- 비동기 메시징 큐 사용 방식 -
2. DB 쿼리 튜닝하기 - 말 그대로 DB 쿼리 튜닝 방식. 사용하는 DB 쿼리에 대한 공부 필요 (ex. RealMySQL 8)
대기 시간 줄이기
1. CDN(S3, Cloudflare)을 사용해서 정적 파일들을 응답 메시지와 분리하여 처리하기
2. 그래도 감당안되면 EC2 인스턴스 사양 높이기
참고