유튜브 "쉬운 코드" 강의를 바탕으로 정리한 글입니다.
https://www.youtube.com/watch?v=zowzVqx3MQ4
DB 요청/응답 흐름 이해하기
일반적으로, 쿼리 요청/응답 과정에서 네트워크 통신이 발생합니다. (TCP 기반으로 동작)
- 높은 송수신 신뢰성을 가짐 (연결 지향)
매번 데이터를 조회할 때 connection을 열고 닫으면 시간적인 비용이 크게 발생한다. (서비스 성능에 좋지 않다.)
이를 개선하기 위해 미리 연결된 커넥션을 가지고 있으면 좋음
DBCP
미리 데이터베이스에 연결 요청을 보내고, 연결된 connection을 애플리케이션 서버에서 관리하고 있는다.
- API 요청이 들어오면 관리하고 있는 Connection Pool에서 하나의 connection을 가져가 사용합니다.
- 데이터베이스와의 연결이 종료되면 close connection이 진행되면, connection pool에 반납합니다.
DBCP 장점
- connection을 재사용할 수 있다.
- 데이터베이스와 연결하고 끊는 시간을 절약할 수 있다.
DBCP 설정 방법
DB Connection은 backend server와 db 서버 사이의 연결을 의미하기 때문에 각 서버에서의 설정을 진행주어야 합니다.
MySQL 설정
- max_connections : client와 맺을 수 있는 최대 connection 수
- 신규 애플리케이션 서버를 증설할 때 유의해야 함
- 애플리케이션이 아무리 많아져도 데이터베이스에서 설정된 커넥션 수만큼 연결을 가질 수 있음
- wait_timeout : connection이 inactive 할 때 다시 요청이 오기까지 얼마의 시간을 기다린 뒤에 close 할 것인지
- 애플리케이션 서버에서 비정상적인 connection 종료, connection 반환 오류, 네트워크 단절 시 데이터베이스 connection이 계속해서 연결되고 있는 문제가 있음
- 이를 위해 wait_timeout 설정을 통해 데이터베이스의 connection을 관리합니다.
Spring HikariCP 설정
- minimumldle : pool에서 유지하는 최소한의 idle connection 수
- maximumPoolSize: Pool이 가질 수 있는 최대 connection 수
- inactive + active connection 수를 의미함
maximumPoolSize가 minimumIdle보다 우선순위가 높다.
idle connection 수가 minimumIdle보다 작고, 전체 connection 수도 maximumPoolSize보다 작으면 추가 connection을 생성합니다.
maximumPoolSize에 충족하면 더 생기지 않는다.
(default, minumumIdle == maximumPoolSize로 고정)
- maxLifetime : pool에서 connection의 최대 수명
- maxLifetime이 넘어가면 idle일 경우 pool에서 바로 제거, active인 경우 pool로 반환된 후 제거
- DB의 connection time limit 보다 몇 초 짧게 설정해야 합니다. (2~5초)
애플리케이션 서버에서 하나의 idle이 59초에 요청을 받아 데이터베이스에 요청을 보내는 경우, 요청을 보내는 순간 데이터베이스에 설정된 wait_timeout이 지나 요청 실패가 될 수 있다. → DB의 connection time limit보다 몇 초 짧게 설정한다.
- connectionTimeout: pool에서 connection을 받기 위한 대기 시간
- 트래픽이 몰리는 경우 connectionTimeout이 지나면 exception을 발생하여 연결 실패 메시지를 전달합니다.
- 사용자 입장에서 30초까지 기다리지 않으므로, connectionTimeout을 적절하게 설정해서 예외 메시지를 전달해줘야 합니다.!!
적절한 connection 수 찾기 위한 과정
- 모니터링 환경 구축하여 서버 리소스, 서버 스레드 수, DBCP를 분석한다.
- 백엔드 시스템 부하 테스트를 진행한다. (nGrinder)
- 조금씩 부하를 주면서 적절한 수를 찾는다.
- request per second와 avg response time을 확인한다.
데이터베이스 부하인 경우, (커넥션 말고 추가적인 리소스가 필요한 경우)
- secondary 추가
- cache layer 추가
- sharding 추가
사진 4) 적절한 데이터베이스의 max_connections을 정한 경우 네트워크 트래픽에 따라 애플리케이션 서버를 증설하여 관리할 수 있다.
2개의 서버로 처리
- 각 애플리케이션 서버에 maximumPoolSize를 25로 설정
- 10개의 connection이 여유분으로 남는다.
- 해당 여유분을 어떻게 설정하냐에 따라서 애플리케이션 서버를 스케일 아웃으로 증설할 수 있다.
- 하나의 서버가 처리할 수 있는 양이 있으므로, 웹 서버를 증설하여 처리한다.
3개의 서버로 처리
- 각 서버에 maximumPoolSize를 15개로 설정한다.
- 15개의 connection이 남는다.
- 하지만, 트래픽이 더 몰리는 경우 서버 증설을 하여 남은 커넥션을 설정하여 처리할 수 있다.
- 하지만, 데이터베이스의 개수를 늘리는 방법도 있으므로, 상황에 따라 적절하게 선택하는 것이 좋아 보임.
참고 자료
https://github.com/brettwooldridge/HikariCP
https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html
https://d2.naver.com/helloworld/5102792