개발일기장

Java 데이터 접근 기술 - connection pool (2) 본문

JAVA

Java 데이터 접근 기술 - connection pool (2)

게슬 2023. 2. 6. 23:29
728x90

데이터베이스 커넥션을 획득하기 위한 복잡한 과정..

1. 애플리케이션 로직은 DB 드라이버를 통해 커넥션을 조회한다.
2. DB 드라이버는 DB와 TCP/IP 커넥션을 연결한다. 물론 이 과정에서 3 way handshake 같은 TCP/IP 연결을 위한 네트워크 동작이 발생한다.
3. DB 드라이버는 TCP/IP 커넥션이 연결되면 ID, PW와 기타 부가정보를 DB에 전달한다.
4. DB는 ID, PW를 통해 내부 인증을 완료하고, 내부에 DB 세션을 생성한다.
5. DB는 커넥션 생성이 완료되었다는 응답을 보낸다.
6. DB 드라이버는 커넥션 객체를 생성해서 클라이언트에 반환한다.

이렇게 나와있다

단순히 local에서 확인하는 정도면 느낄 수 없겠지만, 대량의 transaction 이 발생하는 상황에서는 저런 과정 모두가 부하의 원인이 됨.

 

그렇기 때문에 미리 connection pool을 만들어둔다.. 이런거는 그냥 cs면접에서도 이제는 안나올 기본적인..


그전에는 일반적으로 JDBC의 DriverManager를 통해서 connection 을 획득해왔음

return DriverManager.getConnection(url, user, password);

그런대 이렇게 하는 방식에서 HikariCP나 DBCP로 변경하게 되면 source code까지 변경해야하는 상황이 발생함

그래서 jdbc도 같은방식이지만 DataSource라는 Interface를 java.sql 패키지에서 제공해줌

각각의 connection pool방식들은 이것을 구현하기만 하면 기존 코드의 변경없이 connection을 가지고 올 수 있음


https://search.maven.org/search?q=com.zaxxer.hikaricp 

 

Maven Central Repository Search

 

search.maven.org

일단 여기서 HikariCP jar를 받아서 사용해보자

아 그냥 gradle로 할껄 그랬음 개귀찮

hikrai

그리고 강의에서는 DriverManagerDataSource가 나오는데 이거는 Spring이 해주는 거고 순수 Java에는 없어서 pass함.

그래서 Interface로 구현안했음.. 

public static Connection getConnection2(){
    try{
        HikariConfig hikariConfig = new HikariConfig(); // config정의
        hikariConfig.setJdbcUrl(url);
        hikariConfig.setUsername(user);
        hikariConfig.setPassword(password);

        DataSource dataSource = new HikariDataSource(hikariConfig); //datasource가져오기

        return dataSource.getConnection(); //connection 반환
    }catch (SQLException e){
        throw new IllegalStateException(e);
    }
}

이렇게 소스코드를 작성하고나서 실행해보면

애러발생한다

slf4j이놈을 넣어줘야 하는 것 같다.. 그냥 gradle이나 maven으로 할걸 그랬다

https://mvnrepository.com/artifact/org.slf4j/slf4j-api/1.7.36

여기서 다운받은 다음 그냥 외부라이브러리에 같이 넣어주기만 하면 된다..

conn = DBConnectionUtil.getConnection2();

앞에서 사용했던 connection얻는 method를 변경해주고 실행하면

불편s

log관련해서 무슨 문제가 있어서인지 빨간색이 뜨는데 뭐 또 부족한가보다

그래도 connection은 잘 얻어와서 실행은 잘 된다..

 

저거 지우고 싶으면

https://mvnrepository.com/artifact/org.slf4j/slf4j-simple/1.7.36

이거를 또 다운받아서 import해주어야한다

 

위에서 넣어준거는 그냥 API이고 밑에꺼는 구현체같은 느낌?

5개..

그리고 다시 실행해보면

이렇게 빨간색인데 문제가 있는것 같지는 않은 빨간색이다. 근대 왜 빨간색인지 모르겠는데 기분이 나쁘다....

근대 이거하면서 Java Interface에 static method정의는 할 수 있는데 body구현해야하고 override도 안되는거 알게됨


HikariCP, common-dbcp2 차이점.

스프링부트에서 default로 connection pool은 HikariCP임 근대 이거 안쓰고 common-dbcp쓰는 이유가 있을까

차이점?

이거는 내일해야지.. 잠온다.


일단 common-dbcp2에 대해서 아아아주 잘 설명해준 네이버d2 게시글이 있어서 읽어봤음

https://d2.naver.com/helloworld/5102792

그리고 이해는 한 20퍼 정도밖에 못한듯

아무튼 다운받고 확인해보자

https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi

 

DBCP – Download Apache Commons DBCP

Download Apache Commons DBCP Using a Mirror We recommend you use a mirror to download our release builds, but you must verify the integrity of the downloaded files using signatures downloaded from our main distribution directories. Recent releases (48 hour

commons.apache.org

commons-dbcp2

public static Connection getConnection3(){
    try{
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource.getConnection();
    }catch (SQLException e){
        throw new IllegalStateException(e);
    }
}

일단 이렇게 getConnection3을 만들어봤다(그냥 interface로 할걸 그랬음) 

그냥 될리가 없지

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/pool2/SwallowedExceptionListener

이렇게 나온다

확인해보니깐 디팬던시가 또 있는 놈이었음

apache common pool이랑 logger도 넣어줘야함.. -> 다들 Gradle,  Maven을 이용합니다.

 

아무튼 종속성 문제들을 다 해결하고나면 일단 dbcp도 결과가 잘 나오는것을 볼 수 있다.

근대 알고싶은것은 Hikari 이놈이랑 차이점임

 

일단 max/min 로 설정할 수 있는 것들을 찾아보자(javadoc보기 귀찮으니 그냥 대충 ㄱㄱ)

Hikari max
Hikrai min
dbcp2 max
dbcp2 min

딱 봐도 DBCP에서 설정할 수 있는것들이 많다.  (근대 스프링 default가 Hikari인거 보면 좋은 이유가 있겠죠..?)

공통적으로 connection pool의 개수를 설정을 할 수 있는데

1) 너무 적게 설정을 하게되면 -> 사용자가 많아지는 경우 병목이 발생 할 수 있고

2) 너무 많이 설정을 하면 -> 리소스 낭비가 될 수 있다 -> 그리고 데이터베이스를 혼자 사용하는것이 아니기 때문에 너무많은 connection을  idle하게 두면 좀 그럴거같다.

따라서 해당 서버에서 동시에 처리할 수 있는 사용자를 고려해서 pool의 크기를 설정해야 한다.

 

DBCP(Evictor)

dbcp에서는 Evictor thread가 따로 돌아가는데 이놈은 내부의 connection 자원들을 관리해줌.

1) connection이 유휴 상태에서 minEvictableIdleTimeMillis 이상만큼 있었다면 이놈을 처리해준다.

2) 물론 minIdle 밑으로 connection이 줄어들면 새로 만들어주는 역할을 한다.

3) 그리고 connection이 유효한지 minEvictableIdleTimeMillis 이하인 connection도 검사해준다.

이놈도 따로 돌아가는 thread이기 때문에 너무 자주 확인을 하게하면 이것도 문제가 될 수 있다.

HikariCP(House Keeper)

히카리의 house keeper도 evictor처럼 connection을 관리해주는 쓰레드인데 이거는 위의 3번처럼 connection의 유효성을 검사해주지 않는다. 그냥 minnumIdle이상의 connection이 있는 경우에만 설정된 idleTimeout 이상의 connection을 제거해준다.

그리고 connection pool에 머무를 수 있는 maxLifetime 옵션을 제공해서 connection 을 생성할 때마다 적절하게 변화를 줘서 스케쥴러에 등록시켜준다고 한다..(넘 복잡하다)

 

 

 

 

결론 : connection pool부터 DB까지 해서 어떠한 환경일때 어떻게 설정을 해야하는지에 대해서 많은 경험과 고민이 필요할 거 같다.......


참고 자료

https://d2.naver.com/helloworld/1321

https://kakaocommerce.tistory.com/45?category=368198 

 

JDBC 커넥션 풀들의 리소스 관리 방식 이해하기

이미 JDBC 커넥션 풀 관련 다양한 글들이 존재하지만 대부분 오래된 commons-dbcp 1.x 의 내용 위주라서 최근에 많이 사용되고 있는 tomcat-jdbc-pool과 hikariCP에 대한 내용을 추가로 조사하고 정리해 보았

kakaocommerce.tistory.com

Jdbc관련해서 이것도 읽어봐야할것 같다....

공부해야할거는 쌓이는데 계획을 못잡겠다..

728x90
Comments