[SQL | DB] DBCP(Database Connection Pool)

Jeini·2023년 6월 2일
0

🗂️ DB | SQL

목록 보기
5/5
post-thumbnail

💡 DBCP(DataBase Connection Pool)


✔️ DB와 커넥션을 맺고 있는 객체를 관리하는 역할

클라이언트와 서버 사이드인 웹 어플리케이션에서, 사용자의 요청에 따라 Connection이 생성된다면 수 많은 사용자가 요청을 했을 때 서버에 과부하가 걸리게 된다.

이러한 상황을 예방하기 위해 미리 일정 갯수의 Connection을 만들어 Pool에 저장을 하고, 사용자의 요청이 발생하면 Connection을 제공하고 사용자와의 연결이 종료된다면 Pool에 다시 반환하여 보관하는 것을 의미한다.

⚙️ Connection pool 동작

  1. 여러 개의 DB Connection을 하나의 Pool에 모아놓고 관리

  2. DB 커넥션 객체를 여러 개 생성한 뒤 Pool에 담아놓고 필요할 때 불러와서 사용

  3. 만약, 빌려줄 수 있는 Connection이 없다면 Connection 객체가 반환할 때 까지 클라이언트는 대기 상태로 전환

  4. 사용이 끝난 커넥션 객체는 다른 작업에서 다시 사용할 수 있도록 Pool에 반환

💡 DBCP는 왜 쓰는 걸까?


✔️ 효율적인 DB 커넥션을 위해 DBCP를 사용하는 것
✔️ 큰 비용의 문제를 해결하기 위해 DBCP를 사용

JDBC는 Java DataBase Connectivity 의 약자로 자바에서 데이터베이스에 연결하기 위한 인터페이스이다.

Oracle, MySQL, MsSQL 등 데이터 베이스는 JDBC를 사용하기 위한 각각의 Driver를 제공한다. JDBC는 이 Driver를 통해 DB에 접속한다.

그럼 JDBC만 있으면 DB접속이 되는데 DBCP는 왜 쓰지? 라는 궁금증이 생긴다.
답은 '효율' 이다.

웹 어플리케이션은 CRUD와 같은 작업을 처리할 때 주로 데이터베이스를 이용한다.

DBMS나 기타 외부와의 접속이 빈번하게 필요한 시스템에는 반드시 존재해야 하는 기능인데 데이터베이스와 Connection을 맺는 작업은 매우 느리며 자원을 많이 소모하는 작업이다.
➡️ 서버가 물리적으로 데이터베이스 서버에 연결되어 Connection을 맺는 작업은 비용이 큰 부분 이다.

만약, 다수의 사용자들이 동시다발적으로 데이터베이스의 Connection 연결을 요청한다면 최악의 경우 서버가 다운이 될 수 있다. 따라서 이러한 큰 비용의 문제를 해결하기 위해 DBCP를 사용할 수 있다.

💡 DBCP의 옵션


✏️ maxActive

  • 동시에 사용할 수 있는 최대 커넥션 개수

  • maxActive의 값은 DBMS의 설정과 애플리케이션 서버 갯수, Apache, Tomcat 등에서 동시에 처리할 수 있는 사용자 수 등을 고려해서 설정해야 한다.

✏️ maxIdle

  • Connection Pool에 반납할 때 최대로 유지될 수 있는 커넥션 개수

✏️ minIdle

  • 최소한으로 유지할 커넥션 개수

  • maxActive와 maxIdle 값이 동일한 것이 좋다.

✏️ initialSize

  • 최소로 getConnection() Method를 통해 커넥션 풀에 채워 넣을 커넥션 개수

위와 같은 설정 외에도 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();
	}
}
  • 결과를 보면 DBMS를 이용하는 것이 훨씬 빨랐다. 그러므로 더 효율적으로 사용한다는 것을 알 수 있다.

Reference
: https://zzang9ha.tistory.com/376
: https://aljjabaegi.tistory.com/402

profile
Fill in my own colorful colors🎨

0개의 댓글