Connection Pool
。DB Connection의재사용을 위해 저장 및 관리하는 저장공간
▶Spring에서HikariCP가Connection Pool로서 기능
。Connection Pool은어플리케이션 생애주기간 오직 한 개만 생성되어 관리되어야한다.
▶Connection Pool을중복으로 생성 시DB Connection 객체 수가 중복을 통해 과도하게 많아지므로Connection Pool은 하나로만 관리
。Connection Pool내DB Connection 객체는유휴 상태로 저장 및 필요 시 제공
▶ 제공된Connection객체.close()된 경우Connection Pool로 반납
。저장중인DB Connection 객체의유휴시간이 경과된 경우종료후재시작
。보통10개 안팎의Connection을 생성 및 관리
▶DB Connection 객체수가 과도하게 많아질수록DB가 감당이 불가능
Connection Pool을 사용하는 이유?
。매 요청마다 DriverManager.getConnection()을 통해 즉석에서DB Connection생성 시SQL문 실행 시간보다 TCP Transaction에 의한DB Connection 연결 시간이 더욱 많이 소요되는 단점이 존재
▶어플리케이션 구동동안 다수의DB 연결이 수행되므로요청시 즉석에서DB Connection을 각각 생성하는 경우성능에 매우 치명적으로 작용
。주휴:어플리케이션 실행 시점에서 일정 갯수의Connection을 생성하여Connection Pool에 저장 및필요시 즉시 제공함으로써실행 시간을 단축
▶DB Connection 객체의재사용을 통해DB 연결비용을 최소화
Connection Pool당 권장하는DB Connection 수
。HikariCP공식문서 상( CPU 코어 수 * 2 ) + 유효 디스크 스핀들 수를 권장
▶유효 디스크 스핀들 수 = ( SSD 코어수 * 2 + 1 )
DataSource:javax.sql.DataSource
。특정DBMS에 대한DB Connection을 생성 및 관리하는 역할을 수행하여Connection Pool에 대한표준을 제공하는인터페이스
▶JAVA 어플리케이션이DBMS에 접근 시DataSource를 통해 관리되는DB Connection을 제공받아서
。DB Connection을 관리하는 특성에 의해 최적화된Connection Pool기능을 제공할 수 있음.
▶HikariCP가DataSource를구현하여Connection Pool로서 기능
▶MyBatis에서도PooledDataSource라는 이름으로Connection Pool기능을 제공
Spring Boot에서Connection Pool활용
。Spring Boot의application.yml에서spring.datasource의 설정을 수행하는 경우, 해당 설정값을 기반으로DataSource 객체가 생성되어Spring Bean으로 등록
▶DataSource 구현체의 경우Hikari Connection Pool을 기반으로 생성됨.datasource: url: jdbc:h2:mem:test-db;MODE=MYSQL; username: sa password: driver-class-name: org.h2.Driver
▶application.yml의DataSource 설정을 기반으로HikariCP가 생성되어Spring Bean으로 등록
HikariCP( Hikari Connection Pool )
。Connection Pool을 관리하는DataSource 구현체 클래스
▶Spring Boot등 에서 기본적으로 활용
。HikariCP 객체생성 시java.sql.Connection과 동일하게사용자 접속 정보(=DB URL,사용자ID,사용자PW, DB드라이버)를 필요로 함.
HikariConfig
。생성할HikariCP 객체의설정 정보를 저장하는클래스
▶접속정보를 지정
。설정된 후new HikariDataSource(HikariConfig객체)를 통해HikariCP 객체생성
hikariConfig.setMaximumPoolSize(숫자):Connection Pool에 저장할최대 DB Connection 수
hikariConfig.setMinimumIdle(숫자):Connection Pool에 저장할최소 DB Connection 수
hikariConfig.setIdleTimeout(ms시간):Connection의유휴 유지 시간
hikariConfig.setMaxLifetime(ms시간):Connection의최대 생존 시간
HikariDataSource
。Connection Pool역할을 수행하는HikariCP 객체
▶HikariConfig의 설정을 기반으로 자동으로 설정된 수 만큼의Connection을 생성 및 준비
。어플리케이션 생애주기동안 오직 한개의객체만 생성되어 활용하도록 설정해야함.
HikariDataSource객체.getConnection(): 저장하고 있는DB Connection 객체를 가져와서 제공
HikariCP를 통해Connection Pool생성 및 활용 원리
MavenRepository에서 연결할DBMS의DB Driver랑HikariCP의의존성가져온 후build.gradle에 설정하기
주소implementation 'com.zaxxer:HikariCP:7.0.2' implementation 'com.mysql:mysql-connector-j:9.6.0'
Connection Pool생성 시 필요한접속정보정의
。DB URL,사용자ID,사용자PW, DB드라이버 경로 정의final String JDBC_URL = "jdbc:mysql://localhost:3306/jdbc_shop"; final String USER = "kf16"; final String PASSWORD = "wjd747"; final String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";▶
MySQL 드라이버(DBMS의JDBC 구현체)를 사용하도록External Libraries-MySQL디렉토리-com-mysql-cj-jdbc-Driver로디렉토리 경로로 지정
HikariConfig:hikariCP 접속 정보및세부 설정정의
。new HikariConfig()를 통해 생성 및 설정HikariConfig hikariConfig = new HikariConfig(); hikariConfig.setJdbcUrl(JDBC_URL); hikariConfig.setUsername(USER); hikariConfig.setPassword(PASSWORD); hikariConfig.setDriverClassName(DRIVER_CLASS_NAME); hikariConfig.setMaximumPoolSize(10); // Connection Pool에 저장할 최대 DB Connection 수 hikariConfig.setMinimumIdle(5); // Connection Pool에 저장할 최소 DB Connection 수 hikariConfig.setIdleTimeout(600000); // 유휴 유지 시간: 10분 hikariConfig.setMaxLifetime(1800000); // 최대 생존 시간: 30분
HikariConfig을 활용해HikariCP 객체생성HikariDataSource hikariCP = new HikariDataSource(hikariConfig);
Connection Pool을 단 한번만 생성하여 관리 및 제공하는Util역할의추상클래스정의하기
。Connection Pool은어플리케이션 생애주기간 오직 한 개만 생성되어 관리되므로, 추가적인Connection Pool의 생성을 차단해야함.public abstract class ConnectionPoolUtil { private static final String JDBC_URL = "jdbc:mysql://localhost:3306/jdbc_shop"; private static final String USER = "kf16"; private static final String PASSWORD = "wjd747"; private static final String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver"; private static final HikariDataSource hikariDataSource; static { HikariConfig hikariConfig = new HikariConfig(); hikariConfig.setJdbcUrl(JDBC_URL); hikariConfig.setUsername(USER); hikariConfig.setPassword(PASSWORD); hikariConfig.setDriverClassName(DRIVER_CLASS_NAME); hikariDataSource = new HikariDataSource(hikariConfig); } // Connection Pool 반환 메서드 public static DataSource getDataSource(){ return hikariDataSource; } // DB Connection 반환 메서드 public static Connection getConnection() throws SQLException { return hikariDataSource.getConnection(); } }。`HikariDataSource 객체`를 `static 필드`로 관리 및 `static 블록`으로 초기화 ▶ `어플리케이션 구동` 시점에서 `HEAP 영역` 상의 `추상클래스 프레임`에서 `생애주기` 상 오직 `한번`만 실행되어 초기화
Connection PoolVS즉석 DB Connection 생성
。HikariDataSource 객체에서DB Connection 객체를 가져온 후 활용 후 반납하는 과정을 50번 반복
▶ IntStream을 통해 반복 수행
。try~with문에 의해DB Connection 객체는 자동으로close()되어HikariDataSource로 반납final int MAX_REPEAT_COUNT = 50; // 실행시간 도출 long start = System.currentTimeMillis(); IntStream.rangeClosed(1, MAX_REPEAT_COUNT) // 1~ 50까지 배열 생성 .forEach( i -> { // try~with 구문을 통해 Util클래스에서 HikariDataSource 객체 가져옴 try ( Connection conn = ConnectionPoolUtil.getConnection() ) { conn.createStatement().execute("select 1"); // 단순 작업 } catch (Exception e) { throw new RuntimeException(e); } } ); long end = System.currentTimeMillis() - start; // DriverManager 방식( 4500ms )에 비해 매우 짧은 시간이 도출 System.out.println("%d번 연결 시 %d ms 만큼 시간 소요".formatted(MAX_REPEAT_COUNT, end));。
DriveManager에 의해 즉석에서DB Connection 연결을 생성 후 작업하는 과정을 50번 수행 시4.5초 경과
▶HikariCP에서 사전에 준비된DB Connection을 가져와서 재사용하는 과정을 50번 수행 시0.330초 경과로 단축
System.currentTimeMillis()
。현재 시스템 시간을msec으로 제공
▶완료시점코드 - 시작시점코드를 통해 해당코드의실행시간을 도출하여 성능 측정이 가능