728x90

connection pool 이란?

client 에서 요청이 올때마다 매번 connection 을 맺게 되면 TCP/IP 의 3way handshake 가 발생하게 되고 

그만큼 client 에게 응답이 늦어지므로 사용자의 편의성이 하락 할 수 있다.

 

그리고 Database 의 connection 이 무한하게 증가 함으로 그다지 좋은 방법은 아니라 실무에서는 필수적으로 Connection Pool 을 사용하여 Database 를 사용한다.

 

 

Spring boot 2.0 의 Connection Pool

 

spring boot 2.0 에서는 connection pool 의 기본을 hikaricp 를 사용하도록 되어 있다.

 

hikaricp 가 궁금하시다면 밑에 링크를 참조하자

GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last.

 

GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last.

光 HikariCP・A solid, high-performance, JDBC connection pool at last. - GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last.

github.com

 

 

DriverManger Connection

 

기존에 Java 에서 Database 와 Connection 을 맺으려면 DriverManger 를 통해서 connection 해야 했다.

@Test
void driverManger() throws SQLException {
    Connection connection1 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    Connection connection2 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    log.info("connection = {}, class = {}", connection1, connection1.getClass());
    log.info("connection = {}, class = {}", connection2, connection2.getClass());
}

 

하지만 DriverManger 를 사용하여 connection 을 하게되면 위에서 말했던 문제점 들이 발생하고 

유지보수 측면에서도 설정과 사용이 분리 되지 않아 썩 좋은 코드는 아니다.

 

 

설정과 사용의 분리

@Test
void dataSourceDriverManger() throws SQLException {
    // DriverMangerDataSource - 항상 새로운 커넥션을 획득
    DataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
    useDateSource(dataSource);
}

private void useDateSource(DataSource dataSource) throws SQLException {
    Connection connection1 = dataSource.getConnection();
    Connection connection2 = dataSource.getConnection();
    log.info("connection = {}, class = {}", connection1, connection1.getClass());
    log.info("connection = {}, class = {}", connection2, connection2.getClass());
}

 

DriverMangerDataSource 를 사용하여 설정을 하고 따로 method 를 만들어 사용을 분리하였다.

DriverMangerDataSource 는 내부적으로 DataSource 를 구현하고 있는 구현체 이다.

 

하지만 위와 같은 코드도 client 에서 여러 요청이 왔을때 매번 connection 을 맺기 때문에 위와 같은 문제를 해결 하지 못했다.

 

Connection Pool 만들어 사용하기

@Test
void dataSourceConnectionPool() throws SQLException, InterruptedException {
    // connection pooling
    HikariDataSource hikariDataSource = new HikariDataSource();
    hikariDataSource.setJdbcUrl(URL);
    hikariDataSource.setUsername(USERNAME);
    hikariDataSource.setPassword(PASSWORD);
    hikariDataSource.setMaximumPoolSize(10); // Default 10
    hikariDataSource.setPoolName("MyPool");

    useDateSource(hikariDataSource);
    /**
     * pool 을 추가하는 과정은 application 에 영향을 주지 않도록 하기 위해서
     * 별도의 thread 를 사용하여 추가한다.
     * 이 과정에 있어서 sleep 1000 을 주석 처리 하게 되면 10개의 pool 이 다 생성되기도 전에 test code 가 끝날 가능성이 있다.
     */
    Thread.sleep(1000);
}

private void useDateSource(DataSource dataSource) throws SQLException {
    Connection connection1 = dataSource.getConnection();
    Connection connection2 = dataSource.getConnection();
    log.info("connection = {}, class = {}", connection1, connection1.getClass());
    log.info("connection = {}, class = {}", connection2, connection2.getClass());
}

 

Datasource 를 구현한 HikariDataSource 를 사용하여 Pool 을 10 개를 생성하고 connection 을 맺을때 미리 생성해둔 pool 에서 connection 을 가져와 데이터베이스와 연결을 맺고 사용이 끝나면 반납하는 형식으로 코드를 작성하였다.

 

하지만 요기서 몇가지 주의해야 할 점이 있는데 pool 을 생성하고 추가하는 과정은 비용이 저렴하지 않으므로

application 을 실행에 영향을 주지 않도록 하기 위해 별도의 thread를 사용하여 생성 및 추가한다.

 

이 과정에 있어서 Tread.sleep(1000) 이란 코드가 없다면 10개를 생성 및 추가 하기전에 test code 가 끝나는걸 볼 수 있다.

 

그리고 2번째 주의사항은 connection 이 10개 가 넘어버린다면 ? 어떻게 될까

 

정답은 hikaricp 에서 기본적으로 30초 이상 응답이 지연시 강제로 connection 을 끊어버린다.

실무에서 는 좀더 짧은 시간을 가지는게 사용자 편의를 위해 좋을 것 같다.

 

728x90