ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [DB] Connection Pool 정리
    Web 2021. 9. 11. 16:01

    Connection Pool 개념 


    동시 접속자가 가질 수 있는 커넥션(Connection) 객체를 하나로 모아놓고 관리하는 개념 

     

    웹 컨테이너가 실행되면서 DB와 연결된 커넥션 객체를 Pool 에 저장해두고 필요할 때마다 가져다쓰고 반환하는 개념이다. 남아있는 커넥션이 없다면 해당 Client는 대기상태로 전환시키고, 커넥션이 Pool에 반환되면 대기중인 Client 에게 순서대로 커넥션을 제공한다. 

     

    커넥션 풀에 커넥션을 너무 많이 생성해놓으면 메모리 소모가 크고, 적게 해놓으면 대기시간이 자주 발생하기 때문에 동시접속자 수 등을 고려하여 조정해야한다. 

     

    커넥션이 풀에 미리 생성되어 있어 커넥션을 생성하는데 드는 연결시간이 소비되지 않고, 닫는 시간이 소모되지 않는다. 

    커넥션 수를 제어 한 후 커넥션을 재사용하기 때문에 쉽게 다운되지 않는다는 특징이 있기 때문에 커넥션 풀을 잘 관리하는것은 중요하다. 

     

     

     

    예시와 상황을 통해 살펴보기


    애플리케이션 내의 오류가 명확히 확인되지 않은 상태에서 Out of memory 가 발생하거나, DB 서버에서부터 발생한 장애로 인해 웹 서버가 다운 될 때 대부분의 문제는 WAS 와 DB 서버간의 이슈이다. 

     

    WAS에서 DB 서버에 접근을 시작하고 데이터를 가져오기까지 단계에서 가장 비용이 많이드는 부분은 DB 서버에 최초로 연결되어 Connection 객체를 생성하는 부분이다. 

     

    String driverPath = "net.sourceforge.jtds.jdbc.Driver";
    String address = "jdbc:jtds:sqlserver://IP/DB";
    String userName = "user";
    String password = "password";
    String query = "SELECT ... where id = ?";
    try {
     	Class.forName(driverPath);
     	Connection connection = DriverManager.getConnection(address, userName, password);
     	PreparedStatement ps = con.prepareStatement(query);
     	ps.setString(1, id);
     	ResultSet rs = get.executeQuery();
     	// ....
    } catch (Exception e) { }
    } finally {
     	rs.close();
     	ps.close();
    }

     

    위 소스코드를 살펴보면 다음과 같다.

    1. DB 서버 접속을 위해 JDBC 드라이버를 로드한다.
    2. DB 접속 정보와 DriverManager.getConnection() Method를 통해 DB Connection 객체를 얻는다.
    3. Connection 객체로 부터 쿼리를 수행하기 위한 PreparedStatement 객체를 받는다.
    4. executeQuery를 수행하여 그 결과로 ResultSet 객체를 받아서 데이터를 처리한다.
    5. 처리가 완료되면 처리에 사용된 리소스들을 close하여 반환한다.

     

    출처 https://www.holaxprogramming.com/2013/01/10/devops-how-to-manage-dbcp/

    HTTP 요청에 따라 Thread 를 생성하게 되고 비지니스 로직에 맞게 DB 서버로부터 데이터를 얻게된다. 모든 요청이 DB접속을 위해 Driver를 로드하고 Connection 객체를 생성하여 연결한다면 많은 시간비용과 부하가 발생할 것이다. 

     

    이러한 문제를 해결하기 위해 DBCP(Database Connection Pool)를 이용한다.

     

    DBCP를 이용하면 HTTP 요청마다 1-5 단계를 거치지 않고 다수의 HTTP 요청에 대한 Thread를 효율적으로 처리할 수 있다.

     

     

     

    Connection Pool 은 어떻게 동작할까?


    1. WAS 가 실행되면 설정해놓은 DB Connection 객체를 생성하고 Pool 이라는 공간에 저장해둔다.

    2. HTTP 요청에 따라 필요할 때 Pool 에서 Connection 객체를 가져다 쓰고 반환한다. 

     

    출처 https://www.holaxprogramming.com/2013/01/10/devops-how-to-manage-dbcp/

     

    Connection Pool 을 어플리케이션에 맞게 효율적으로 관리하기 위한 설정값들이 존재하며, DBCP 라이브러리를 통해 설정이 가능하다. 

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

     

    커넥션을 최대로 활용할 수 있을 때 4개는 사용중이고 4개는 대기중인 상태(Idle)라면 커넥션 풀의 상태는 아래와 같다. 

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

    MaxActive >= InitialSize 

    - 최대 커넥션 개수는 초기에 생성할 커넥션 개수와 같거나 크게 설정해야한다.

     

    MaxActive = MaxIdle 

    - 이 둘의 값은 같은 것이 바람직하다.

     

    InitialSize MaxActive MaxIdle  MinIdle 항목은 동일한 값으로 통일해도 무방하다.

    - 커넥션 개수와 관련된 가장 중요한 성능요소는 MaxActive 이다. 

    - MaxActive 값은 DBMS 의 설정과 애플리케이션의 서버개수, WAS 에서 동시에 처리할 수 있는 사용자 수 등을 고려해서 설정해야하며 DBMS 가 수용할 수 있는 커넥션 개수를 확인한 후에 애플리케이션 서버 인스턴스 1개가 사용하기 적절한 개수를 설정한다. 

    - 사용자가 몰려 커넥션을 많이 사용할 때 MaxActive 값이 충분히 크지 않다면 병목지점이 될수 있으니 유의하자. 

     

    WAS에서 성능에 가장 많은 영향을 주는 부분은 Thread 와 Connection Pool의 개수이다. 

    - 직접적으로 메모리와 관련있기 때문에 많이 사용하면 메모리를 많이 점유하게 되고 적게 지정하면 많은 요청을 처리하지 못하고 대기할 수 밖에 없다.

     

     

     

    DBCP 관리는 어떻게 해야할까 


    1. 실제 운영할 시스템 환경에서 성능 테스트를 진행하는것이 가장 좋다.

    - 시스템 환경에 최적화된 값을 찾자. 

     

    2. WAS의 Thread 수는 DBCP의 개수보다 여유있게 설정하자. 

    - 애플리케이션에 대한 모든 요청이 DB 접근이 아닐수 있다. 

    - 10개정도 더 지정하는 것이 바람직하며, 요청이 얼마나 들어오는지 파악하여 최적화된 값을 찾는 것이 중요하다. 

     

     

     

    참고자료


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

    https://www.holaxprogramming.com/2013/01/10/devops-how-to-manage-dbcp/

    https://brownbears.tistory.com/289

    'Web' 카테고리의 다른 글

    Thread Pool (Java, Tomcat, SpringBoot)  (0) 2024.07.25
    XML & JSON & YAML  (0) 2021.10.30
    쿠키(Cookie)와 세션(Session) 정리  (0) 2021.09.04
    HTTP 프로토콜 정리  (0) 2021.08.28
Designed by Tistory.