7.1 연결 풀

오늘 우리는 데이터베이스를 훨씬 더 전문적으로 사용하는 방법을 배웁니다. 이제 스레드 풀 또는 연결 풀 에 대해 영어로 이야기하겠습니다 .

데이터베이스에 연결하는 데 약간의 시간이 걸립니다. 특히 데이터베이스가 원격인 경우. 각 요청에 대해 데이터베이스에 연결하면 응용 프로그램의 응답 속도가 엄청나게 느려집니다. 소비할 자원은 말할 것도 없습니다.

이러한 문제에 대한 해결책으로 스레드 풀이라는 일부 세트에 베이스에 대한 연결을 저장하는 것이 제안되었습니다.

새로운 커넥션을 요청하면 커넥션 풀이 생성하고 닫히면 닫지 않고 커넥션 풀에 저장한다. 연결 풀에서 다시 연결을 요청하면 새 연결을 만드는 대신 이전 연결 중 하나를 제공합니다.

실제로 응용 프로그램은 일반 JDBC 드라이버의 래퍼이며 풀 작업을 위한 추가 기능이 있는 특수 드라이버를 통해 작동합니다. 이 상황은 다음과 같이 나타낼 수 있습니다.

연결 풀

프로그래머는 활성 연결 수, 시간 초과 등 연결 풀에 대한 설정을 수동으로 설정할 수 있습니다.

특히 극단적인 상황의 경우 연결 목록을 포함하는 클래스인 고유한 연결 풀을 작성할 수 있습니다. 연결을 다시 목록으로 반환하는 닫기 기능을 재정의하고 연결 열기 타이머와 같은 다른 많은 장점이 있습니다. 오랫동안 연결이 없으면 연결이 닫힙니다.

7.2* 인터페이스 DataSource 및 ConnectionPoolDataSource

스레드 풀은 일반적으로 DataSource 개체와 함께 작동합니다. 이 개체는 원격 데이터베이스의 추상화로 생각할 수 있습니다. Data Source라는 이름은 문자 그대로 Data Source로 번역될 수 있습니다. 일종의 암시입니다.

DataSource 개체는 데이터베이스에 대한 물리적 연결을 얻는 데 사용되며 DriverManager의 대안입니다. JDBC 드라이버를 등록할 필요가 없습니다. 연결을 설정하기 위해 적절한 매개변수를 설정하기만 하면 됩니다.getConnection() 메소드 실행.

DataSource 유형의 개체를 로컬로(응용 프로그램에서 직접) 만들 때 연결 매개 변수는 JDBC 드라이버 공급자가 제공하는 적절한 방법으로 설정됩니다. 이러한 메서드는 DataSource 인터페이스에 의해 정의되지 않습니다. 다른 공급업체의 DBMS에 연결하기 위한 매개변수의 유형과 수가 모두 다를 수 있기 때문입니다(예를 들어, 모든 DBMS가 드라이버 또는 네트워크 프로토콜의 유형을 지정해야 하는 것은 아닙니다).

따라서 Oracle DBMS를 사용할 때 해당 set 및 get 메소드를 사용하려면 DataSource 인터페이스를 구현하는 동일한 이름의 클래스 인스턴스인 OracleDataSource 유형의 오브젝트를 확보해야 합니다. 따라서 DataSource 유형의 개체를 만드는 이 방법은 코드의 이식성이 떨어지고 드라이버의 특정 구현에 대한 의존도를 낮춥니다.

다음은 DataSource 유형 개체의 로컬 사용을 설명하는 코드 예제입니다.

import java.sql.*;
import javax.sql.*;
import oracle.jdbc.driver.*;
import oracle.jdbc.pool.*;

public class DataSource {
    public static void main(String[] args) {
    	try {
        	OracleDataSource ods = new OracleDataSource();

        	ods.setUser("root");
        	ods.setPassword("secret");
        	ods.setDriverType("thin");
        	ods.setDatabaseName("test");
        	ods.setServerName("localhost");
        	ods.setPortNumber(1521);

        	Connection connection = ods.getConnection();
        	System.out.println("Connection successful!!!");

    	} catch (SQLException se) {
        	se.printStackTrace();
    	}
    	System.out.println("Goodbye!");
	}
}

7.3* JNDI 인터페이스

DataSource 유형 개체의 전체 기능은 JNDI 인터페이스 사용과 함께 나타납니다. JNDI는 하나의 서비스가 다른 서비스와 연결을 설정할 수 있도록 하는 대규모 서버 응용 프로그램을 위한 특수 서비스(디렉토리와 같은 것)입니다.

이름 및 디렉터리 서비스를 사용하면 미리 정의된 연결 매개 변수를 사용하여 시스템 관리자가 이전에 만든 DataSource 유형의 개체를 저장할 수 있습니다. 다음은 Sun에서 개발한 일부 표준 속성(매개변수) 이름입니다.

속성 이름 자바 데이터 유형 목적
데이터베이스 이름 데이터베이스 이름
서버 이름 서버 이름
사용자 사용자 이름(ID)
비밀번호 사용자 암호
포트 번호 정수 DBMS 서버 포트 번호

DataSource와 JNDI 인터페이스의 조합은 J2EE 구성 요소 기술을 기반으로 하는 다중 계층 엔터프라이즈 애플리케이션 개발에서 핵심적인 역할을 합니다.

애플리케이션 코드에서 DataSource와 JNDI 인터페이스의 조합을 사용하는 경우 이름 지정 및 디렉토리 서비스에서 DataSource 유형의 객체를 요청하기만 하면 됩니다. 이 경우 드라이버의 특정 구현에 종속된 연결 및 프로그램 코드의 세부 정보는 이름 및 디렉터리 서비스에 저장된 개체의 응용 프로그램에서 숨겨집니다.

따라서 DataSource 및 JNDI 유형의 객체 공유에는 서로 독립적으로 수행되는 두 단계가 포함됩니다.

  1. Context.bind()를 사용하여 명명 및 디렉터리 서비스에 DataSource 유형의 명명된 개체를 저장해야 합니다 javax.naming.
  2. 를 사용하여 응용 프로그램의 이름 지정 및 디렉터리 서비스에서 DataSource 유형의 개체를 요청합니다 Context.lookup(). 그런 다음 해당 방법을 사용하여 DataSource.getConnection()데이터베이스에 연결할 수 있습니다.

다음은 JNDI 인터페이스와 OracleDataSource 타입의 객체를 함께 사용하는 예이다.

// Create a key JNDI object
Hashtable env = new Hashtable();
env.put (Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
env.put (Context.PROVIDER_URL, "file:JNDI");
Context ctx = new InitialContext(env);

// Get the DataSource object by its name
DataSource ods = (DataSource) ctx.lookup("myDatabase");

// Get the Connection from the DataSource object
Connection connection = ods.getConnection();
System.out.println("Connection successful!!!");

우리는 JNDI의 작업을 분석하지 않을 것입니다. 이것은 이 과정의 범위를 벗어납니다. 이 접근 방식은 대규모 애플리케이션에서 매우 일반적이라는 점을 알아두시기 바랍니다. 앞으로 이와 같은 코드를 보게 되더라도 당황하지 마십시오.

작동 방식은 중요하지 않습니다. JNDI 서비스를 사용하면 서비스 디렉터리에 등록된 모든 서비스의 프록시 개체를 가져올 수 있다는 점만 알면 됩니다. 이것이 DataSource 개체를 가져와서 데이터베이스 작업에 사용하는 방법입니다.

7.4 연결 풀 예

우리가 시작한 곳인 연결 풀로 돌아가 봅시다.

프로그램의 Java 프로그래머는 연결 풀의 다양한 구현을 포함하는 라이브러리를 매우 자주 사용합니다. 그중 가장 인기있는 세 가지가 있습니다.

  • 아파치 커먼즈 DBCP
  • C3PO
  • 히카리CP

Apache 프로젝트는 우수한 연결 풀을 처음으로 만들었으며 Tomcat 웹 서버 내부에서도 사용됩니다. 작업의 예:

public class DBCPDataSource {

    private static BasicDataSource ds = new BasicDataSource();
    static {
    	ds.setUrl("jdbc:h2:mem:test");
    	ds.setUsername("user");
    	ds.setPassword("password");
    	ds.setMinIdle(5);
    	ds.setMaxIdle(10);
    	ds.setMaxOpenPreparedStatements(100);
    }

    public static Connection getConnection() throws SQLException {
    	return ds.getConnection();
    }

    private DBCPDataSource(){ }
}

두 번째로 인기 있는 풀은 C3PO 입니다 . 이상한 이름, 동의합니다. C3PO라는 이름은 스타워즈의 c3po 로봇에서 따온 것입니다. 또한 CP는 Connection Pool의 약자입니다.

public class C3p0DataSource {

    private static ComboPooledDataSource cpds = new ComboPooledDataSource();
    static {
    	try {
        	cpds.setDriverClass("org.h2.Driver");
        	cpds.setJdbcUrl("jdbc:h2:mem:test");
        	cpds.setUser("user");
        	cpds.setPassword("password");
    	} catch (PropertyVetoException e) {
            // handle the exception
    	}
    }

    public static Connection getConnection() throws SQLException {
    	return cpds.getConnection();
    }

    private C3p0DataSource(){}
}

이에 대한 문서는 공식 페이지 에서 찾을 수 있습니다 .

마지막으로 우리 시대에 가장 인기 있는 연결 풀은 HikariCP 입니다 .

public class HikariCPDataSource {

    private static HikariConfig config = new HikariConfig();
    private static HikariDataSource ds;

    static {
    	config.setJdbcUrl("jdbc:h2:mem:test");
    	config.setUsername("user");
    	config.setPassword("password");
    	config.addDataSourceProperty("cachePrepStmts", "true");
    	config.addDataSourceProperty("prepStmtCacheSize", "250");
    	config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
    	ds = new HikariDataSource(config);
    }

    public static Connection getConnection() throws SQLException {
    	return ds.getConnection();
    }

    private HikariCPDataSource(){}
}

다음은 그의 공식 GitHub 페이지 입니다 .

그리고 구성에 대한 좋은 기사입니다 .