[ 소개 ]
- JDBC_Connection_Pool 은 Apache_Commons_DBCP 를 대체 가능하다. (기본값: Apache_Commons_DBCP_2 사용)
1004lucifer
1. JDBC_Connection_Pool 을 사용해야 하는 이유
1) Commons_DBCP v1.x 는 단일 스레드를 사용한다. (DBCP_2 해당안됨)
2) Commons_DBCP 논리적 CPU 수가 증가하고 객체를 빌리거나 반환하려는 동시 스레드 수가 증가함에 따라 성능이 저하된다. (DBCP_2 해당안됨)
3) Commons_DBCP 는 60개가 넘는 클래스가 있지만 tomcat-jdbc-pool core 는 8개의 클래스 이므로 추후 요구사항에 따른 적은 수정만 필요하다.
4) Commons_DBCP 는 정적 인터페이스를 사용하기에 올바른 JVM 버전을 사용하지 않으면 NoSuchMethodException 이 발생할수 있다.
5) Tomcat_JDBC_Pool 은 라이브러리 자체에 추가적인 스레드를 추가하지 않고 비동기적으로 Connection 을 검색하는 기능을 구현하고 있다.
6) Tomcat_JDBC_Pool 은 Tomcat 모듈이며, Tomcat 에서 사용하는 단순화된 로깅 프레임워크인 Tomcat JULI 에 의존한다.
7) javax.sql.PooledConnection 인터페이스를 사용하여 기본 연결을 검색한다.
8) Pool 이 비어있고 스레드가 Connection 대기중인 경우, Connection 이 반환되면 Pool은 대기중인 올바른 스레드를 다시 깨운다.
2. JDBC_Connection_Pool 에 추가된 기능
1) 높은 동시성 환경과 Multi Core/CPU 시스템을 지원한다.
2) 인터페이스의 동적 구현은 JDK의 낮은 버전으로 컴파일된 경우에도 런타임 환경을 지원하고 java.sql, javax.sql 인터페이스를 지원한다. (JDBC 드라이버가 동일한 경우)
3) Validation 간격 - Connection 을 사용할 때마다 Validate 를 할필요 없으며, Connection 을 가져오거나 반환할 때 Validation 을 할 수 있지만, 우리가 구성한것보다 더 많이 Validation 을 수행하지는 않는다.
4) Run-Once 쿼리는 Database 연결될 때 한반만 실행하도록 구성하는 쿼리다. Connection 이 맺어지는 전체 시간동안 세션에 대한 설정을 하는데 유용하다.
5) 사용자 지정 인터셉터를 구성하여 성능을 향상시킬 수 있다. 인터셉터를 사용하여 쿼리수집 상태, 세션캐시 상태, Connection 실패에 대한 재연결, 쿼리 재시도, 쿼리캐시결과 등을 수행할 수 있다. 옵션은 무궁무진하며 인터셉터는 java.sql / javax.sql 인터페이스의 JDK 버전에 묶이지 않는다.
6) 비동기 Connection 검색 - Connection 요청을 대기열에 넣고 Future<Connection> 을 응답받을 수 있다.
7) idle Connection 처리 개선. Connection 을 직접 Close 하는대신 Connection 을 Pooling 하고 알고리즘을 통해 idle Pool 사이즈를 조정한다.
8) Pool 의 임계값을 지정하여 Pool 이 꽉차거나 timeout 시에 Connection 이 중단(abandon)된 것으로 간주하는 시점을 결정할 수 있다.
9) 중단 Connection 타이머는 statement/query 수행 시 재설정 된다. 오랬동안 사용중인 Connection 에 대해서 timeout 발생하지 않도록 허용한다. ResetAbandonedTimer 를 통해 설정 가능하다.
10) 일정시간 연결이 유지된 Connection 을 닫는다. Pool 에 다시 돌아갈 때 유지 기간에 따라 닫는다.
11) Connection 이 중단(abandon) 된 것으로 의심되는경우 JMX 알림을 받고 로그를 기록한다. removeAbandonedTimeout 과 유사하지만 아무것도 하지 않고 로그만 쌓는다. suspectTimeout 속성을 통해 설정 가능하다.
12) Connection 은 java.sql.Driver, javax.sqlDataSource, javax.sql.XADataSource 를 통해서 가져올 수 있으며 dataSource 와 dataSourceJNDI 속성을 통해 구성한다.
13) XA Connection 을 지원한다. (하지만 Tomcat 은 JTA를 지원하지 않는다.)
[ 사용 방법 ]
- Tomcat Connection Pool 의 사용법은 최대한 간단히 만들어졌기 때문에 commons-dbcp 에 익숙한 사용자라면 전환이 간단하다. 다른 Connection Pool 에서 전환하는 것도 간단하다.
1. 추가 기능
- Tomcat Connection Pool 은 다른 Pool 이 제공하는 기능에 비해 몇 가지 추가 기능을 제공한다.
1) initSQL - Connection 이 생성될 때 한번만 수행되는 SQL 을 실행하는 기능
2) validationInterval - Connection 에 대한 유효성 검사, 너무 자주 실행하지 않도록 유의 필요
3) jdbcInterceptors - Pool, Query, Result 에 대한 커스텀 처리를 만드는 인터셉터 플러그
4) fairQueue - Connection 에 대한 FIFO 방식으로 Thread 공정성을 처리하거나 비동기 Connection 을 가져오려면 true 로 설정
2. Apache Tomcat Container 설정
- Tomcat Connection Pool 은 The Tomcat JDBC 문서 에 있는 설명된 리소스로 구성되며, 유일한 차이점은 factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 속성을 지정해야 한다는 점이다.
3. 다른 독립 Application 설정
- 해당 Connection_Pool 은 tomcat-juli.jar 에만 의존성이 있다.
- org.apache.tomcat.jdbc.pool.DataSource Bean 을 인스턴스화 하여 다른 독립 프로젝트에서 Pool 을 구성할 수 있다.
- (아래 설명되어 있는것과 같이) Connection Pool 을 JNDI 리소스로 구성하는데 사용한것과 동일한 속성이 DataSource 를 Bean 으로 구성하는데 사용된다.
4. JMX
- Connection Pool 객체는 등록할 수 있는 MBean 을 노출한다.
- Connection Pool 객체가 MBean 을 생성하려면 jmxEnabled 설정을 true 로 해야한다. (Pool 이 MBean 서버에 등록된다는 의미가 아니라 MBean 이 생성되는것을 의미)
- Tomcat 과 같은 컨테이너는 Tomcat 스스로 MBean 서버에 DataSource를 등록하는데, 그러면 org.apache.tomcat.jdbc.pool.DataSource 객체가 실제 Connection Pool MBean 에 등록한다.
- 만약 컨테이너가 아닌경우 DataSource 를 지정한 이름으로 직접 등록이 가능하며, 등록한 기본 Pool 이 전파된다.
- 이렇게 하려면 mBeanServer.registerMBean(dataSource.getPool().getJmxPool(), objectname) 과 같이 호출한다. 이 함수를 호출하기전에 dataSource.createPool() 을 호출하여 Pool 이 생성되었는지 확인한다.
[ 속성 ]
- common-dbcp 와 tomcat-jdbc-pool 을 간단히 전환할 수 있도록 대부분의 속성은 동일하고, 동일한 의미를 갖는다.
1. JNDI 팩토리 및 유형
속성 | 설명 |
---|---|
factory | 필수값이며, 다음 값을 넣는다. org.apache.tomcat.jdbc.pool.DataSourceFactory |
type | 값은 항상 javax.sql.DataSource 또는 javax.sql.XADataSource 값 이어야 한다. 유형에 따라 org.apache.tomcat.jdbc.pool.DataSource 또는 org.apache.tomcat.jdbc.poo.XADataSource 가 생성이 된다. |
2. 시스템 속성
- JVM의 System Properties 는 JVM 에 생성된 모든 Pool 에 영향을 미친다.
속성 | 설명 |
---|---|
org.apache.tomcat.jdbc.pool.onlyAttemptCurrentClassLoader | (boolean) JDBC Drivers, Interceptors, Validators 와 같은 동적 클래스의 클래스로딩을 제어한다. 기본값인 false 로 설정하면 Pool 은 현재 로더(Pool class를 로드한 클래스로더)를 사용하고, 클래스 로딩에 실패 시 Thread Context Loader 를 사용하여 로드를 시도한다. true 로 설정하면 Tomcat 8.0.8 이하의 하위호환성을 유지하고 현재 로더만 시도한다. |
3. 공통 속성
- 여기 속성들은 commons-dbcp 와 tomcat-jdbc-pool 이 공유하고 있으나 어떤 경우에는 기본값이 다르기도 하다.
속성 | 설명 |
---|---|
defaultAutoCommit | (boolean) Pool 에서 생성된 Connections 의 기본 auto-commit 상태. 설정하지 않으면 JDBC 드라이버 기본값 (setAutoCommit 메소드가 호출되지 않음) |
defaultReadOnly | (boolean) Pool 에서 생성된 Connections 의 기본 read-only 상태. 설정하지 않으면 setReadOnly 메소드가 호출되지 않음 (Informix 와 같은 일부 드라이버는 read-only 모드가 지원되지 않음) |
defaultTransactionIsolation | (String) Pool 에서 생성된 Connections 의 기본 TransactionIsolation 상태. 다음중 하나 (javadoc 참고) - NONE - READ_COMMITTED - READ_UNCOMMITTED - REPEATABLE_READ - SERIALIZABLE 설정하지 않으면 호출되지 않으며 기본 JDBC 드라이버가 사용된다. |
defaultCatalog | (String) Pool 에서 생성한 Connections 의 기본 Catalog |
driverClassName | (String) 사용할 FQCN 형식 자바 클래스 이름. 드라이버는 tomcat-jdbc.jar 와 동일한 클래스 로더에서 엑세스 할 수 있어야 한다. |
username | (String) Connection 설정을 위한 JDBC 드라이버에게 전달하는 username DataSource.getConnection(username, password) 메소드는 메소드에 전달된 자격증명을 사용하지 않고 여기에 구성한 정보를 사용한다. 자세한 내용은 alternateUsernameAllowed 속성을 참고. |
password | (String) Connection 설정을 위한 JDBC 드라이버에게 전달하는 password DataSource.getConnection(username, password) 메소드는 메소드에 전달된 자격증명을 사용하지 않고 여기에 구성한 정보를 사용한다. 자세한 내용은 alternateUsernameAllowed 속성을 참고. |
maxActive | (int) Pool 에서 할당 가능한 Active_Connection 의 최대 개수 (기본값 : 100) |
maxIdle | (int) Pool 에서 항상 보관해야 하는 최대 Connection 개수. testWhileIdle 이 활성화 되어있는 경우 Idle_Connection 은 주기적으로 체크되고 minEvictableIdleTimeMillis 보다 오래되면 해제된다. (testWhileIdle 참고) |
minIdle | (int) Pool 에 항상 연결되어야 하는 최소 Connection 개수. Validation_Query 가 실패하면 Connection_Pool 이 minIdle 값 아래로 줄어들 수 있다. 기본값은 initialSize:10 에 영향을 받는다. (testWhileIdle 참고) |
initialSize | (int) Pool 이 시작할 때 생성할 초기 Connection 개수. (기본값: 10) |
maxWait | (int) (사용 가능한 연결이 없는경우) Pool 에서 예외를 발생시키기 전에 Connection 이 반환될 때까지 대기하는 최대 milliseconds 값 (기본: 30000, 30초) |
testOnBorrow | (boolean) Pool 에서 Connection 을 빌리기전에 객체의 유효성을 검사할지 여부. 객체의 유효성 검사에 실패하면 Pool 에서 삭제되고 다른 객체를 빌리려고 시도한다. 효율적인 유효성 검사를 하려면 validationInterval 을 참고. 기본값 : false |
testOnConnect | (boolean) Connection 이 처음 생성될 때 객체 유효성을 거사할지 여부. (기본값: false) 검사 실패하는경우 SQLException 이 발생한다. |
testOnReturn | (boolean) Connection 을 Pool 에 반환하기전에 객체 유효성 검사를 할지 여부. (기본값: false) |
testWhileIdle | (boolean) Idle_Connection 객체 제거자가 있는경우 객체의 유효성을 검사할지 여부. (기본값: false) 객체가 유효성 검사에 실패하면 Pool 에서 삭제된다. Pool clear/test Thread 를 실행하려면 true 로 설정해야 한다. (timeBetweenEvictionRunsMillis 참고) |
validationQuery | (String) Connection 호출자에게 전달하기전에 Pool 에서 유효성 검사를 할 SQL 쿼리. (기본값: null) 이 옵션을 지정하면 해당 쿼리는 데이터를 반환하지 않으며, SQLException 도 발생하지 않는다. 설정하지 않은경우 Connection 은 isValid() 메소드로 유효성 검사를 한다. Example) - MySQL : SELECT 1 - Oracle : select 1 from dual - MS_SQL : SELECT 1 |
validationQueryTimeout | (int) validationQuery 가 실패하기 전까지의 시간(초) validationQuery 가 수행하는 곳에서 java.sql.Statement.setQueryTimeout(secods) 를 호출하여 작동한다. Pool 은 쿼리 제한시간은 두지 않으며, 제한시간을 두는것은 JDBC 드라이버에 달려있다. 0 보다 작거나 같은 값인경우 기능이 비활성화 된다. (기본값 : -1) |
validatorClassName | (String) (내부에는 있을 수 있지만) 인자없는 생성자와 함께 org.apache.tomcat.jdbc.pool.Validator 인터페이스를 구현하는 클래스 이름. 이 옵션을 지정하면 Validator 인스턴스가 생성이 되고 Connection 의 유효성을 검사할 때 Validation Query 대신 사용된다. 기본값 : null 예시) com.mycompany.project.SimpleValidator |
timeBetweenEvictionRunsMillis | (int) idle Connection 에 대해서 Validation / Cleaner 쓰레드의 수행 사이에 대기하는 밀리초 시간 (기본값: 5000, 5초) 이 값을 1초 미만으로 설정하면 안됨. 이 값은 Connection 의 idle, abandoned, validation 을 검사하는 빈도를 결정한다. maxAge 값이 0 이 아니고 이 설정값보다 낮은경우 maxAge 값으로 대체된다. |
numTestsPerEvictionRun | (int) tomcat-jdbc-pool 에서는 사용하지 않음 |
minEvictableIdleTimeMillis | (int) 객체가 Pool 에서 (idle)유휴 상태로 있을 수 있는 최소 시간 (기본값 : 60000, 60초) |
accessToUnderlyingConnectionAllowed | (boolean) 사용하지 않는 속성 Pool 안에 있는 Connection 에서 unwarp 호출하여 접근 가능하다. javax.sql.DataSource 를 참조하거나, 리플렉션을 통해 getConnection 을 호출하거나 javax.sq.PooledConnection 으로 캐스팅한다. (추가설명: DBCP 에서 래핑하기 이전의 원본 커넥션을 가져오는데 잘못된 연상 수행으로 위험해 질 수 있으니 드라이버 고유의 확장 기능을 직접 사용하는 경우가 아니라면 권장하지 않음) |
removeAbandoned | (boolean) (abandoned)중단된 Connection 이 removeAbandonedTimeout 을 초과하는 경우 제거 Flag 를 지정한다. (기본값: false) true 로 셋팅 시 Connection 이 removeAbandonedTimeout 을 초과한경우 중단된 것으로 간주하고 제거할 수 있고, Application 에서 Close 하지 않은 Connection 을 복구할 수 있다. (logAbandoned 참고) |
removeAbandonedTimeout | (int) (사용중인) abandoned Connection 을 제거할 수 있는 시간(초) 설정 (기본값: 60, 60초) 이 값은 Application 에서 가장 오래 실행되는 쿼리 시간으로 설정해야 한다. |
logAbandoned | (boolean) abandoned Connection 의 Application 코드에 대한 Stack Trace Log 를 남기도록 지정 (기본값: false) abandoned Connection 을 로깅 하려면 가져온 Connection 에 대해서 Stack Trace 를 추가해야 하기 때문에 오버헤드가 추가된다. (성능 낮아짐) |
connectionProperties | (String) 새로운 Connection 연결을 할 때 JDBC 드라이버로 보내는 연결속성 (기본값: null) 문자열의 형식은 [propertyName=property;]* 형식이어야 한다. "user", "password" 속성은 명시적으로 전달되기에 여기 포함할 필요 없음. |
poolPreparedStatements | (boolean) 사용하지 않는 속성 |
maxOpenPreparedStatements | (int) 사용하지 않는 속성 |
4. Tomcat JDBC 전용 추가 속성
속성 | 설명 |
---|---|
initSQL | (String) Connection 이 처음 생성될 때 실행되는 커스텀 쿼리 (기본값 : null) |
jdbcInterceptors | (String) org.apache.tomcat.jdbc.pool.JdbcInterceptor 를 extens 한 클래스 리스트(세미콜론으로 구분) 이러한 인터셉터들은 java.sql.Connection 객체의 작업체인에 인터셉터로 삽입된다. (기본값: null) [미리 정의된 인터셉터] - org.apache.tomcat.jdbc.pool.interceptor.ConnectionState : auto commit / read only / catalog / transaction isolation level 을 추적 - org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer : opened statements 와 Connection 이 반환될 때 close 되었는지 추적 - 등등 더 많은 내용은 아래 JDBC 인터셉터 구성 내용 참고 |
validationInterval | (long) 과도한 유효성 검증을 피하고 최대한 이 값의 빈도로 검증을 수행한다. (기본값: 3000, 3초) (Validation)유효성 검증이 필요한 Connection 이지만 이 간격 이내에 유효성 검사을 받은 적이 있으면 유효성 검사를 재수행 하지 않는다. |
jmxEnabled | (boolean) JMX에 Pool 을 등록할지 여부 (기본값: true) |
fairQueue | (boolean) true 설정 시 getConnection 호출이 FIFO 방식으로 순차적으로 처리됨 (기본값 : true) idle Connections 목록에 org.apache.tomcat.jdbc.pool.FairBlockingQueue 구현된것을 사용한다. 비동기 Connection 연결을 가져오려면 이 설정이 필요하다. 이 값을 설정하면 Thread 가 도착하는 순서대로 Connection 을 받는다. 성능테스트 시 lock / lock waiting 구현방식에 따라 큰 차이가 있었다. fairQueue=true 인경우 실행중인 OS에 따라서 프로세스 기본방식이 결정된다. (os.name=Linux 속성) 리눅스 시스템인경우 Connection_Pool 클래스가 로드되기 전에 org.apache.tomcat.jdbc.pool.FairBlockingQueue.ignoreOS=true 시스템 프로퍼티를 추가하여 리눅스 전용 동작을 비활성화 하고 FIFO Queue 방식을 사용할 수 있다. |
abandonWhenPercentageFull | (int) 시간 초과된 abandoned Connection 개수가 이 값의 퍼센트를 초과하지 않는 한 Close 되지 않고 로그에 남지 않는다. 값은 0~100 사이 입력 가능 (기본값: 0) 기본값 0 은 removeAbandonedTimeout 에 도달하는 즉시 Close 가 되는것을 의미한다. |
maxAge | (long) Connection 을 다시 생성하기 전에 연결을 유지하는 밀리초 시간. (기본값: 0) Pool 에서 Connection 을 가져올 때 maxAge < 현재시간 - Connection_연결시간 체크하여 (age)시간이 도달한 경우 ReConnect 한 후 가져온다. Connection 이 Pool 에 반환될 때 maxAge < 현재시간 - Connection_연결시간 체크하여 (age)시간이 도달한 경우 ReConnection 수행한다. Connection 이 idle 상태이고 timeBetweenEvictionRunsMillis 가 0 보다 큰경우 주기적으로 maxAge < 현재시간 - Connection_연결시간 체크하여 (age)시간이 도달한 경우 ReConnection 수행한다. maxAge 를 timeBetweenEvictionRunsMillis 보다 낮게 설정하면 maxAge 값은 timeBetweenEvictionRunsMillis 값으로 셋팅된다. (idle Connection 의 Validation / Cleaning 이 더 자주 실행된다.) 기본값인 0 인 경우 Connection 이 Open된 상태로 유지되고, Connection 을 Pool 에서 가져올때나 Pool 에 돌려줄때, idle Connections 체크 시 age 시간 체크를 수행하지 않는다. |
useEquals | (boolean) ProxyConnection 클래스에서 메소드 이름을 비교할 때 String.equals 를 사용하려면 true 로 셋팅하고, == 를 사용하려면 false 를 셋팅한다. (기본값: true) 인터셉터는 개별적으로 구성되기에 이 값은 인터셉터에 적용되지 않는다. |
suspectTimeout | (int) 시간 초 값 (기본값: 0) logAbandoned 가 true 인경우, removeAbandonedTimeout 과 유사하지만 Connection 을 Close 하거나 Abandoned 하는것 대신 단순히 경고 로그만 남긴다. 0 이거나 0보다 작은경우 Connectin 의심 체크를 수행하지 않는다. abandon 체크가 비활성화 되어있거나 값이 0보다 크고 Connection 이 (abandon) 중단 되지 않은경우 체크를 수행한다. Connection 이 의심스러운경우 경고 메시지를 로그에 남기고 JMX 알림이 한번 전송된다. |
rollbackOnReturn | (boolean) autoCommit==false 이면 Connection 이 Pool 로 반환될 때 rollback 을 호출하여 트랜잭션을 종료할 수 있다. (기본값: false) |
commitOnReturn | (boolean) autoCommit==false 이면 Connection 이 Pool 로 반환될 때 commit 을 호출하여 트랜잭션을 완료할 수 있다. (기본값: false) rollbackOnReturn==true 인 경우 이 속성은 무시된다. |
alternateUsernameAllowed | (boolean) 기본적으로 성능상의 이유로 jdbc-pool 의 DataSource.getConnection(username, password) 호출을 무시하고, username, password 의 글로벌 속성으로 구성된 이전에 Pool 된 Connection 을 가져온다. (기본값: fasle) Pool 은 Connection 을 요청할때마다 매번 다른 자격증명을 사용하도록 구성할 수 있다. true 로 설정 시 간단하게 DataSource.getConnection(username, password) 를 호출하여 해당 메소드의 설명된 기능을 사용할 수 있다. 만약 user1/password1 으로 Connection 자격증명을 요청했는데 이전에 user2/password2 로 Connection 연결된게 있다면 Connection 을 Close 하고 이전에 연결된 Connection 을 다시 Open 하여 가져온다. 이렇게 하면 Pool 사이즈가 스키마 레벨이 아닌 글로벌 레벨로 관리된다. 이 속성은 bug 50025 의 기능 향상을 위해 추가되었다. 설명: DataSource.getConnection(username, password)를 사용하더라도 Tomcat 에 (글로벌 커넥션) JNDI 구성이 되어 있다면 해당 커넥션을 가져오는게 우선이며, 이 옵션을 true 로 설정 시 JNDI 값을 가져오지 않고 새로 연결을 맺는다. |
dataSource | (javax.sql.DataSource) Connection Pool 에 데이터소스를 주입하면 Pool 은 java.sql.Driver 인터페이스 대신 설정한 데이터소스를 사용하여 Connection 을 연결한다. (기본값: null) 이 기능은 연결 문자열 대신에 데이터소스를 사용하여 XA Connections 를 Pool 하는데 유용하다. |
dataSourceJNDI | (String) JNDI 를 조회하고 DB에 커넥션 연결에 사용할 데이터소스의 JNDI 이름 (기본값: null) |
useDisPosableConnectionFacade | (boolean) Connection 연결이 Close 된 후 재사용할 수 없도록 Facade 를 설정하려면 이 값을 true 로 설정 (기본값: true) 이렇게 하면 Thread 가 이미 Close 된 Connection 의 참조를 유지하여 해당 Connection 에 대한 쿼리 수행을 방지한다. |
logValidationError | (boolean) (Validation) 유효성 검사 단계 중 발생한 에러를 로그에 기록하려면 true 로 설정한다. (기본값: false) 이전버전의 호환성을 위해 기본값은 false 이다. |
propagateInterruptState | (boolean) 인터럽트 된 Thead 의 상태를 전파하려면 true 로 설정한다. (인터럽트 상태를 지우지 않으려면..) 이전버전의 호환성을 위해 기본값은 false 이다. |
ignoreExceptionOnPreLoad | (boolean) Pool 을 초기화 하는동안 Connection 생성 오류를 무시할지 여부 (기본값: false) Pool 을 초기화 하는 동안 Connection 생성 오류를 무시하려면 true 로 설정한다. Exception 을 발생시켜 Pool 의 초기화를 실패하게 하려면 false 를 설정한다. |
useStatementFacade | (boolean) Statement Proxy 가 설정된 경우 Close 된 Statement 의 equals() 와 hashCode() 메소드를 활성화 하기 위해 Statement 를 래핑한다. (기본값: true) |
[ 고급 사용법 ]
1. JDBC 인터셉터
- 인터셉터 사용방법의 예시를 보려면 org.apache.tomcat.jdbc.pool.interceptor.ConnectionState 를 참조한다. 이 간단한 인터셉터는 transaction isolation level / auto commit / read only state 세가지 속성의 캐시로써 시스템이 불필요한 Database 의 통신을 피할 수 있도록 한다.
- 필요에 따라 더 많은 인터셉터가 Pool 의 코어에 추가될 예정이다.
- 인터셉터는 java.sql.Connection 에만 제한되는게 아니라 모든 메소드의 결과를 래핑하는데에도 사용할 수 있다. 쿼리가 예상시간보다 오래 걸릴 때 JMX 알림을 제공하는 쿼리 분석기를 구축할수도 있다.
2. JDBC 인터셉터 구성
- JDBC 인터셉터는 jdbcInterceptors 속성을 사용하여 구성한다. 이 속성은 세미콜론(;) 으로 구분된 클래스 리스트로 구성된다. 클래스 이름이 (fully qualified)정규화 되지 않은경우 org.apache.tomcat.jdbc.pool.interceptor 가 접두사로 붙는다.
- 예제: jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState; org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
- 인터셉터도 속성을 가질 수 있다. 인터셉터의 속성은 클래스 이름 뒤에 괄호 안에 지정된다. 여러 속성은 쉼표로 구분된다.
- 예제: jdbcInterceptors="ConnectionState;StatementFinalizer(useEquals=true)"
- Class Names / Property Names / Values 의 주변의 공백 문자는 무시된다.
3. org.apache.tomcat.jdbc.poolJdbcInterCeptor
- 모든 인터셉터에 대한 기본 추상클래스 이며 인스턴스화 할 수 없다.
속성 | 설명 |
---|---|
useEquals | (boolean) ProxyConnection 클래스에서 메소드 이름을 비교 시 String.equals 를 사용하려면 true 로 설정, == 로 사용하려면 false 셋팅 (기본값: true) |
4. org.apache.Tomcat.jdbc.pool.interceptor.ConnectionState
autoCommit / readOnly / transactionIsolation / catalog 속성에 대한 Connection 을 캐시한다. 이미 설정된 값으로 getter / setters 를 호출 할때 Database 의 통신을 피하기 위한 성능향샹 기능.
* 속성 없음
5. org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer
- createStatement / prepareStatement / prepareCall 을 사용하여 생성된 모든 Statements 를 추적하고, Connection 이 Pool 로 반환되면 Statements 를 Close 한다.
속성 | 설명 |
---|---|
trace | (boolean as String) Close 되지 않은 Statement 를 추적에 대한 여부, true 설정 시 Connection 이 Close 되고, Statement 가 Close 되지 않았을 때 Stack Trace 로그를 남긴다. (기본값: false) |
6. org.apache.tomcat.jdbc.pool.interceptor.StatementCache
- Connection 의 PreparedStatement / CallableStatement 인스턴스를 캐시한다.
- Connection 별로 Statement 가 캐시 된다. 카운트 제한은 같은 Pool 에 있는 모든 Connection 에 대해서 (Global)전역 카운트를 한다. 카운트가 max 에 도달하면 다음 Statement 는 캐시에 반환되지 않고 즉시 Close 된다.
속성 | 설명 |
---|---|
prepared | (boolean as String) true 설정 시 기존에 생성하여 호출에 사용한 PreparedStatement 인스턴스를 캐싱한다. (기본값: true) |
callable | (boolean as String) true 설정 시 기존에 생성하여 prepareCall 호출에 사용한 CallableStatement 인스턴스를 캐싱한다. (기본값: true) |
max | (int as String) Connection Pool 에 캐시된 Statement 캐시의 개수 제한 (기본값: 50) |
7. org.apache.tomcat.jdbc.pool.interceptor.StatementDecoratorInterceptor
- 버그리포트 48392 참고
- Statement 와 ResultSet 을 래핑하여 ResultSet.getStatement().getConnection() 과 Statement.getConnection() 메소드를 사용하는 실제 커넥션에 대한 접근을 제한한다.
* 속성 없음
- 버그리포트 추가설명: Statement 와 ResultSet 에서 Proxy Connection 을 리턴하지 못하는 이슈가 있었고, JdbcInterceptor 에 Proxy Statement/ResultSet 을 구현했다. Proxy 된 Connection 을 사용하는 경우 해당 인터셉터를 추가하여 Proxy 되지 않은 Connection 에 대한 접근을 차단할 수 있다.
8. org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor
- 새로운 Statement 가 생성되면 자동으로 java.sql.Statement.setQueryTimeout(seconds) 가 호출된다. Pool 자체는 쿼리의 Timeout 에 관여하지 않고 JDBC 드라이버가 Timeout 에 관여한다.
속성 | 설명 |
---|---|
queryTimeout | (int as String) 쿼리 타임아웃에 설정할 (초)시간, 0 이거나 0 보다 작으면 비활성화 된다. (기본값: 1 초) |
9. org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport
- 쿼리가 (threshod)임계값을 초과하면 WARN 레벨의 로그를 생성한다.
속성 | 설명 |
---|---|
threshold | (int as String) Log 생성하기 전에 최대한 기다릴 수 있는 (밀리초)시간. (기본값: 1000 밀리초) |
maxQueries | (int as String) 메모리 용량을 다 사용하지 않도록 쿼리 추적하는 최대 개수. (기본값: 1000) 0 이거나 0 보다 적은경우 기능 비활성화 |
logSlow | (boolean as String) true 설정 시 Slow 쿼리를 로그에 기록 (기본값: true) |
logFailed | (boolean as String) true 설정 시 실패한 쿼리를 로그에 기록 (기본값: false) |
10. org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx
- SlowQueryReport 를 확장하고 로그 저장 이외에 모니터링 툴이 반응할 수 있도록 JMX 에 알림을 보낸다. (SlowQueryReport) 부모 클래스로부터 모든 속성을 상속한다.
- 이 클래스는 Tomcat JMX 엔진을 사용하므로 Tomcat 컨테이너가 아닌 외부 Application 에서는 동작하지 않는다. 기본적으로 JMX 알림은 환성화된 ConnectionPool MBean 으로 전송한다.
- SlowQueryReportJmx 는 notifiPool=false 설정이 되어있는 경우 등록이 가능하다.
속성 | 설명 |
---|---|
notifyPool | (boolean as String) JMX 알림을 SlowQueryReportJmx MBean 으로 보내려면 false 로 설정한다. (기본값: true) |
objectName | (String) MBean 서버에 등록하는데 사용할 유효한 javax.management.ObjectName 객체 문자열을 정의한다. (기본값: null) 객체는 tomcat.jdbc:type=org.apache.tomcat.jdbc.pool.inerceptor.SlowQueryReportJmx,name=the-name-of-the-pool 을 사용하여 등록된다. |
11. org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer
- abandoned 타이머는 Connection 이 Pool 에서 체크아웃 될때 시작된다. 즉 Timeout 이 30초인경우 10초 수행 쿼리를 10번 수행 시 abandonWhenPercentageFull 속성에 따라 회수가 가능해지고 abandoned 가 마킹된다.
- 이 인터셉터를 사용하면 Connection 에서 작업을 수행하거나 쿼리가 성공적으로 수행될 때마다 체크아웃 타이머가 리셋된다.
* 속성 없음
[ 코드 예제 ]
- Tomcat JDBC 사용을 위한 다른 구성 예제는 해당 Tomcat 문서에서 확인할 수 있다.
1. 기본 자바
- 데이터 소스를 만들고 사용하는 간단한 예제
2. 리소스
- JNDI 조회를 위한 리소스 설정에 대한 예제
3. 비동기 Connection 검색
- Tomcat JDBC Connection Pool 은 Pool 라이브러리에 스레드를 추가하지 않고도 비동기 Connection 검색을 지원한다.
- 이 작업은 Future<Connection getConnectionAsync() 메소드를 데이터소스에 추가하여 호출한다.
- 비동기 검색을 사용하려면 아래 두가지 조건을 충족해야 한다.
1) fairQueue 속성을 true 로 설정
2) 데이터소스를 org.apache.tomcat.jdbc.pool.DataSource 로 캐스팅 해야한다.
- 비동기 기능을 사용하는 예제
4. 인터셉터
- 인터셉터는 특정 Connection 이나 하위 구성요소에서 기능을 활성화 / 비활성화 / 수정 할 수 있는 강력한 방법이다.
- 인터셉터가 유용한 경우의 사례는 다양하다. 기본적으로 성능상의 이유로 Connection Pool 은 (stateless)상태가 없다.
- Pool 의 상태는 속성을 일부러 설정한경우 defaultAutoCommit, defaultReadOnly, defaultTransactionIsolation, defaultCatalog 상태를 설정할 수 있으며, 이 속성은 Connection 이 생성될 때만 설정되고 사용중에 속성을 수정해도 재설정 되지 않는다.
- 인터셉터는 인자가 없는 생성자를 가진 org.apache.tomcat.jdbc.pool.JdbcInterceptor 를 extends 한 클래스다.
- Pool 에서 Connection 을 가져오면 인터셉터는 아래 메소드를 구현하여 초기화 하거나 다른 방식으로 이벤트에 반응할 수 있다. 이 메소드는 Connection Pool 자신의 ConnectionPool parent 와 기본 Connection 인 PooldConnection con. 두개의 파라미터를 가지고 있다.
- java.sql.Connection 객체가 invoke 되면 아래 메소드가 같이 invoke 된다. Method method 는 실제 invoke 된 메소드 이고, Object[] args 는 넘겨받은 인자이다.
- 아래와 같이 Connection 이 이미 Close 된 경우에는 java.sql.Connection.close() 함수가 정상 적으로 수행되지 않는 간단한 예를 보여줄 수 있다.
- 메소드 이름도 같이 비교하는데 "close".equals(method.getName()) 을 수행할수도 있지만 위에서는 메소드 이름과 static final String 을 직접 비교를 했다. JVM 스펙에 따르면 메소드 이름과 static final String 은 정적 상수 Pool 에 있으므로 reference 비교도 가능해야 한다. 물론 아래와 같이 할수도 있다. compare(String, Method) 는 인터셉터에서 useEquals 플래그를 사용하며, useEquals=true 를 설정 시 reference 비교나 String 값 비교를 한다.
- Pool 시작 / 중지
Connection Pool 이 Start 되거나 Close 될 때 알림을 받을 수 있다. 인스턴스 메소드 이더라도 인터셉터 클래스당 한번만 알림을 받게되며, Pool 에 연결되지 않은 인터셉터를 사용하여 알림을 받게된다. JdbcInterceptor 확장 클래스에서 이러한 메소드를 오버라이드 할 때 super 를 호출하는 것을 잊으면 안된다.
- 인터셉터 설정
인터셉터는 jdbcInterceptors 속성 또는 setJdbcInterCeptors 메소드를 사용하여 구성한다. 인터셉터에는 속성이 있을 수 있으며 아래와 같이 구성할 수 있다.
- 인터셉터 속성
인터셉터에는 프로퍼티가 있을 수 있으므로 인터셉터 내에서 이러한 프로퍼티 값을 읽을 수 있어야 한다. 예를들어 아래와 같이 setProperties 메소드를 오버라이드 할 수 있다.
5. 실제 JDBC Connection 가져오기
- Connection Pool 은 적절한 Pooling 을 위해 실제 Connection 을 래핑한다. 또한 이러한 래퍼에 특정 기능을 수행할 수 있도록 인터셉터를 생성한다.
- 실제 Connection 이 필요한 경우에 java.sql.PooledConnection 인터페이스를 사용하여 가져올 수 있다.
참고
- https://tomcat.apache.org/tomcat-11.0-doc/jdbc-pool.html
댓글
댓글 쓰기