JSP

[Camel][JSP] Connection Pool (커넥션 풀) with DBCP

Camelll 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일 경우 비활성화 커넥션을 추출할 때 커넥션의 유효 여부를 검사한 후, 유효하지 않은 커넥션은 커넥션 풀에서 제거.