ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Camel][JSP] Connection Pool (커넥션 풀) with DBCP
    JSP 2020. 3. 16. 22:26

    1. Connection Pool(커넥션 풀)이란?

    JSP 페이지를 실행할 때마다 Connection을 생성하고 닫는다면 시간적 비용이 많이 들기 때문에 접속자 수가 많은 웹 사이트의 경우 성능 저하가 발생할 수 있습니다. 이러한 성능 저하를 막기 위해서 커넥션 풀이라는 것이 사용됩니다. 

     

     커넥션 풀은 데이터베이스와 연결된 Connection을 미리 생성한 뒤 Pool이라는 곳에 저장해 두고, 필요할 때마다 꺼내서 사용한 뒤 사용이 끝나면 다시 Pool에 반환하는 기법입니다. 즉, 데이터베이스의 커넥션이 필요할 때 커넥션을 새로 생성하는 것이 아니기 때문에 생성을 위한 시간적 비용이 절감됩니다. 생성뿐만 아니라 커넥션의 종료를 위해 소모되는 시간도 절감할 수 있습니다. 

     

     이러한 특징은 한번에 생성될 수 있는 커넥션의 수를 제한하는 것이고, 이는 동시 접속자의 증가로 인한 웹페이지 다운을 완전하지는 않더라도 어느정도 방지할 수 있습니다. 

     

     

     

    2. DBCP (DataBase Connection Pool)

    2-1. Connection Pool 라이브러리 다운로드 및 추가

     DBCP API를 사용하기 위해서는 아래의 라이브러리가 필요합니다. Apache Commons 다운로드 페이지에서 다운받을 수 있습니다.  두 압축파일을 다운로드 받은 후 압축을 풀어보면 그 안에는 jar 형태의 파일이 있습니다. jar 파일을 WEB-INF/lib 디렉터리에 복사해서 넣어줍니다. 

    • commons-dbcp-버전-bin.zip
    • commons-pool-버전-bin.zip

    빨간색 사각형이 가리키는 DBCP zip파일 다운로드
    빨간색 사각형이 가리키는 Pool zip파일 다운로드

     

     

    2-2. Connection Pool 설정 파일 작성

     다음으로는 커넥션 풀 설정파일을 작성해야 합니다. 아래와 같이 커넥션 풀 설정파일을 작성하겠습니다. 

     

    ch2/WEB-INF/classes/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/ch2?useUnicode=true&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=UTC&amp;characterEncoding=utf8"/>
    		<string value="camel"/>
    		<string value="1234"/>
    	</object>
    	
    	<object class="org.apache.commons.pool.impl.GenericObjectPool">
    		<object class="org.apache.commons.pool.PoolableObjectFactory" null="true" />
    	</object>
    	
    	<object class="org.apache.commons.pool.KeyedObjectPoolFactory" null="true"/>
    	
    	<string null="true"/>
    	
    	<boolean value="false"/>
    	
    	<boolean value="true"/>
    </object>
    

     

    DBMS와 연결할때 사용할 JDBC URL과 사용자 계정, 패스워드를 지정해줍니다. 그리고 커넥션 풀과 관련된 추가 설정 정보 또한 지정해줬습니다.

    <string null="true"/>는 커넥션의 유효 여부를 검사하기 위해 사용할 Query입니다. Query를 지정하고 싶다면 <string value="select count(*) from member"/>와 같이 지정할 수 있습니다.

     처음 <boolean value="false"/>는 커넥션을 읽기 전용으로 생성할지 말지를 결정하는 부분입니다. false로 지정함으로써 insert, update, delete와 같은 작업을 수행할 수 있습니다. 

     두번째 <boolean value="true"/>는 커넥션 자동 commit 모드를 설정하는 부분입니다. true로 설정함으로써 자동 commit이 됩니다.

     또한 한가지 주의할 점이 있다면 커넥션 설정 파일은 XML 문서로 처리되기 때문에 JDBC URL을 표현할 때 사용되는 '&' 기호 대신에 '&amp;'를 사용한다는 점입니다. 

     

     

     

    2-3. Connection Pool 초기화

    이제 커넥션 풀 설정파일까지 적절할 위치에 위치시켜 주었다면 커넥션 풀을 초기화해줘야 합니다. 커넥션 풀을 사용하기 위해서는 커넥션풀과 관련된 JDBC 드라이버를 로딩해줘야 합니다. 그러므로 아래의 두 드라이버를 로딩해줘야 합니다. 

    • DBMS에 연결할 때 사용될 JBDC 드라이버
    • DBCP API의 JDBC 드라이버

    웹 어플리케이션이 시작될 때 자동으로 DBMS JDBC 드라이버를 로딩하는 것처럼, DBCP API의 JDBC 드라이버 역시 웹 어플리케이션이 시작될 때 자동으로 로딩되도록 하는 것이 편리하다고 할 수 있습니다. JDBC 드라이버 로딩과 관련된 내용은 이전 포스팅을 참고하시면 되겠습니다.

    2020/03/15 - [JSP] - [Camel][JSP] JDBC 프로그래밍 2부 in JSP

     

    [Camel][JSP] JDBC 프로그래밍 2부 in JSP

    이 포스팅은 이전 포스팅과 이어지는 내용입니다. 2020/03/14 - [JSP] - [Camel][JSP] JDBC 프로그래밍 1부 in JSP [Camel][JSP] JDBC 프로그래밍 1부 in JSP JDBC 프로그래밍이 대해 설명하기에 앞서 저는 MySQL..

    cameldev.tistory.com

    package jdbc.loader;
    
    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);
    		}
    	}
    }
    

    이전 포스팅에서와 마찬가지로 WEP-INF/web.xml 파일에 DBCPInit 클래스에 대한 설정 정보를 추가해 줘야합니다. 그렇게 되면 이제 웹 어플리케이션이 시작될 때 DBCPInit 클래스가 시작되도록 할 수 있습니다. 

     

    web.xml 

    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee">
    
    
    	<servlet>
    
    		<servlet-name>JDBCDriverLoader</servlet-name>
    
    		<servlet-class>jdbc.loader.Loader</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>
    
    
    	<servlet>
    
    		<servlet-name>DBCPInit</servlet-name>
    
    		<servlet-class>jdbc.loader.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>
    
    </web-app>

     

     

    2-4. Connection Pool의 Connection 사용

    커넥션 풀을 생성하고 초기화 했다면 커넥션풀의 Connection을 이제 사용할 수 있습니다. 커넥션 풀의 Connection은 일반적인 Connection과 사용방법이 동일합니다. 

     하지만, 한가지 차이점이 있습니다. JDBC URL에서 차이가 있습니다. 일반 커넥션 풀을 사용할 경우 JDBC URL을 아래와 같은 형식으로 입력해줘야 합니다.

    String jdbcDriver = "jdbc.apsche:commons:dbcp:/[pool이름]";
    

     저의 경우는 pool.jocl 파일으로 설정한 커넥션 풀을 사용하기 때문에 아래와 같이 코드를 작성했습니다. 

    String jdbcDriver = "jdbc.apsche:commons:dbcp:/pool";

    커넥션 풀에서 생성된 Connection의 close 메소드를 호출하면 일반 커넥션의 경우 커넥션이 종료되지만, 커넥션 풀의 Connection의 경우에는 커넥션 풀로 Connection을 반환합니다.  

     

     

     

    2-5. Connection Pool의 속성

     앞서 작성했던 커넥션 풀 설정 파일인 pool.jocl 에서는 커넥션 풀의 속성을 아무것도 지정하지 않았었습니다. 하지만 DBCP의 커넥션 풀은 다양한 속성을 지정할 수 있으며 지정방법은 아래의 태그 사이에 커넥션 풀 속성 값을 지정해 주면 됩니다. 

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

    속성 값을 지정해 준 예제 코드는 아래와 같습니다. 

     

    pool2.jocl

    <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>

    각 속성에 대한 설명은 아래의 표를 참고하기실 바랍니다. 

    속성 설명
    maxActive 커넥션 풀의 최대 커넥션의 수. DMBS의 수용가능 수준에 맞게 지정해야 성능저하를 막을 수 있다. 
    whenExhaustedAction 커넥션 풀에서 가져올 수 있는 커넥션이 없을 경우의 동작을 결정.
    maxWait whenExhaustedAction 속성의 값이 1이면 사용되는 대기시간. 음수 입력시 무한 대기.
    maxIdle 사용되지 않고 풀에 저장될 수 있는 최대 커넥션의 수. 음수일 경우 무한
    minIdle 사용되지 않고 풀에 저장될 수 있는 최소 커넥션의 수.
    testOnBorrow true일 경우 커넥션 풀에 커넥션을 가져올 때 커넥션의 유효 여부 검사
    testOnReturn true일 경우 커넥션 풀에 커넥션을 반환할 때 커넥션의 유효 여부 검사
    timeBetweenEvctionRunsMillis 사용되지 않은 커넥션을 추출하는 쓰레드의 실행 주기를 지정. 양수일 때만 실행.
    numTestsPerEvictionRun 사용되지 않는 커넥션을 몇 개 검사할지 지정
    minEvictableIdleTimeMillis 사용되지 않는 커넥션을 추출할 때 이 속성에서 지정한 시간 이상 비활성화 상태인 커넥션만 추출. 양수로 입력 되어야지만 이 속성으로 추출 가능.
    testWhileIdle true일 경우 비활성화 커넥션을 추출할 때 커넥션의 유효 여부를 검사한 후, 유효하지 않은 커넥션은 커넥션 풀에서 제거.

     

    댓글

Camel`s Tistory.