백엔드 서버로 요청이 들어오고, DB를 사용해야 하는경우 시퀀스 다이어그램. 백엔드 서버와 데이터베이스 서버는 TCP 기반으로 동작한다.
TCP는 연결지향 프로토콜이며, 데이터 순서를 보장하며 신뢰성이 높다.
백엔드 서버는 데이터베이스 서버와 통신하기위해 커넥션을 생성하고 통신이 끝난 후 커넥션을 제거한다.
open connection : 3 ways handshake
close connection : 4 ways handshake
통신을 열고 닫는경우 의외의 시간이 소비된다. 매번 connection을 열고 닫는 시간적 비용 발생 서비스 성능에 좋지 않다.
백엔드 서버가 동작될 때 미리 데이터베이스와 연결되는 커넥션을 미리 생성 하고 연결해놓고, 커넥션은 1개가 아니고 여러개이기 때문에 pool이라 부른다.
백엔드 서버로 요청이 들어오면 백엔드 서버는 사용되지 않고 있는 커넥션을 획득하고, 데이터베이스와 처리가 끝난 경우 커넥션을 닫는게 아닌, 커넥션 풀에 사용한 커넥션을 반납한다.
★데이터베이스와 통신이 필요한 경우 매번 커넥션을 열고 닫는게 아닌, 미리 준비된 커넥션을 사용하고 반납하고 재사용한다.
스프링부트 Hikari CP, MySQL 기준
CP는 백엔드서버와 데이터베이스 서버 사이의 연결과 통신이기 때문에 백엔드 서버와 데이터베이스 서버 각각의 설정법을 잘 알고 있어야한다.
max_connections : client와 (동시에) 맺을 수 있는 최대 connection 수
커넥션의 갯수가 4개이고, max_connections의 값이 4인 경우. 백엔드 서버로 계속해서 클라이언트 요청이 들어오면 커넥션이 계속 사용되고 데이터베이스가 처리할 수 있는 요청은 최대4개 뿐이다. 백엔드 서버를 증설해도 데이터베이스에서는 커넥션을 더 받아들일 수 가 없다.
wait_timeout : connection이 비활성 상태일 때 다시 요청이 오기까지 얼마의 시간을 기다린 뒤에 close할 것인지를 결정한다.
비정상적으로 connection이 종료되고, connection을 사용 후 반환이 안되거나 네트워크가 단절된 경우 데이터베이스에서 connection을 관리할 수가 없다.
계속해서 open되어 있는 커넥션이 반환도 안되고, 데이터베이스 측에서 TCP로 연결되어있고 백엔드 서버로 부터 요청을 기다린다.
종료도 안되는 경우 어느 정도의 시간이 지난 후 자동적으로 connection을 close하기 위한 time설정
마지막으로 백엔드 서버로부터 요청을 받은 시간을 계산하여 백엔드 서버로 부터 요청을 받지 못하면 일정 시간 이후 커넥션을 close한다.
만약, wait_timeout 시간내에 백엔드 서버로부터 요청이 도착하면 0으로 초기화된다.
minimumIdle : pool에서 유지하는 최소한의 idle connection 수
maximumPoolSize : pool이 가질 수 있는 최대 connection 수
idle 커넥션 갯수 + active 커넥션의 최대 갯수
idle == inactive, active == in-use(히카리 기준)
idle 상태인 커넥션 수가 minimumIdle 수보다 작고, 전체 커넥션 수도 maximumPoolSize보다 작다면 추가적으로 connection을 만든다.
커넥션 풀에 커넥션이 2개가 있는 상황에서 요청이 생겨 커넥션 1개가 생겼을 경우 idle 커넥션 갯수는 1개가 된다. 따라서, 커넥션을 추가적으로 생성하고 idle 커넥션 갯수를 2개로 맞추고, 총 커넥션 갯수는 3개가된다.
만약 커넥션이 4개이고, 모든 커넥션이 사용자의 요청을 처리하는 경우에는 maximumPoolSize는 4이기 때문에 커넥션을 추가할 수가 없다.
권장사항 : 히카리 CP에서는 minimumIdle의 수와 maximumPoolSize의 수를 동일하게 하도록 권장한다. pool size가 고정되고, 사용자의 요청이 몰려와도 추가적으로 connection을 생성하지 않고, idle상태인 커넥션을 사용하도록한다.
maxLifetime : pool에서 connection의 최대 수명. maxLifetime을 넘기면 idle일 경우 pool에서 바로 제거, active인 경우 pool로 반환된 후 제거된다.
제거된 connection을 대체하기 위해 백엔드 서버와 데이터 베이스 서버는 새롭게 connection을 생성하고 open한다.
만약 데이터베이스 서버에서 사용되던 connection이 pool로 반환되지 않으면 active상태로 판단하기 때문에 반환될 때까지 제거되지 않는다.
데이터베이스 서버에서는 wait_timeout 기다리다가, 사용자의 요청이 오지 않으면 연결을 끊어버리고, 백엔드 서버가 연결이 끊어진 커넥션을 사용할 경우 Exception이 발생한다.
maxLifetime을 wait_timeout보다 몇초 정도 짧게 설정해야한다.
백엔드 서버와 통신 중 데이터베이스 서버로 커넥션을 사용하여 요청을 보내려고 할때 wait_timeout이 지나 데이터베이스 서버에서 커넥션을 close할 수도 있다.
백엔드 서버에서 CP로 부터 커넥션을 받기위해 대기하는 시간
만약 시간내에 CP에서 커넥션을 얻지 못한경우 Exception 발생
사용자가 29초까지 기다리다가 연결을 끊어버리는 경우 비용 낭비가 생길 수 있다. 따라서, connectionTimeout을 적절하게 설정해야한다.
주로 데이터베이스 서버를 고가용성(High availability)을 보장하기 위해 replication하여 사용한다. primary server는 read-write가 가능하며, secondary server들은 read만 가능하다.
request per second : 1초에 request(요청)을 얼마나 처리할 수 있는가
avg response time : 평균 응답 시간
트래픽이 많이 발생할 수록 1초에 처리할 수 있는 요청의 갯수가 증가되지 않고, 평균 응답시간도 늘어나는 경우 해당 시점을 모니터링 한다.
백엔드 서버의 CPU,메모리 사용률이 높은 경우 백엔드 서버를 증설한다.(코드적으로 해결이 안되는 경우)
하지만, 백엔드 서버 사용률은 정상이고, DB 서버의 CPU 사용률이 높은경우 replication, cache, sharding등을 이용할 수 있다.
하나의 요청마다 쓰레드 1개를 사용하는 경우. 쓰레드 병목현상이 발생할 수 있다. 쓰레드 풀에 쓰레드 갯수가 5개이고 사용되는 쓰레드가 5개인경우 쓰레드를 증가 시키는 방법도 있을것이다.
쓰레드 풀은 100개이고, active 쓰레드가 50개인 경우 쓰레드 병목현상은 발생하지 않지만, 성능이 안나오는 경우 connection 수를 확인한다.