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() 메서드가 호출되게 하기 위해
<servlet>
<servlet-name>oracleDriverLoader</servlet-name>
<servlet-class>jdbc.DBCPInit</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>