원인 : 스프링 프레임워크와 MySQL 사용시 특정 시간이 지나면 자동으로 커넥션을 잃어버리는 문제가 있다. 오랜시간 아무런 데이터 요청이 없으면 커넥션과 풀링을 해지하는 기능을 가지고 있기때문에 발생한다.
커넥션 풀이란?
커넥션 풀 이란 ?
→ 클라이언트 요청이 오면 connection을 빌려주고, 처리가 끝나면 다시 connection을 반납받아 pool에 저장하는 방식
- 그때그때 연결을 하게되면 시간이 소요되고 (2-3초) 컴퓨터내에서 다시붙는 시간은 굉장히 오래걸리는 시간이기때문에 미리 커넥션 풀을 여러개 만들어놓고 사용하고 반납하는 식으로 사용
Pooling 기법이란 ?
미리 데이터베이스 Connection을 여러 개 만들어서 특정 공간에 저장해 놓고, 여러 사용자가 필요할 때 마다 하나씩 꺼내서 사용하고 다시 집어 넣는 방식
지금까지는 JDBC에서 Connection이 필요할 때마다 생성하고, 직접 종료 시켜야 했습니다. 하지만 Connection Pooling 기법에서는 Connection Pool이라는 커넥션 관리자가 연결과 해제를 직접 관리
* Pooling 기법
1. Connection을 생성해서 보관
2. Connection에 대한 요청이 들어오면, 보관중인 Connection중 하나를 넘겨줌
3. 사용이 끝난 Connection을 다시 보관
* Connection Pooling의 장점
1. 속도향상
2. 자원공유
3. Connection객체 제어
====
Hikari - 데이터베이스와의 Connection Pool을 관리
HikariCP는 요청이 들어오면 Thread가 커넥션을 요청하고, Hikari는 Pool내에 있는 커넥션을 연결
HikariCP
- Database와 의존 관계를 분리하였기에, 지속적으로 유효성을 체크하지 않아도 되며, 내부적으로 커넥션이 58초가 되었는지 계산하면 된다.
- max-lifetime값은 네트워크 지연 등을 포함하여 2~3초간의 시간을 뺀 58초 정도로 설정, HikariCP의 ThreadLocal 내부에서 커넥션 유지 시간을 계산한다.
- max_lifetime을 Database의 wait_timeout보다 30초 이상 짧게 주라는 것은 잘못 되었다. 공식 문서 업데이트를 진행하지 않은 것이다.
-
HikariCP는 커넥션 풀을 관리하기 위해 HouseKeeper라는 Thread가 30초마다 돌고 있다.
- HouseKeeper가 30초마다 돌며 커넥션을 종료하였기에, 이전 29.xx초까지의 커넥션들에 대해 유효성 체크가 누락될 수 있어서 30초의 여유를 준 것이다.
- 현재 방식은, ThreadLocal에서 각각 타이머를 통해 max-lifetime에 도달했는지 체크를 하는 방식으로 변경되었다.
HikariCP property
- connectionTimeout(default: 30000 - 30 seconds)
connection 연결시도시 timeout out값을 설정합니다. 이 시간내로 connection을 연결하는데 실패하면 SQLException을 발생합니다.
- idleTimeout(default : 600000 - 10 minutes)
connection Pool에 의하여 확보된 connection의 maximum idle time을 결정합니다. connection Pool에 의하여 확보된 connection이 사용되지 않고, Pool에 의해서만 이 시간동안 관리된 경우, connection을 DB에 반환하게 됩니다. 값을 0으로 설정하는 경우, 확보된 connection을 절대 반환하지 않습니다
- maxLifetime(default : 1800000 - 30 minutes)
connection Pool에 의하여 확보된 connection의 최대 생명주기를 지정합니다. connection을 얻어낸지, 이 시간이상되면 최근에 사용하고 있던 connection일지라도, connection을 close시킵니다. 사용중에 있던 connection은 close 시키지 않습니다. (사용이 마쳐지면 바로 close 됩니다.) HikariCP에서는 이 값을 30~60 minutes 사이의 값을 설정하라고 강력권고합니다. 값을 0로 설정하는 경우 lifetime은 무제한이 됩니다.
- leakDetectionThreshold (default : 0)
connectionPool에서 반환된 connection의 올바른 반환이 이루어졌는지를 확인하는 thread의 갯수를 지정합니다. 이 값을 0로 지정하는 경우, leak detection을 disable 시키게 됩니다. 만약에 또다른 connection pool을 사용하고 있다면, 다른 connection pool에서 만들어진 connection을 leak으로 판단하고 connection을 닫아버릴 수 있습니다.
- minimumIdle (default : maximumPoolSize)
connection Pool에서 유지할 최소한의 connection 갯수를 지정합니다. HikariCP에서는 최고의 performance를 위해 maximumPoolSize와 minimumIdle값을 같은 값으로 지정해서 connection Pool의 크기를 fix하는 것을 강력하게 권장합니다.
- maximumPoolSize
connection Pool에서 사용할 최대 connection 갯수를 지정합니다. 이 부분은 운영환경과 개발환경에 매우 밀접하게 연결되는 부분으로, 많은 테스트 및 운영이 필요합니다.
Timeout
- connect_timeout
이 설정은 mysqld 와 mysql client 가 연결(connection)을 맺기 위해서 mysqld 가 연결 패킷을 기다리는 최대 시간입니다. 즉 TCP 연결을 맺는 과정(3-way handshake)에서, connect_timeout 동안에도 연결 패킷이 들어오지 않으면 연결이 실패(취소가 아님)되고, bad handshake 로 응답합니다.
- interactive_timeout
interactive 모드에서 time out 을 말합니다. interactive 모드는 'mysql>' 과 같은 프롬프트 있는 콘솔이나 터미널 모드를 말합니다. mysqld 와 mysql client 가 연결을 맺은 다음, 다음 쿼리까지 기다리는 최대 시간을 의미합니다. 설정된 interactive_timeout 까지도 아무런 요청(쿼리)이 없으면 연결은 취소되고, 그 이후에 다시 요청이 들어오면 연결은 자동으로 맺어집니다. interactive_timeout 안에 다시 요청이 들어오면 wait time은 0으로 초기화 됩니다(CLIENT_INTERACTIVE).
- wait_timeout
interactive 모드가 아닌 경우에 해당되며, mysqld 와 mysql client 가 연결을 맺은 후, 다음 쿼리까지 기다리는 최대 시간을 의미합니다.
interactive_timeout 과 마찬가지로 wait_timeout 까지 아무런 요청(쿼리)이 없으면 연결은 취소되고 그 결과는 Aborted_clients 에 누계됩니다. wait_timeout 안에 다시 요청이 들어오면 wait time 은 0 으로 초기화 됩니다.
커넥션 풀 찍는 로그
<logger name="com.zaxxer.hikari.pool.HikariPool" level="DEBUG"/>
'SpringBoot' 카테고리의 다른 글
[Java] @Deprecated (0) | 2020.10.27 |
---|---|
QueryDSL like, contains (0) | 2020.10.27 |
[Intellij] test events were not received (0) | 2020.08.10 |
[Intellij] 디버깅이 너무 오래걸릴때 해결 방법 (1) | 2020.08.10 |
DataSource (0) | 2020.07.30 |