본문 바로가기

PROGRAMMING/JSP

커넥션 풀(Connection Pool)

오늘은 커넥션 풀에 대한 포스팅을 해볼까 한다.


커넥션 풀이란 무엇일까?

'풀'이란 단어를 보니, 수영장 풀이 생각나는 듯하다.

그럼 연결...수영장....뭘까?


1) 커넥션 풀

: 데이터 베이스와 연결된 커넥션을 미리 만들어서 풀(pool) 속에 저장해 두고 있다가 필요할 때에 커넥션을 풀에서 가져다 쓰고 다시 풀에 반환하는 기법을 의미한다.

이렇게 풀 속에 미리 생성되어 있는 커넥션을 가져다가 사용하고, 사용이 끝나면 커넥션을 풀에 반환한다.


2) 커넥션 풀의 특징

 - 풀 속에 미리 커넥션이 생성되어 있기 때문에 커넥션을 생성하는 데 드는 연결 시간이 소비되지 않는다.

 - 커넥션을 계속해서 재사용하기 때문에 생성되는 커넥션 수가 많지 않다.


☞ 커넥션 풀을 사용하면 커넥션을 생성하고 닫는 시간이 소모되지 않기 때문에 그만큼 어플리케이션의 실행 속도가 빨라지며, 또한 한 번에 생성될 수 있는 커넥션 수를 제어하기 때문에 동시 접속자 수가 몰려도 웹 어플리케이션이 쉽게 다운되지 않는다.


3) 그렇다면 동시 접속자 처리는..?

: 커넥션 풀에서 생성되어 있는 커넥션의 갯수는 한정적이다. 그렇다면 동시 접속자가 많아지면 어떻게 될까?

커넥션 풀은 누군자 접속하면 커넥션 풀에 남아 있는 커넥션을 제공하는 식이다. 하지만 남아있는 커넥션이 없을 경우 해당 클라이언트는 대기 상태로 전환이 되고, 커넥션이 반환되면 대기하고 있는 순서대로 커넥션이 제공된다.


4) 커넥션 풀의 속성 사용

: 커넥션 풀은 여러 속성을 지정할 수 있다.

 속성

설명

maxActive 

커넥션 풀이 제공할 최대 커넥션 갯수 

whenExhaustedAction

커넥션 풀에서 가져올 수 있는 커넥션이 없을 때 어떻게 동작할지를 지정.

0일 경우 에러 발생

1일 경우 maxWait 속성에서 지정한 시간만큼 커넥션을 구할때까지 기다림

2일 경우 일시적으로 커넥션을 생성해서 사용

 maxWait

whenExhaustedAction 속성의 값이 1일 때 사용되는 대기 시간.

단위는 1/1000초, 0보다 작을 경우 무한히 대기

maxIdle 

사용되지 않고 풀에 저장될 수 있는 최대 커넥션 갯수.

음수일 경우 제한이 없음 

minIdle 

사용되지 않고 풀에 저장될 수 있는 최소 커넥션 갯수. 

testOnBorrow 

true일 경우 커넥션 풀에서 커넥션을 가져올 때 커넥션이 유효한지의 여부를 검사 

testOnReturn 

true일 경우 커넥션 풀에 커넥션을 반환할 때 커넥션이 유효한지의 여부를 검사 

timeBetweenEvctionRunsMillis 

사용되지 않는 커넥션을 추출하는 쓰레드의 실행 주기 지정.

양수가 아닐 경우 실행되지 않는다.

시간 단위는 1/1000초. 

numTestsPerEvictionRun 

사용되지 않는 커넥션을 몇 개 검사할 지 지정 

minEvictableIdleTimeMillis 

사용되지 않는 커넥션을 추출할 때 이 속석에서 지정한 시간 이상 비활성화 상태인 커넥션만 추출.
양수가 아닌 경우 비활성화된 시간으로는 풀에서 제거되지 않음.
시간 단위는 1/1000초 

testWhileIdle 

true일 경우 비활성화 커넥션을 추출할 때 커넥션이 유효한지의 여부를 검사해서 유효하지 않은 커넥션은 풀에서 제거 


5) 커넥션 풀을 사용하려면..?

DBCP 다운로드 : 2013.08.04) commons-dbcp DOWNLOAD

POOL 다운로드 : 2013.08.04) commons-pool DOWNLOAD


위의 링크를 클릭하여 들어간 다운로드 페이지에서 각 dbcp와 pool을 다운로드 받아 WEB-INF/lib 디렉터리에 복사해준다.

그리고 커넥션 풀 설정 파일을 작성해주고 커넥션 풀과 관련된 JDBC 드라이버를 로딩해주는 클래스파일을 작성하고, web.xml 파일에 설정해주면 웹 어플리케이션이 시작할 때 DBCPInit 서블릿 클래스가 자동으로 시작되는 것을 볼 수 있다.


pool.jocl(커넥션 풀 설정 파일)


<object class="org.apache.commons.dbcp.PoolableConnectionFactory" 

xmlns="http://apache.org/xml/xmlns/jakarta/commons/jocl">


<object class="org.apache.commons.dbcp.DriverManagerConnectionFactory">

<string value="jdbc:mysql://localhost:3306/데이터베이스이름?useUnicode=true&amp;characterEncoding=utf8"/>

<string value="데이터베이스 사용자 계정 이름"/>

<string value="데이터베이스 사용자 계정 암호"/>

</object>

<object class="org.apache.commons.pool.impl.GenericObjectPool">

<object class="org.apache.commons.pool.PoolableObjectFactory" null="true" />

    <int value="10" /> <!-- maxActive -->

    <byte value="1" /> <!-- whenExhaustedAction -->

    <long value="10000" /> <!-- maxWait -->

    <int value="10" /> <!-- maxIdle -->

    <int value="3" /> <!-- minIdle -->

    <boolean value="true" /> <!-- testOnBorrow -->

    <boolean value-"true" /> <!-- testOnReturn -->

    <long value="600000" /> <!-- timeBetweenEvctionRunsMillis -->

    <int value="5" /> <!-- numTestsPerEvictionRun -->

    <long value="3600000" /> <!-- minEvictableIdleTimeMillis -->

    <boolean value="true" /> <!-- testWhileIdle -->

</object>

<object class="org.apache.commons.pool.KeyedObjectPoolFactory" null="true"/>

<string null="true"/>

<boolean value="false"/>

<boolean value="true"/>

</object>


JDBC 드라이버를 로딩하는 코드


import javax.servlet.http.HttpServlet;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import java.util.StringTokenizer;


public class DBCPInit extends HttpServlet {

public void init(ServletConfig config) throws ServletException {

try{

String drivers = config.getInitParameter("jdbcdriver");

StringTokenizer st = new StringTokenizer(drivers, ",");

while(st.hasMoreTokens()){

String jdbcDriver = st.nextToken();

Class.forName(jdbcDriver);

}

Class.forName("org.apache.commons.dbcp.PoolingDriver");

}catch(Exception ex){

throw new ServletException(ex);

}

}


}


web.xml에 추가할 부분


<servlet>

<servlet-name>DBCPInit</servlet-name>

<servlet-class>DBCPInit의 경로</servlet-class>

<init-param>

<param-name>jdbcdriver</param-name>

<param-value>com.mysql.jdbc.Driver</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>


pool을 설정해주고 난 뒤 커넥션 풀로부터 커넥션을 사용하려면


String jdbcDriver = "jdbc:apache:commons:dbcp:/pool";

String query  = "....";

conn = DriverManager.getConnection(jdbcDriver);


이런 식으로 사용해 주면 된다.


몇 가지의 코드만 작성해주면 그대도 풀을 사용할 수 있다.

사실 개인적으로 테스트해보기 위해 소규모로 개발을 진행하면 Pool을 왜 사용하는지는 몸소 못느낄 것 같다. 내가 그랬기 때문이다.

접속자수가 많은 웹사이트에서 Pool을 사용 안하고 있었다면, 그 때 Pool을 사용하여 다시 서비스를 제공한다면 그 때 성능이 좋아진 것을 느낄 수 있지 않을까 한다.

'PROGRAMMING > JSP' 카테고리의 다른 글

MVC1 vs MVC2  (126) 2013.08.26
Cygwin에서의 JSP 개발환경 설정.  (3) 2013.05.03