-
BootCamp(2) - 프리티어 인스턴스 성능 튜닝Record 2022. 11. 25. 23:08
작지만 강한 벌꿀 오소리처럼... 시작하며
3개월 간 진행한 부트캠프의 마지막 프로젝트에서 AWS 프리티어 리소스를 단물이 나오지 않을 때까지 최대한 써먹기 위해 고민한 내용들을 정리했습니다. 현업에서는 어떻게 클라우드 리소스 비용 최적화를 진행할까 많이 고민했고, 정답은 당연히 나오지 않았으나 최대한 시도해보려고 한 흔적들이니 심심할 때 봐주시면 좋을 것 같고 피드백 주시면 감사하겠습니다.
✔ EC2 ( t2.micro ), RDS ( t3.micro ), ElastiCache for Redis ( t2.micro ) 를 Beanstalk 환경에서 대용량 데이터가 있는 쇼핑몰 프로젝트를 진행하고 있습니다.
GitHub - SpringMarket/SpringMarket: 1000만 건 상품 데이터가 있는 의류 쇼핑몰
1000만 건 상품 데이터가 있는 의류 쇼핑몰. Contribute to SpringMarket/SpringMarket development by creating an account on GitHub.
github.com
📌 고려하는 부분은 4가지 입니다.
- DB 읽기 전용 복제본을 생성해 Read 요청을 분산합니다.
- Hikari Connection Pool 최적의 개수를 찾아야 합니다.
( Cache Write Back 전략으로 조회수를 관리하고 있었기에 Connection Pool 확장이 필요했습니다. ) - Time_Wait 소켓의 최적화가 필요했습니다.
- TCP 기반으로 동작하는 Redis의 통신 최적화가 필요했습니다.
( Warmup 동작의 최적화 )
✅ DB 읽기 전용 복제본
- RDS 데이터베이스 작업에서 간단하게 진행할 수 있었습니다.
- 총 5개까지 생성이 가능합니다. ( MySQL 기준 )
- 모든 동작들이 하나의 DB로 진행되는 상황에서 분산이 가능해졌습니다.
- Update 요청은 메인 DB 에서만 동작합니다.
- Read 요청은 Replica DB 에서만 교차로 동작합니다. ( 설정 가능합니다. )
✅ Hikari Connection Pool 최적의 개수
- Cache Write Back 전략으로 조회수를 관리하고 있었기에 Connection Pool의 확장이 필요했지만
성능이 낮은 DB를 사용하고 있었기에 무작정 개수를 늘릴수는 없었습니다.
( 부하가 걸리지 않게 하는 선에서 확장이 필요했습니다. ) - RDS T3.Micro의 Max Connections은 85개입니다. Pool의 개수가 이 수를 초과하면 안됩니다.
- 하단의 데드락을 회피할 수 있는 Pool Size 공식은 참고만 했습니다.
( 최대한 확장하는게 목표였습니다. )
데드락을 회피할 수 있는 최소한의 Pool Size입니다. Jmeter을 활용한 부하테스트로 최적의 지점을 확인하고자 합니다.
( Connection Pool이 너무 적음 ▶ 🎉최적의 Pool Size🎉 ▶ DB가 동시에 들어오는 요청을 감당하기 힘듬 )
- 10초간 1000명의 동시 상품에 대한 주문은 무난히 성공했습니다.
( Connection Pool Size : 10 // Default 값 입니다. )
- 하지만 1500건의 주문부터 오류가 나기 시작했습니다.
- 결론부터 말하자면 Connection Pool의 적정 수는 20이었습니다.
Pool 10 ▶ Error 21.04%
Pool 13 ▶ Error 14.53%
Pool 17 ▶ Error 11.24%
🎉 Pool 20 ▶ Error 5.67% 🎉
Pool 30 ▶ Error 29.20%
Pool 60 ▶ Error 35.50%
( 포스팅의 길이 최적화를 위해 Connection Pool 20 테스트 결과만 첨부하겠습니다. )
요기에서 병목이 발생하는 것 같네요🔼 ✅ Time_Wait 소켓의 최적화
- Elastic Beanstalk 서버에 NginX가 있기 때문에 요청이 오면 Nginx가 그 요청을 받아 다시 스프링부트로 실행된 Tomcat 으로 요청을 보냅니다. 이 과정에서 Nginx 는 Client가 되고, Tomcat은 Server가 됩니다.
( 참고 : 이동욱님 블로그 )
KeepAlive 적용
- KeepAlive는 한번 맺은 세션을 요청이 끝나더라도 유지해주는 기능을 얘기합니다.
- 매 요청마다 새로운 세션을 만들지 않고, 지정된 숫자만큼의 세션을 연결한 뒤 그 연결을 통해 요청을 처리하게 해줍니다.
- 이것저것 시도 해보고싶어서 적용해봤으나, 유동적이고 동시에 많은 접근이 발생하는 이커머스 특성상 어울리지 않아 실제 환경에서는 사용하지 않을 것 같습니다.
nginx.conf 결과 ✅ Redis 통신 최적화
상품 데이터의 빠른 조회와 DB 부하 분산을 위해 캐싱은 필수였습니다.
캐싱(인기게시물 상세페이지, 랭킹보드)을 위해서는 Warmup 동작이 필수였지만 TCP 기반으로 동작하는
Redis에 몇 천건의 데이터를 주기적으로 Input 한다는 것은 결과가 뻔히 보이는 듯 했습니다.
- 5000건의 상품 데이터를 캐싱한다고 가정했을 때 하단의 사진처럼 5000건의 Request와 Response가 발생합니다.
- 파이프라이닝을 통해 각각의 Response를 기다리지 않고, 한번에 여러개의 명령어를 전송할 수 있게 됐고, 비동기적으로 그에 대한 Response를 받아오는 과정으로 진행됩니다.
- 이에 대해 간단히 정리해놓은 포스트 첨부하겠습니다.
포스트는 여기까지 하고 마치겠지만 더 생각나는게 있다면 추가하겠습니다.
읽어주셔서 감사합니다.
'Record' 카테고리의 다른 글
AWS Building Block Review - DevSecOps (0) 2023.04.21 토비의 스프링부트 수강 후기 (0) 2023.04.17 On Boarding (2) :: 이력 데이터 관리 (0) 2023.03.16 On Boarding (1) :: 아키텍처 (0) 2023.03.16 BootCamp(1) :: 마지막 프로젝트 (0) 2022.11.24