반응형

Connection pool 이란?

Connection pooling 은 데이터 접근 패턴 중 하나로, 주 목적은 데이터베이스 접속하여 작업하는 데에 과부하를 줄이는 것이다. 사용자의 요청에 따라 Connection을 생성하다 보면 동시에 많은 수의 연결이 발생했을 때 서버에 과부하가 걸리게 된다. 이러한 상황을 방지하기 위해 미리 일정수의 Connection 을 만들어 pool에 담아 뒀다가 사용자의 요청이 발생하면 연결을 해주고 연결 종료 시 pool 에 다시 반환하여 보관하는 것이다.
DBMS로의 연결이 오래 걸리며 DB 작업을 할 때마다 Connection ~ Close 까지의 반복 작업이 비효율적이기 때문에 Connection pool에 Connection 객체를 생성해 놓고 DB 작업 시 pool에서 Connection을 빌려 사용 후 다시 반납하는 구조로 되어있다.
Connection Pool을 잘 사용하면 DB와 Application에서 발생하는 문제가 전체로 전파되지 않게 할 수 있고, 일시적인 문제가 장기간 이어지지 않게 할 수 있다. 때문에 적절한 DBCP 값을 설정하여 어플리케이션 성능과 안정성을 높일 수 있다.

DataSource : Connection pool을 구현하기 위해 명세를 정해놓은 interface로 데이터베이스에 대한 연결을 제공하는 서비스이다. 다양한 방식의 데이터베이스 연결을 제공하고, 이에 대한 추상화계층을 제공함으로써, 비즈니스 로직과 데이터베이스 연결 방식 간의 종속성을 배제한다.

Java로 구현해보는 Connection Pooling

이미 훌륭한 DBCP 오픈소스 라이브러리가 존재하므로 직접 구현할 필요 없으며, 해당 코드는 DBCP 이해를 위해 사용된다.
Connection Pool에서 Connection을 가져와서 사용하므로 새로운 Connection을 생성할 필요가 없다. 또한 빌려간 Connection을 사용 완료했을 때 다시 Pool에 반환하므로 다른 사용자들이 해당 Connection을 재사용할 수 있다.

  • ConnectionPool Interface는 Connection Pool의 Public API를 정의한다.

    public interface ConnectionPool {
    Connection getConnection();
    boolean releaseConnection(Connection connection);
    String getUrl();
    String getUser();
    String getPassword();
    }
  • BasicConnectionPool class는 전형적인 connection pooling의 기능을 제공한다.

    public class BasicConnectionPool 
    implements ConnectionPool {
    
    private String url;
    private String user;
    private String password;
    private List<Connection> connectionPool;
    private List<Connection> usedConnections = new ArrayList<>();
    private static int INITIAL_POOL_SIZE = 10;
    
    public static BasicConnectionPool create(
      String url, String user, 
      String password) throws SQLException {
    
        List<Connection> pool = new ArrayList<>(INITIAL_POOL_SIZE);
        for (int i = 0; i < INITIAL_POOL_SIZE; i++) {
            pool.add(createConnection(url, user, password));
        }
        return new BasicConnectionPool(url, user, password, pool);
    }
    
    // standard constructors
    
    @Override
    public Connection getConnection() {
        Connection connection = connectionPool
          .remove(connectionPool.size() - 1);
        usedConnections.add(connection);
        return connection;
    }
    
    @Override
    public boolean releaseConnection(Connection connection) {
        connectionPool.add(connection);
        return usedConnections.remove(connection);
    }
    
    private static Connection createConnection(
      String url, String user, String password) 
      throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }
    
    public int getSize() {
        return connectionPool.size() + usedConnections.size();
    }
    
    // standard getters
    }
    }
  • TEST (H2를 사용하였다고 가정)

    @Test
    public whenCalledgetConnection_thenCorrect() {
    ConnectionPool connectionPool = BasicConnectionPool
      .create("jdbc:h2:mem:test", "user", "password");
    
    assertTrue(connectionPool.getConnection().isValid(1));
    }

DBCP 속성 설정

DBCP 오픈소스마다 표현하는 필드명은 조금씩 다르나, 아래와 같은 환경 설정을 할 수 있도록 제공한다. 아래는 HikariCP 기준이지만, 다른 DBCP에서도 적절히 설정해야하므로 안내한다.

  • autoCommit : default true
  • connectionTimeout : 클라이언트가 Pool에서 Connection을 얻기 위해 대기하는 시간. 해당 시간이 도달할때까지 Connection을 얻지 못하면 SQLException을 발생시킨다. default 30 seconds, Lowest 250ms.
  • idleTimeout : Connection의 최대 유휴시간(idleTimeout)을 의미한다. 해당 속성은 minimumIdle < maximumPoolSize 일때만 동작한다. Idel Connection은 minimumIdle 에 도달할때까지 Pool에 반납되지 않으며, minimumIdle Connection 수를 초과할 경우 바로 반환하지 않고 해당 유휴시 간이 지나기를 기다린 후 반납한다. '0'으로 설정할 경우 idle connection이 Pool에서 절대 지워지지않게 할 수 있다. 최소 시간 10초, default 10분
  • keepaliveTime : Connection을 유지하기 위한 시간 설정으로, 데이터베이스나 네트워크에 의해 타임아웃되는 것을 방지한다. 해당 값은 maxLifetime 값보다 반드시 작아야한다. "keepalive"는 오직 idel connection에만 적용되며, "keepalive" 시간에 도달하였을 때
  • maxLifetime : Connection의 유지 시간을 설정한다. 사용중인 Connection은 절대 반환되지 않으며, 오직 사용이 종료된 Connection에 대해 Pool에서 제거한다. HikariCP는 해당 값을 설정하기를 강력하게 권장하며, 데이터베이스의 연결시간 제한보다 몇 초 짧게 설정하도록 하는 것을 추천한다. default 30m, 최소 30s.
  • connectionTestQuery : 만약 사용중인 드라이버가 JDBC4를 지원한다면 해당 속성은 사용할 필요 없다. default none.
  • minimumIdle : default maximumPoolSize와 동일하며, 최소 Idel Connection 개수를 조절할 수 있다. HikariCP에서는 해당 속성을 설정하지 않기를 권장한다.
  • maximumPoolSize : Pool에서 보관 가능한 최대 Connection 개수. 사용할 수 있는 Connection이 없다면 connectionTimeout 만큼 기다린다. default 10, CPU와 스레드에 따른 산정 방식이 존재한다.
  • metricRegistry : Pool에 의해 다양한 매트릭스를 기록한다(?). default none.
  • healthCheckRegistry : Pool이 헬스체크를 위해 보고서 작성용으로 사용함. default none.
  • poolName : default auto-generated

HikariCP 라이브러리 사용

DBCP 오픈소스 중 하나인 HikariCP의 이해와 사용법에 대해 안내한다.
Spring Boot는 2.X 버전부터 default Datasource를 Tomecat-JDBC에서 HikariCP로 변경하였다.
here

참고 자료

반응형

'데이터 관리 > Database' 카테고리의 다른 글

Docker로 Redis 설치하기  (1) 2021.12.17
복합키 VS 대표 ID PK  (0) 2021.08.31
Mac OS 오라클 설치하기  (0) 2021.02.28
카디널리티와 복합키 순서 그리고 PK Index  (0) 2020.10.12
ORACLE SQL paging 처리  (0) 2017.03.21