JDBC Connection Pool
데이터베이스와 애플리케이션을 효율적으로 연결하기 위해,
동시 접속자가 가질 수 있는 Connection을 하나로 모아놓고 관리한다
Pool에 사용할 수 있는 Connection을 생성해놓고 Connection이 필요할 때마다 제공하여, Conneciton 생성/닫기 하는 시간 소비를 줄이고, 계속 재사용이 가능하기 때문에 애플리케이션의 속도 향상을 기대할 수 있으며, 동시 접속자(Connection 요청)도 제어할 수 있어 애플리케이션의 과부하를 막아 쉽게 다운되지 않는다.
HikariCP
"This is a very lightweight (at roughly 130Kb) and lightning fast JDBC connection pooling framework"
DB 연결을 위해 JDBC Connection Pool을 사용하는데, Spring boot 2.0 버전 이후는 HikariCP로 Default가 변경되었다.
하기 그림은 HikariCP 와 기타 connection pool (c3p0, dbcp2, tomcat, vibur)을 벤치마킹한 그래프이다.
“zero-overhead”라고 말할 정도로 가볍고 빠르다고 소개하고 있다.
brettwooldridge github에 직접 성능을 테스트할 수 있도록 벤치마킹한 소스도 함께 첨부되어 있다.
그래프를 대충 보아도 spring boot 2.x 버전부터 기본으로 HikariCP를 포함하였는지 알 수 있다.
필자가 개발 중인 maven java project의 Hibernate로 구현되어 있는 프로젝트가 대량 DB 조회가 필요하여 HikariCP를 직접 설정해보려고 한다.
hibernate 설정 후 별도의 CP를 설정하지 않아 hibernate의 기본 내장 CP를 사용하고 있었다.
간단하게 hikariCP를 설정해보자.
1. hibernate hikariCP maven install
먼저 hibernate 용 hikariCP를 import 한다.
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-hikaricp -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-hikaricp</artifactId>
<version>5.4.10.Final</version>
</dependency>
2. hibernate.cfg.xml 설정 변경
hibernate 설정파일의 기본 datasource로 연결된 부분에 hikariCP를 적용해주자.
1) 기본 hibernate 설정
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
<property name="connection.username">userId</property>
<property name="connection.password">password</property>
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
...
<property name="show_sql">false</property>
<mapping class="entity class path" />
...
</session-factory>
</hibernate-configuration>
2) hikariCP 설정
<hibernate-configuration>
<session-factory>
<property name="connection.provider_class">com.zaxxer.hikari.hibernate.HikariConnectionProvider</property>
<property name="hikari.minimumIdle">5</property>
<property name="hikari.maximumPoolSize">10</property>
<property name="hikari.idleTimeout">30000</property>
<!--<property name="hikari.dataSourceClassName">oracle.jdbc.driver.OracleDriver</property>-->
<property name="hikari.dataSourceClassName">oracle.jdbc.pool.OracleDataSource</property>
<property name="hikari.dataSource.url">jdbc:oracle:thin:@121.167.147.13:1521:orcl</property>
<property name="hikari.dataSource.user">userid</property>
<property name="hikari.dataSource.password">passwrd</property>
...
</session-factory>
</hibernate-configuration>
hikariCP 처음 설정시 주석 처리된 부분(기존 data source 설정 값)으로 잘못 설정하니 다음과 같은 에러가 발생했으니 주의하자.
Caused by: org.hibernate.HibernateException: java.lang.RuntimeException: java.lang.ClassCastException: Cannot cast oracle.jdbc.driver.OracleDriver to javax.sql.DataSource
at com.zaxxer.hikari.hibernate.HikariConnectionProvider.configure(HikariConnectionProvider.java:91)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:107)
...
올바르게 수정 후 DB Connection을 진행하니 출력된 console log
HikariCP에서 사용되는 class name은 하기와 같이 설정해야 한다.
default는 none이다.
Database | Driver | DataSource class |
Apache Derby | Derby | org.apache.derby.jdbc.ClientDataSource |
Firebird | Jaybird | org.firebirdsql.ds.FBSimpleDataSource |
H2 | H2 | org.h2.jdbcx.JdbcDataSource |
HSQLDB | HSQLDB | org.hsqldb.jdbc.JDBCDataSource |
IBM DB2 | IBM JCC | com.ibm.db2.jcc.DB2SimpleDataSource |
IBM Informix | IBM Informix | com.informix.jdbcx.IfxDataSource |
MS SQL Server | Microsoft | com.microsoft.sqlserver.jdbc.SQLServerDataSource |
Connector/J | ||
MariaDB | MariaDB | org.mariadb.jdbc.MariaDbDataSource |
Oracle | Oracle | oracle.jdbc.pool.OracleDataSource |
OrientDB | OrientDB | com.orientechnologies.orient.jdbc.OrientDataSource |
PostgreSQL | pgjdbc-ng | com.impossibl.postgres.jdbc.PGDataSource |
PostgreSQL | PostgreSQL | org.postgresql.ds.PGSimpleDataSource |
SAP MaxDB | SAP | com.sap.dbtech.jdbc.DriverSapDB |
SQLite | xerial | org.sqlite.SQLiteDataSource |
SyBase | jConnect | com.sybase.jdbc4.jdbc.SybDataSource |
필자와 같이 configuration file base가 아니라면 하기와 같이 configruation class 구현하여 data source를 handling 하면 된다.
HikariConfig.class
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/db");
config.setUsername("userId");
config.setPassword("password");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
...
HikariDataSource ds = new HikariDataSource(config);