✔️ DB와 커넥션을 맺고 있는 객체를 관리하는 역할
클라이언트와 서버 사이드인 웹 어플리케이션에서, 사용자의 요청에 따라 Connection이 생성된다면 수 많은 사용자가 요청을 했을 때 서버에 과부하가 걸리게 된다.
이러한 상황을 예방하기 위해 미리 일정 갯수의 Connection을 만들어 Pool에 저장을 하고, 사용자의 요청이 발생하면 Connection을 제공하고 사용자와의 연결이 종료된다면 Pool에 다시 반환하여 보관하는 것을 의미한다.
여러 개의 DB Connection을 하나의 Pool에 모아놓고 관리
DB 커넥션 객체를 여러 개 생성한 뒤 Pool에 담아놓고 필요할 때 불러와서 사용
만약, 빌려줄 수 있는 Connection이 없다면 Connection 객체가 반환할 때 까지 클라이언트는 대기 상태로 전환
사용이 끝난 커넥션 객체는 다른 작업에서 다시 사용할 수 있도록 Pool에 반환
✔️ 효율적인 DB 커넥션을 위해 DBCP를 사용하는 것
✔️ 큰 비용의 문제를 해결하기 위해 DBCP를 사용
JDBC는 Java DataBase Connectivity 의 약자로 자바에서 데이터베이스에 연결하기 위한 인터페이스이다.
Oracle, MySQL, MsSQL 등 데이터 베이스는 JDBC를 사용하기 위한 각각의 Driver를 제공한다. JDBC는 이 Driver를 통해 DB에 접속한다.
그럼 JDBC만 있으면 DB접속이 되는데 DBCP는 왜 쓰지? 라는 궁금증이 생긴다.
답은 '효율' 이다.
웹 어플리케이션은 CRUD와 같은 작업을 처리할 때 주로 데이터베이스를 이용한다.
DBMS나 기타 외부와의 접속이 빈번하게 필요한 시스템에는 반드시 존재해야 하는 기능인데 데이터베이스와 Connection을 맺는 작업은 매우 느리며 자원을 많이 소모하는 작업이다.
➡️ 서버가 물리적으로 데이터베이스 서버에 연결되어 Connection을 맺는 작업은 비용이 큰 부분 이다.
만약, 다수의 사용자들이 동시다발적으로 데이터베이스의 Connection 연결을 요청한다면 최악의 경우 서버가 다운이 될 수 있다. 따라서 이러한 큰 비용의 문제를 해결하기 위해 DBCP를 사용할 수 있다.
동시에 사용할 수 있는 최대 커넥션 개수
maxActive의 값은 DBMS의 설정과 애플리케이션 서버 갯수, Apache, Tomcat 등에서 동시에 처리할 수 있는 사용자 수 등을 고려해서 설정해야 한다.
최소한으로 유지할 커넥션 개수
maxActive와 maxIdle 값이 동일한 것이 좋다.
위와 같은 설정 외에도 validationQuery
, testOnCreate
, testOnBorrow
, testOnReturn
, defaultAutoCommit
, defaultReadOnly
등등 다양한 설정이 존재한다.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;
// datasource가 정말로 성능 효율이 있는지 알아보는 class
public class DBCP_vx_Normal {
private static BasicDataSource ds;
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
static {
ds = new BasicDataSource();
ds.setUrl("jdbc:mysql://localhost:3306/bookDB");
ds.setUsername("root");
ds.setPassword("12345678");
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setInitialSize(10); // 처음 가지고 몇개 시작할-> 어플리케이션의 규모에 따라서 달라질 수 있다.
ds.setMaxActive(10); // 최대 몇개까지 connection을 커버하는가. 10명까지 주는데 11명이 들어왔다. 한놈의 끝낼때까지 대기탄다.
ds.setMaxIdle(10);
ds.setMinIdle(10);
}
public static void normalCase() {
Connection con = null;
long time = System.currentTimeMillis();
for(int i = 0; i < 1000; i++) {
try {
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookDB", "root", "12345678");
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
con.close();
} catch (Exception e) {}
}
}
time = System.currentTimeMillis() - time;
System.out.println("normal: " + time + "ms");
}
public static void dbcpCase() {
Connection con = null;
long time = System.currentTimeMillis();
for(int i = 0; i < 1000; i++) {
try {
con = ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
con.close();
} catch (Exception e) {}
}
}
time = System.currentTimeMillis() - time;
System.out.println("dbcp: " + time + "ms");
}
public static void main(String[] args) {
normalCase();
dbcpCase();
}
}
Reference
: https://zzang9ha.tistory.com/376
: https://aljjabaegi.tistory.com/402