빨간색코딩

Commons DBCP2 (dbcp 정의, 커넥션 속성, Evictor, 트랜잭션, Statements Pool, 예제) 본문

database

Commons DBCP2 (dbcp 정의, 커넥션 속성, Evictor, 트랜잭션, Statements Pool, 예제)

빨간색소년 2018. 4. 11. 16:48

참조문서


1. DBCP 란?

Database Connection Pool 의 약자이다. 요청이 올때마다 Connection 객체를 얻는 것이 아닌, 미리 일정 갯수 찍어내서 Connection Pool 로 관리하는 것이다. DBCP를 사용치 않으면 아래와 같은 과정을 거친다.

  1. DB 서버 접속을 위해 JDBC 드라이버를 로드한다.
  2. DB 접속 정보와 DriverManager.getConnection() Method를 통해 DB Connection 객체를 얻는다.
  3. Connection 객체로 부터 쿼리를 수행하기 위한 PreparedStatement 객체를 받는다.
  4. executeQuery를 수행하여 그 결과로 ResultSet 객체를 받아서 데이터를 처리한다.
  5. 처리가 완료되면 처리에 사용된 리소스들을 close하여 반환한다.

하지만, DBCP 를 사용하면

  1. WAS가 실행되면서 미리 일정량의 DB Connection 객체를 생성하고 Pool 이라는 공간에 저장해 둔다.
  2. HTTP 요청에 따라 필요할 때 Pool에서 Connection 객체를 가져다 쓰고 반환한다.

이와 같은 방식으로 HTTP 요청 마다 DB Driver를 로드하고 물리적인 연결에 의한 Connection 객체를 생성하는 비용이 줄어들게 된다.

2. Commons 의 DBCP

apache commons DBCP 는 커넥션 풀 구현체 오픈소스 중 가장 많이 쓰인다. 여기서는 현재 기준 최신버전인 Commons DBCP 2.2 를 기준으로 다뤄보자.

2-1. Commons DBCP 버전

현재 기준으로 dbcp 홈페이지에 가보면 Last Published: 27 December 2017 | Version: 2.2.0 라고 되어있다. dbcp2 는 Commons Pool2 를 기반으로 하며, 1.x보다 성능이 좋아졌다고한다. 또한 JMX(Java Management eXtensions)를 지원한다.

Commons DBCP 버전JDK 버전JDBC 버전
2.x74.1
1.464
1.3 이하1.4 ~ 1.53

maven 설정

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.2.0</version>
</dependency>

2-2. 커넥션에 관련된 속성들

아래 속성에서 1~4번 속성은 통일해도 무방하다. 여기서 커넥션은 java.sql.Connection 이다.

  • initialSize : 최초 시점에 getConnection() 를 통해 커넥션 풀에 채워 넣을 커넥션 개수 (default = 0)
  • maxTotal (1.x에서는 maxActive): 동시에 사용할 수 있는 최대 커넥션 개수 (default = 8)
  • maxIdle : Connection Pool에 반납할 때 최대로 유지될 수 있는 커넥션 개수 (default = 8)
  • minIdle : 최소한으로 유지할 커넥션 개수 (default = 0)
  • maxWaitMillis (1.x에서는 maxWait) : pool이 고갈되었을 경우 최대 대기 시간 (ms단위, default = -1 = 무한정)
    • 이걸 설정하지 않았는데, pool이 고갈되었고, 엔드유저의 요청은 계속 들어온다면?
    • tomcat 스레드 풀이 고갈되어 죽는다. 엔드유저 요청마다 무한정 대기중일 테니...

2-3. 커넥션의 검사와 정리에 관련된 속성들

  • validationQuery : 풀에 커넥션을 반환하기 전이나, 풀을 획득하기 전에 커넥션이 valid한지를 검사, mysql 기준으로 보통 select 1 설정
  • validationQueryTimeout
  • testOnCreate
  • testOnBorrow : 커넥션 풀에서 커넥션을 얻어올 때 테스트 실행 (default = true)
  • testOnReturn : 커넥션 풀로 커넥션을 반환할 때 테스트 실행 (default = false)
  • testWhileIdle : Evictor 가 실행될 때 커넥션 풀 안에 있는 유휴 상태의 커넥션을 대상으로 테스트 실행 (default = false)
  • maxConnLifetimeMillis : 커넥션의 최대 라이프타임을 지정 (default = -1)
  • logExpiredConnections : 로그로 maxConnLifetimeMillis를 초과한 경우에 커넥션이 닫혔음을 남김 (default = true)
  • connectionInitSqls
  • lifo

2-4. Evictor 스레드와 관련된 속성

Evictor 스레드는 Commons DBCP 내부에서 커넥션 자원을 정리하는 구성 요소이며 별도의 스레드로 실행된다.

  • timeBetweenEvictionRunsMillis : Evictor 가 동작하는 간격 (default = -1, 비활성화)
  • numTestsPerEvictionRun : Evictor 동작 시 한 번에 검사할 커넥션의 개수 (default = 3)
  • minEvictableIdleTimeMillis : Evictor 동작 시 커넥션의 유휴 시간을 확인해 설정 값 이상일 경우 커넥션을 제거 (ms단위, default = 30분) -1 로 설정할 경우 사용하지 않음. (권장)
  • softMiniEvictableIdleTimeMillis : Evictor 가 커넥션을 제거하기 전에 minIdle 수 만큼의 커넥션은 남기도록 한다. 이때 설정값 시간만큼 존재한다. (default = -1)

2-5. 트랜잭션에 관련된 속성들

  • defaultAutoCommit : true 이면 풀에 의해서 생성된 커넥션은 autocommit 된다. 커넥션이 종료되기 전에 commit 처리된다. (default = 드라이버기본값)
  • defaultReadOnly : 풀에 의해서 생성된 커넥션의 read-only상태를 설정 (default = 드라이버기본값)
  • defaultTransactionIsolation
  • defaultCatalog : 풀에 생성된 커넥션의 기본 카탈로그를 설정
  • cacheState
  • defaultQueryTimeout
  • enableAutocommitOnReturn
  • rollbackOnReturn

2-6. PreparedStatements Pool 에 관련된 속성들

  • poolPreparedStatements : statement 풀링여부 설정 (default = false)
  • maxOpenPreparedStatements : 커넥션 당 최대 pooling 할 PreparedStatement 의 갯수를 설정 (default = 무한정, 무한정일 경우 OOM 발생할 수 있음)

3. DataSource

JDBC API 를 이용하여 DB 연동을 처리하려면 DB로부터 커넥션을 얻어야 한다. 따라서 DB정보를 bean으로 등록하여 스프링 컨테이너가 생성하도록 해야한다. 이렇게 생성된 bean은 트랜잭션, mybatis, jpa 등등 범용적으로 사용될 수 있다.

4. 예제 설정

<!-- DataSource 설정 -->
<bean id="sampleDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
	<property name="driverClassName" value="${jdbc.sample.driverClassName}"/>
	<property name="url" value="${jdbc.sample.url}${jdbc.sample.connectionProperties}"/>
	<property name="username" value="${jdbc.sample.username}"/>
	<property name="password" value="${jdbc.sample.password}"/>

    <!-- 4개의 설정은 동일하게 설정하는 것이 예외 케이스를 줄일 수 있음 -->
	<property name="initialSize" value="20"/>
	<property name="maxTotal" value="20"/>
    <property name="maxIdle" value="20"/>
	<property name="minIdle" value="20"/>

    <property name="defaultReadOnly" value="true"/>

    <!-- pool이 고갈되었을 경우 최대 대기 타임 ms -->
	<property name="maxWaitMillis" value="3000"/>

    <property name="validationQuery" value="SELECT 1"/>

    <!-- Evictor 설정 -->
    <property name="testOnBorrow" value="false"/>
    <property name="testOnReturn" value="false"/>

    <!-- testWhileIdle 설정. 150초마다 4개의 connection 꺼내 validation query를 날려 확인 -->
    <property name="testWhileIdle" value="true"/>
   
    <property name="timeBetweenEvictionRunsMillis" value="150000"/>
    <property name="numTestsPerEvictionRun" value="4"/>
    <property name="minEvictableIdleTimeMillis" value="-1"/>
    
    <!-- preparedStatement 풀링 여부 -->
    <property name="poolPreparedStatements" value="true"/>
	<property name="maxOpenPreparedStatements" value="50"/>
</bean>


Comments