-
Hikari CP 설정 알아보기📖 개발 공부 2024. 11. 24. 21:07
최근 회사에서 DB 관련한 이슈가 꽤 발생했었다.
- "Unable to acquire JDBC Connection 에러 발생"
- "연결된 connection 수가 예상보다 2배 많은 상황"
- "slow query가 잡혀서 error가 튀는 상황"
- …
위 이슈들을 대응하면서, HikariCP의 동작 원리와 설정값들을 충분히 이해하고 있어야만 이슈 파악에 도움이 될 것이라는 생각이 들었다.
그래서 이번 기회에 HikariCP에 대해 정리해려고 한다!
Connection Pool
커넥션 풀(Connection Pool)은 데이터베이스와의 연결을 미리 생성해 두고, 필요할 때마다 이를 재사용하는 방식으로 성능을 최적화하는 기술이다. 커넥션을 매번 새로 생성하는 것은 시간이 많이 걸리고 리소스를 낭비할 수 있다. 커넥션 풀은 애플리케이션 실행 시점에 미리 커넥션을 생성해 두고, 필요할 때마다 이를 재사용하기 때문에 효율적으로 리소스를 관리할 수 있다.
커넥션풀은 다음과 같은 동작을 한다.
- 커넥션 생성 및 초기화 : 미리 설정된 최소 연결 수만큼의 DB 연결을 미리 초기화하고, 풀에 저장한다.
- 커넥션 제공 : 애플리케이션이 DB에 커넥션이 필요한 경우, 미리 생성된 CP에서 사용 가능한 커넥션을 제공한다.
- 연결 사용: 제공된 커넥션을 사용하여 데이터베이스 작업을 수행한다.
- 연결 반납: DB 작업이 끝난 후, 사용한 연결을 풀에 반납한다.
- CP 관리: CP는 최소 연결 수를 유지하며, 필요에 따라 동적으로 연결을 추가하거나 해제하여 최적의 성능을 유지한다.
Hikari CP
자바에서는 기본적으로 DataSource 인터페이스를 사용하여 커넥션 풀을 관리한다. Spring에서는 개발자가 직접 커넥션을 관리할 필요 없이, 자동으로 커넥션 풀을 관리할 수 있도록 다양한 라이브러리(예: HikariCP, Tomcat JDBC Pool 등)를 제공한다.
Spring Boot 2.0 이상부터는 기본 커넥션 풀로 Hikari CP가 사용된다. Hikari CP는 고성능의 경량화된 커넥션 풀 라이브러리로, JDBC 연결 풀링을 최적화하여 높은 성능을 제공한다.
Hikari CP는 다양한 설정 옵션을 제공하여 개발자가 애플리케이션의 요구사항에 맞게 커넥션 풀을 최적화할 수 있다.
- connectionTimeout
- idleTimeout
- keepAliveTime
- maxLifetime
- …
이는 다음과 같이 설정 파일을 통해서 옵션들을 관리할 수 있다.
datasource: url: ${DB_URL} username: ${DB_USERNAME} password: ${DB_PASSWORD} hikari: maximum-pool-size: 50 connection-timeout: 1000 ...
이번에 나는 DB 관련한 여러 이슈들을 대응하면서 Hikari 설정 옵션들을 조정해보았다.
이 설정값들에 대해 충분히 이해하고 있어야만 향후 발생할 수 있는 이슈에 대해 어떤 설정을 변경해야 할지 잘 판단할 수 있을 것이라고 생각했다. 그래서 Hikari 설정 옵션들을 정리해보려고 한다.
Hikari CP 설정
connectionTimeout
이 속성은 클라이언트가 풀에서 연결을 기다리는 시간을 제어한다. 연결이 사용 가능하지 않은 채 이 시간을 초과하면 SQLException이 발생한다.
(Lowest acceptable connection timeout is 250 ms. Default: 30000 (30 seconds))"Unable to acquire JDBC Connection 에러 발생"
우리 프로젝트에서는 기존에 connectionTimeout 값을 별도로 설정하지 않았기 때문에, 커넥션이 부족한 상황에서 클라이언트는 연결을 얻기 위해 최대 30초 동안 대기했다. 이로 인해 스레드가 길게 점유되었고, 그 결과 다른 요청을 처리할 수 없는 상태가 발생했다.
이러한 문제로 인해 응답이 느려지면서 서버 재시작을 반복하는 현상이 발생했다.
따라서 우리 팀은 connection timeout을 1초로 설정하여서 커넥션을 얻지 못하는 경우 빠르게 실패하도록 처리했다.maximumPoolSize
maximumPoolSize는 유휴 커넥션과 활성 커넥션을 모두 포함하여, 풀이 도달할 수 있는 최대 크기를 제어하는 속성이다. 풀이 maximumPoolSize만큼 도달하고, 유휴 커넥션이 없으면 connectionTimeout 시간까지 기다려도 커넥션을 받지 못하면 예외가 발생한다.
(Default: 10)
minimumIdle
이 속성은 풀에서 유지하려고 시도하는 최소 유휴 연결 수를 설정하는 속성이다. 커넥션 풀은 이 개수만큼의 유휴 커넥션을 유지하려고 한다. 유휴 커넥션이 minimumIdle 아래로 떨어지고, 풀의 총 커넥션수가 maximumPoolSize보다 작으면 HikariCP는 추가 커넥션을 추가하려고 한다.
(Default: maximumPoolSize와 같다.)
"minimumIdle = maximumPoolSize"
우리 프로젝트에서는 minimumIdle, maximumPoolSize 값을 각각 환경변수로 관리하고 있었다. 그러다보니 pool size를 변경하려고 할 때, minIdle 값의 변경 없이 maximumPoolSize 값만 올리는 경우가 발생했다.
이렇게 maximumPoolSize와 값을 다르게 설정하면 다음과 같은 문제점이 발생할 수 있다. 이 경우에 대기 중인 유휴 커넥션이 적어져 트래픽이 몰릴 경우, 즉시 사용할 수 있는 연결이 부족해져 새로운 커넥션을 생성해야 하는 상황이 발생할 수 있다. 이로 인해 커넥션 생성에 시간이 소요되며 성능 저하가 발생할 수 있다. 그래서 풀 크기를 늘릴 때는 minIdle도 적절히 증가시켜, 유휴 커넥션을 충분히 확보한 상태에서 트래픽 급증에 대응할 수 있도록 관리하는 것이 중요하다.
이 설정으로 인한 이상현상이 나타나진 않았지만,
각 옵션들에 대해 알아보는 중에 minimumIdle과 maximumPoolSize를 같게 권장하는 이유를 알 수 있었다.idleTimeout
이 속성은 연결이 풀에서 유휴 상태로 유지될 수 있는 최대 시간을 제어한다. 이는 minimumIdle이 maximumPoolSize보다 작은 경우에만 적용된다.
(Default: 600000 (10 minutes))maxLifetime
풀에 있는 커넥션의 최대 수명을 제어한다. maxLifetime에 설정한 시간이 지나면 커넥션을 재연결한다. 활성 커넥션은 절대 폐기되지 않고, 종료된 후에만 제거된다. 이는 DB의 wait timeout보다 짧게 유지하는 것을 권장한다.
(The minimum allowed value is 30000ms (30 seconds). Default: 1800000 (30 minutes))
Hikari CP 관련 이슈들을 접할 때마다, 이 글을 계속 업데이트하려고 한다.!
참고
반응형'📖 개발 공부' 카테고리의 다른 글
Spring 트랜잭션 롤백 관리: rollback-only 이슈 분석과 해결 (3) 2024.11.10 The SAGA Pattern (0) 2024.09.29 Toss | 서버 증설 없이 처리하는 대규모 트래픽 (0) 2024.07.27 system-design-101. CAP 이론 (CAP theorem) (2) 2024.07.14 system-design-101. How to improve API performance? (0) 2024.06.22