상세 컨텐츠

본문 제목

데이터 베이스 커넥션 풀(Database Connection Pool)

Database

by 성찬우 2022. 9. 24. 07:15

본문

데이터베이스를 우리가 JDBC를 통해 연결 할시에 매번 연결이 필요하다. 

하지만 이렇게 연결을 계속하게 되면 비효율적이기 때문에 캐싱같이 빠르게 데이터를 전달하는 것처럼

 

일정한 수(보통 10개)의 커넥션을 미리 만들어 놓고 필요한 시점에 애플리케이션에 제공하는 서비스 및 관리 체계 

를 의미한다.

 

사이즈 계산법 : 

 

PoolSize = Tn × ( Cm - 1 ) + ( Tn / 2 )

  • thread count : 16
  • simultaneous connection count : 2
  • pool size : 16 * ( 2 – 1 ) + (16 / 2) = 24

 

커넥션 풀 생성

애플리케이션을 시작할 때 커넥션 풀을 필요한 만큼 미리 확보해 풀에 보관하는 형식이다. 

 

 

이제 우리는 커넥션 풀을 통해서 이미 생성되어있는 커넥션을 객체 참조로 사용이 가능하며

풀에 커넥션을 요청할 시에 가지고 있는 커넥션중에 하나를 반환한다. 이후 사용된 커넥션은 반환된다.

 

 

대표적인 커넥션 풀 오픈소스
  • commons-dbcp2
  • tomcat-jdbc pool
  • HikariCP ☆
문제점

이렇게 다양한 커넥션 풀 오픈소스가 존재하는 상황에서 

만약 DriverManager 를 통한 커넥션을 해야할 때,  커넥션 풀 오픈소스로 변경하게 되었을 때 

또는 오픈소스를 변경하게 되었을 때 

 

우리들의 코드를 수정해주어야 한다. 

그럴때 사용되기 위해 나온것이 DataSource<interface>이다. 

 

 

DataSource

DataSource 란 커넥션을 획득하는 방법을 추상화 하는 인터페이스이다. 대표적인 기능은 커넥션 조회이다. 

대부분의 커넥션 풀은 DataSource 인터페이스를 구현해 두었기 때문에 

커넥션 풀을 위한 코드가 아닌 DataSource를 위한 코드를 구현하면 된다. 

 

DriverManager의 경우 DataSource 인터페이스를 사용하지 않기 때문에 

DriverManagerDataSource를 사용해야한다. 

 

여기서 햇갈릴 수도있는데 우리가 DataSource에 대해서 안다고 해도 아직

커넥션 풀을 사용하는 것은 아니다 

 

DriverManagerDataSource를 사용했다고 한들 달라지는건 

DriverManager는 매번 URL, USERNAME, PASSWORD 를 전달하지만 

Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Connection connection2 = DriverManager.getConnection(URL, USERNAME,PASSWORD);

DriverManagerDataSource는 생성자를 이용해서 한번 파라미터를 전달하면 getConnection();을 통해

다음 부터는 전달하지 않아도 된다는 차이점만이 존재한다. 아직 까지 매번 DB를 사용할시 매번 연결한다.

DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME,PASSWORD);
Connection connection = dataSource.getConnection();
Connection connection1 = dataSource.getConnection();

 

(URL, USERNAME, PASSWORD 는 미리 설정해둔 변수들이다.)

 

직접적으로 Hikari 를 통해서 커넥션 풀을 설정해 보도록 하겠다. 

 

커넥션 풀링

HikariDataSource 를 사용해 볼것인데 디펜던시는 JDBC만 해도 된다. 

 

HikariDataSource hikari = new HikariDataSource();

간단하게 이렇게 HikariDataSource를 생성할 수 있다. 

 

아까처럼 URL, USERNAME, PASSWORD를 set 해주고 이제 

풀 사이즈를 정해주어야 하는데 풀 이름도 지정 가능하다.

 

HikariDataSource hikari = new HikariDataSource();

hikari.setJdbcUrl(URL);
hikari.setUsername(USERNAME);
hikari.setPassword(PASSWORD);
hikari.setMaximumPoolSize(10);
hikari.setPoolName("marcoPool");

 

이렇게 내가 지정한 URL+USERNAME+PASSWORD 이외에도 10개의 사이즈와 이름을 정해주었다. 

 

이렇게 만들어진 hikari를 바로 getConnection()하면 문제가 발생 할 수도있다. 

 

커넥션 풀에서 커넥션을 생성하는 작업은 애플리케이션 실행속도에 영향을 주지 않기 위해서 

다른 쓰레드("우리가 설정한 이름" + connection adder)에서 진행 및 생성이 된다. 

 

커넥션을 풀에 생성하는 작업은 생각보다 오래걸리는 일이다. 그렇기 떄문에 쓰레드를 따로둬서 실행되는 것이고 

쓰레드가 애플리케이션과 다르기 때문에 애플리케이션이 먼저 종료되어 버리면

풀 쓰레드들이 제대로 실행되지 못하고종료되어 버린다. 

 

그렇기 떄문에 test를 해보고 싶으면 Thread.sleep();을 넣어 주어야한다. 

 

DataSource 를 받아서 사용해보자 
public class RepositorySample {
    private final DataSource dataSource;

    public MemberRepository2(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    private Connection getConnection() throws SQLException {
        Connection connection = dataSource.getConnection();
        return connection;
    }
    private void close(Connection connection, Statement statement, ResultSet set) {
        JdbcUtils.closeResultSet(set);
        JdbcUtils.closeStatement(statement);
        JdbcUtils.closeConnection(connection);
    }
}

close는 각각의 jdbc cred 로직 마지막에 넣어주는 매서드이다. 

 

 

태스트 코드를 작성해 볼것인데 

 

여기서 BeforeEach로 HikariDataSource를 사용해볼 예정이다.

 

RepositorySample repositorySample;

@BeforeEach
void beforeEach() throws Exception {
    HikariDataSource dataSource = new HikariDataSource();
    dataSource.setJdbcUrl(URL);
    dataSource.setUsername(USERNAME);
    dataSource.setPassword(PASSWORD);
    repositorySample = new RepositorySample(dataSource);
}

이렇게 dataSource를 Hikari로 생성해서 Repository생성자 매게변수로 넣어주면 된다. 

 

이렇게 하면 HikariDataSource를 사용하게 되는 것이다. 

 

yml 파일 설정법
spring:
 datasource:
   url: jdbc:h2://localhost:3306/world?serverTimeZone=UTC&CharacterEncoding=UTF-8
   username: sa
   password: 
   hikari:
     maximum-pool-size: 10
     connection-timeout: 5000
     connection-init-sql: SELECT 1
     validation-timeout: 2000
     minimum-idle: 10
     idle-timeout: 600000
     max-lifetime: 1800000
  • maximum-pool-size: 최대 pool size (defailt 10)
  • connection-timeout: 유지 시간
  • connection-init-sql: SELECT 1
  • validation-timeout: 2000
  • minimum-idle: 연결 풀에서 HikariCP가 유지 관리하는 최소 유휴 연결 수
  • idle-timeout: 연결을위한 최대 유휴 시간
  • max-lifetime: 닫힌 후 pool 에있는 connection의 최대 수명 (ms)입니다.
  • auto-commit: auto commit 여부 (default true)

'Database' 카테고리의 다른 글

Transaction session & manager  (2) 2022.09.30
트랜잭션  (1) 2022.09.24
데이터 접근 기술 - JDBC  (0) 2022.09.21
h2 [Error creating bean with name 'dataSourceScriptDatabaseInitializer']  (0) 2022.09.16
Hash Table Collision  (0) 2022.08.10

관련글 더보기

댓글 영역