DBCP (Connection Pool)

이수보🧑🏻‍💻·2022년 1월 22일
0

JSP

목록 보기
1/1
  • DBCP (Connection Pool)

DBCP 는 Database Connection Pool 의 약자로

말 그대로 데이터베이스와 연결된 커넥션을 미리 만들어 Pool 에 미리 저장해 두고 있다가 필요한 시점이 생기면 새로 생성이 아닌 기존에 있던 커넥션 객체를 반환하여 사용하고 사용한 객체를 다시 Pool에 저장하는 기법입니다.

그렇다면 Connection 이 무엇이냐??

저희는 앞서 JDBC 를 배웠습니다.
자바에서 데이터베이스를 이용하려면 DB와 JAVA를 서로 연결해주는 Connection 객체가 필요합니다.

Connection 객체의 생성
Connection con = DriverManager.getConnection( url, userID, Password );

문제는 여기서 부터 시작이 됩니다. Connection 객체를 한 번만 만들어 사용하면 문제가 없습니다. 그러나!! 코딩을 하며 한 번만 사용할 일이 있을까요?
조금만 생각 해봐도 DB와 연결이 필요한 경우는 상당히 많습니다.

1) 회원가입
2) 리스트 출력
3) 데이터 수정 등등....

한 사람은 위와 같이 3번의 DB 연결을 하지만 서버의 입장에서 접속자가 1000명이라면??
3000번의 Connection 이 이뤄집니다.

때문에 이러한 Connection을 필요할 때마다 생성하고 사용한다면 상당한 부담이 생길 수 있습니다.

때문에 Connection Pool 이 등장하게 됩니다.

  • Connection Pool의 장점

    • Pool 속에 미리 Connection이 생성되어 있어 Connection을 생성하고 연결하는 시간이 절약

    • Connection을 계속해서 재사용하기 때문에 생성되는 Connection의 수가 적다.

결국 위의 특징 덕분에 실행 속도가 빨라지면서 동시에 접속이 몰려도 서버가 다운되는 불상사가 발생할 경우를 줄일 수 있습니다.

사용법

style="color:olivedrab">사용하기 앞서 라이브러리 파일이 필요
https://mvnrepository.com/ 접속하여

를 다운 받은 후

빌드 패스 해준다.

이 외에도 Dynamic Web Project -> Web-Inf -> lib 파일에 Copy도 해준다.

이제 라이브러리를 사용할 준비가 끝이 났다. Connection Pool 을 설정해보자

package jdbc;

import java.sql.DriverManager;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.commons.dbcp2.ConnectionFactory;
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
import org.apache.commons.dbcp2.PoolableConnection;
import org.apache.commons.dbcp2.PoolableConnectionFactory;
import org.apache.commons.dbcp2.PoolingDriver;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;


// 서블릿 클래스
public class DBCPInit extends HttpServlet{

	private static final long serialVersionUID = 1L;
	
	@Override
	public void init() throws ServletException{
		// JDBC Driver 를 로딩
		loadJDBCDriver();
		
		// 커넥션 풀을 초기화
		initConnectionPool();
	}
	
	// 커넥션 풀이 내부에서 사용할 JDBC Driver를 로딩함.
	private void loadJDBCDriver() {
		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
		}catch(ClassNotFoundException e) {
			throw new RuntimeException("fail to load JDBC Driver", e);
		}
	}
	
	// 커넥션 풀을 초기화
	private void initConnectionPool() {
		try {
			// 풀에서 새로운 커넥션 객체를 생성할 때 팩토리가 있어야 함.
			// 즉, 커넥션풀에서 새로운 커넥션 객체를 생성할 때 사용할 커넥션 팩토리 생성
			String url = "jdbc:oracle:thin:@localhost:1521:xe";
			String user = "jspexam";
			String password = "java";
			ConnectionFactory connFactory = new DriverManagerConnectionFactory(url, user, password);
			
			
			// DBCP는 커넥션풀에 커넥션을 보관할 때 PoolableConnection을 사용
			// 이 Class 는 내부적으로 실제 Connection을 담고 있음
			// 즉, Connection Pool 을 관리
			PoolableConnectionFactory poolableConnFactory = new PoolableConnectionFactory(connFactory, null);
			
			// 커넥션관리자이기 때문에 커넥션이 유효한지(사용 가능한Connection인지)검사 해준다.
			poolableConnFactory.setValidationQuery("select 1");
			
			// 커넥션 풀의 설정 정보 생성
			GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
			
			// 유효 커넥션 검사 주기(5분)
			// 커넥션이 5분이 지나도 놀고 있다면 pool에서 제거하는 기준 시간이다.10 분 정도가 가장 적당하다. 
			// 또한 아무렇게나 다 제거하는 것이 아니다.
			// setMinIdle / setMaxTotal    커넥션의 최소/최대 개수를 고려하여 제거한다.
			poolConfig.setTimeBetweenEvictionRunsMillis(1000L * 60L * 5L);
	
			// 위의 검사를 실행할지 안할지 여부 설정 위를 설정했는데 이 여부 설정을 하지 않으면 XXX
			poolConfig.setTestWhileIdle(true);
			
			// 커넥션 최소 개수    / 커넥션 최대 개수
			poolConfig.setMinIdle(4);
			poolConfig.setMaxTotal(50);
			
			// 커넥션 풀의 설정 정보를 생성, 팩토리와 커넥션 풀 설정을 파라미터로 받음
			GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnFactory, poolConfig);
			
			// poolableConnFactory 에도 생성이 된 커넥션 풀을 연결
			poolableConnFactory.setPool(connectionPool);
			
			// 커넥션 풀을 제공하는 JDBC 드라이버를 등록함
			// oracle.jdbc.driver.OracleDriver
			Class.forName("org.apache.commons.dbcp2.PoolingDriver");
			
			PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
			
			// 커넥션 풀 드라이버에 생성된 커넥션 풀을 등록
			jdbc:apache:commons:dbcp
			driver.registerPool("ddit", connectionPool);
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		} 
		
	}
	
	
}

위와 같이 설정을 Pool에 대한 설정을 끝마치면
서버가 기동됨에 따라 위 내용의 Pool 이 같이 실행되게 하기 위해서
즉, 웹 어플리케이션이 시작할 때(톰캣 시작) DBCPInit 서블릿 클래스가 자동으로 시작되고, init() 메서드가 호출되게 하기 위해

  • Dynamic Web Project -> Web-INF -> web.xml 파일에 위 Pool 설정 내용을 등록해준다.
	<servlet>
		<servlet-name>oracleDriverLoader</servlet-name>
		<servlet-class>jdbc.DBCPInit</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

0개의 댓글