DEV ℧ Developer Diary

[Java] Hikari CP에 대해 알아보자. (2)

HikariCP가 어떤것인지 간략하게 알았으니, 어떻게 사용하는지 알아보도록 하자.

HikariCP Config

HikariCP의 실행

HikariCP는 Spring boot 2.0 이상에는 기본적으로 탑재되어 있어, Application을 실행 시킬경우 실행 로그가 출력되는것을 확인 할 수 있다.

2022-12-19_23:05:48.854 INFO  o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 9 ms. Found 0 Redis repository interfaces.
2022-12-19_23:05:49.364 INFO  o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)
2022-12-19_23:05:49.372 INFO  o.a.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]
2022-12-19_23:05:49.373 INFO  o.a.catalina.core.StandardService - Starting service [Tomcat]
2022-12-19_23:05:49.373 INFO  o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.63]
2022-12-19_23:05:49.599 INFO  o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2022-12-19_23:05:49.600 INFO  o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 1706 ms
2022-12-19_23:05:49.619 INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
2022-12-19_23:05:49.721 INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.

그래서 Spring Boot 2 이상의 환경에서는 application.properties 혹은 application.yml에서 설정을 추가하여 HikariCP를 쉽게 튜닝 할 수 있다.

필자는 yml을 사용하므로, Spring boot의 appliction.yml 기준으로 HikariCP의 주요 설정들을 알아보도록 하자.

HikariCP Config

자세한 내용은 HikariCP 공식 Document에서 확인이 가능하다.

Github-HikariCP Configuration

필수 설정

dataSourceClassName

JDBC 드라이버에서 제공하는 DataSource 클래스 이름을 설정한다. 몇가지 유명한 class name을 몇가지 적어보자면, 아래와 같다. (기본값 : 없음)

  • MySQL : com.mysql.cj.jdbc.Driver
  • MariaDB : org.mariadb.jdbc.MariaDbDataSource
  • PostgreSQL : org.postgresql.ds.PGSimpleDataSource
  • Oracle : oracle.jdbc.pool.OracleDataSource
  • H2 : org.h2.jdbcx.JdbcDataSource

jdbcUrl

dataSourceClassName 설정 대신 jdbc-url 설정을 통해 DB의 정보를 설정 해 줄 수있다. 둘중 하나를 선택해서 사용 가능 하다.

다중 DB설정을 해야하는 경우는 해당 설정을 사용하기도 한다.(기본값 : 없음)

username & password

해당 속성은 기본 드라이브에서 연결을 가져올 때 사용되는 기본 인증 사용자 이름과, 인증 암호를 설정한다. (기본값 : 없음)

자주 사용되는 설정

아래의 속성들은 자주 사용되고, 설정 값에 따라 HikariCP의 성능에 크게 영향을 끼친다. 잘못 설정할 경우 DeadLock에 걸릴 수 있으니 알아보고 설정하도록 하자. (사실 이렇게 겁줄 정도는 아니다 ㅎㅎ)

autoCommit

Connection pool의 auto commit 여부를 설정한다. (기본값 : true)

connectionTimeout

connectionTimeout 속성은 클라이언트에서 요청시 유후 Connection이 Connection Pool에 없을 경우 Connection의 연결을 기다리는 시간을 설정한다.

예를 들어 30초(30000ms)를 설정했다면 유후 Connection이 없을시 설정한 30초까지 대기를 하고, 이후에도 Connection을 획득할 수 없을시 SQLException을 발생시킨다. 최소 값은 250ms 이다. (기본값 30000(30초))

maximumPoolSize

maximumPoolSize 속성은 앞서 설명한 HikariCP가 Connection Pool에서 가질 수 있는 최대 Connection 수(유후 Connection + 사용중 Connection)를 설정하는 설정이다. 해당 값의 설정으로, 데이터베이스와 백엔드간의 실제 연결 최대수를 결정 할 수 있다.

정말 중요한 설정이며, 해당 Pool Size를 지정하는 것은 공식이 있는데, 아래의 링크에서 자세히 확인할 수 있다. (기본값 : 10)

Github-HikariCP About-Pool-Sizing

minimumIdle

minimumIdle 속성은 HikariCP가 풀에서 유지하려는 최소 유휴 Connection 수를 제어한다. 유후 Connection 값과, Pool 내부의 Connection 연결 수가 해당 설정값보다 아래가 된다면 빠르게 Connection을 추가하여 최소 수를 유지한다.

최적의 성능을 요구한다면 이 값은 따로 설정하지 않아도 된다. 값을 따로 설정하지 않을 경우 maximumPoolSize와 동일한 값을 같는다. (기본값 : maximumPoolSize 설정값)

idleTimeout

idleTimeout 속성은 Connection이 유후 상태로 있을 수 있는 최대 시간을 설정한다. 유휴 Connection이 해당 설정의 시간을 넘을 경우 Connection을 해제한다.

그러다보니, 해당 설정을 사용하기 위해서는 조건이 붙는데 minimumIdle의 값을 maximumPoolSize 값보다 낮게 설정하여 Connection의 수를 조절 할 경우 사용 할 수 있는 조건이다. (기본값 : 600000 (10분))

maxLifetime

maxLifetime 속성은 Connection Pool에서 Connection의 최대 수명을 제어합니다.만약 active상태에 들어간 Connection은 절대 폐기되지 않지만, Closing 될경우 Connection이 제거된다.

대량으로 Connection이 사라지는 것을 막기 위해 Connection별로 수명을 매긴다.

해당 값은 연결 시간 제한이 있는 데이터베이스 또는 인프라보다는 몇 초 더 짧아야 한다. 결국 Connection이란 것은 DB의 Connection을 따라가기에 암만 해당 설정을 길게 설정하여도 DB의 Connection 연결시간(예를 들면 MySql의 wait_timeout)이 더 짧다면 적용되지 않는다.

해당 값에 대해 몇가지 예시가 있는데, MySql의 wait_timeout 시간 설정이 30초, HikariCP의 maxLifetime 설정을 40초로 설정한 적이 있다. 서버가 가동하면서 문제가 생기지는 않았지만 아래와 같은 문구가 계속 출력이 되었다.

2022-XX-XX XX:XX:XX.XXX  WARN 12212 --- [n(4)-10.20.2.28] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Failed to validate connection com.mysql.jdbc.JDBC4ReplicationMySQLConnection@1486b850
(Communications link failure The last packet successfully received from the server was 23,137 milliseconds ago.  The last packet sent successfully to the server was 0 milliseconds ago.).
Possibly consider using a shorter maxLifetime value.

해당 이슈가 발생되어 찾아보니, MySql의 wait_timeout이 HikariCP의 maxLifetime 설정보다 짧다보니, 40초가 지난 이후에 Connection을 닫으려보니, 이미 MySql이 Connection을 반납해버려서 저런 로그가 출력 되던 것이었다.

poolName

poolName 속성은 HikariCP의 로그출력시 이름을 지정해 줄 수 있다.

만약 test-pool의 이름으로 설정한다면 아래와 같이 출력 된다.

2022-12-20 23:01:21.889  INFO 19772 --- [           main] com.zaxxer.hikari.HikariDataSource       : test-pool - Starting...
2022-12-20 23:01:21.951 DEBUG 19772 --- [           main] com.zaxxer.hikari.pool.HikariPool        : test-pool - Added connection conn0: url=jdbc:h2:mem:testdb user=SA
2022-12-20 23:01:21.951  INFO 19772 --- [           main] com.zaxxer.hikari.HikariDataSource       : test-pool - Start completed.

정리

이렇게 HikariCP에 대해 간단하게 정리해보았다.

마침 오늘 회사에서 동일한 이슈가 발생되어 다같이 원인을 찾고 이슈체킹을 하였는데, HikariCP의 문제는 크게 아니었고 다른것이 원인이었다.. 그래도 공부가 된것같아, 만족스럽다. 다음엔 회사에서 발생한 이슈를 중심으로 포스팅을 진행하고자 한다.