본문 바로가기
데이터베이스/JDBC

[JDBC] 커넥션 풀

by 거북이의 기술블로그 2024. 11. 4.
1. 커넥션 풀이란?
2. 커넥션 풀 구조
3. 커넥션 풀 오픈소스
4. 커넥션 풀 직접 구현

 

Connection Pool 이란?

DB와 연결을 짓는 과정자체를 Connection 과정이라고 일컫는다.
여기서 매번 DB와의 연결을 위해서 TCP/IP 3wayhandshake를 과정을 거치기도 하고, 인증과정도 거치게된다.
이런 과정속에서 인증하고 커넥션 작업을 하는데에만 리소스를 많이 사용하게 될 수도 있기에 미리 커넥션을 맺어놓아 보관해두는 공간을 "Connection Pool"이라고 한다.

  • 위의 그림과 같은 과정을 통해 DB의 커넥션을 가지고 올 수 있다
    • 단점
      • 매번 요청시마다 커넥션을 맺는과정을 거쳐야한다. (리소스를 효율적으로 사용하지 못함)
      • DB의 상황에따라 많은 수의 쿼리 요청을 받지 못할 가능성이 존재한다.
      • 데이터베이스마다 커넥션 과정의 소요시간은 다르다

 

Connection Pool 구조

  • Connection Pool이란 쉽게 말해서, 미리 커넥션 과정을 맺어놓고 맺어져 있는 커넥션을 사용하고 반환을 반복하는 공간을 말한다
  • 커넥션의 개수의 경우 보통은 10개를 기본으로 설정하고 서버 스펙에 따라 상이하게 설정할 수 있다
  • 애플리케이션 로직에서는 커넥션 풀에 있는 커넥션을 조회하고 반환하는 작업을 통해 빠르게 DB작업을 이행할 수 있다

 

Connection Pool 오픈소스

1. Commons-dbcp2
2. Tomcat-jdbc pool
3. HikariCP (현재 주로 사용됨)
...
  • DataSource 인터페이스를 통해서, 오픈소스를 이용하여 Connection Pool을 이용할 수 있음
  • OCP, DI를 지키며 구현이 가능

//test
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(ConnectionConst.URL);
dataSource.setUsername(ConnectionConst.USERNAME);
dataSource.setPassword(ConnectionConst.PASSWORD);

repository = new MemberRepositoryV1(dataSource);



//repositoryV1 Class
private final DataSource dataSource;

    public MemberRepositoryV1(DataSource dataSource){
        this.dataSource = dataSource;
    }

 

 

Connection Pool 직접 구현

  • 생성자를 통해, 커넥션 생성 ( intialSize를 통해 첫 커넥션 수 지정 )
  • maxSize를 통해, 커넥션 생성 제한
문제)
여러 곳에서 쓰레드로 요청하게 되면, getConnection 메서드에서 최대개수 이상으로 커넥션을 생성할 수 있ㅇ므
( * lock 이 필요 )
- DataSource 인터페이스도 사용하기에 제한적 ( 내부적으로 로직을 통해 getConnection이 발생 )
- 실사용하기 위해서는 오픈소스를 이용해서 하는 편이 안정성과 성능이 더 좋아보임..
public class ConnectionPoolEX {
    private BlockingQueue<Connection> connectionPool;
    private int maxPoolSize;
    private String jdbcURL;
    private String jdbcUser;
    private String jdbcPasswd;

    public ConnectionPoolEX(int initialSize,int maxPoolSize, String jdbcURL, String jdbcUser, String jdbcPasswd) throws SQLException{
        this.connectionPool = new LinkedBlockingQueue<>();
        this.maxPoolSize = maxPoolSize;
        this.jdbcURL = jdbcURL;
        this.jdbcUser = jdbcUser;
        this.jdbcPasswd = jdbcPasswd;

        for (int i = 0; i<initialSize; i++){
            connectionPool.add(createConnection());
        }
    }

    private Connection createConnection() throws SQLException {
        return DriverManager.getConnection(jdbcURL,jdbcUser,jdbcPasswd);
    }

    public Connection getConnection() throws InterruptedException, SQLException{

        Connection connection = connectionPool.poll();

        if (connection == null){
            if(connectionPool.size() < maxPoolSize){
                connection = createConnection();
            }else{
                connection = connectionPool.take(); // 요소가 사용가능할때까지 대기
            }
        }

        return connection;


    }

    public void releaseConnection(Connection connection){
        if(connection != null){
            connectionPool.offer(connection); // 꽉차자지 않았을경우, 삽입 (가득찬 경우 지정된 시간까지 대기)
        }
    }

    public void shutdown() throws SQLException{
        for (Connection connection : connectionPool) {
            connection.close();
        }
    }

}

 

'데이터베이스 > JDBC' 카테고리의 다른 글

[JDBC] 트랜잭션 매니저  (0) 2024.11.05
[JDBC] 트랜잭션  (0) 2024.11.05
[JDBC] JDBC CRUD 구축  (1) 2024.10.31
[JDBC] JDBC 와 최신 데이터 접근 기술 (Sql Mapper , ORM)  (1) 2024.10.31