Spring - ConnectionPool

유재학·2022년 11월 17일
0

기존 데이터베이스 접근 방식을 사용하다 문제점을 알게 되었습니다. 데이터베이스에 접근할 때마다 연결을 열고 닫는 과정에서 비용이 많이 든다 것이었습니다. 이번 포스트에서는 이러한 문제점을 해결하기 위한 방법인 ConnectionPool에 대해 정리해보았습니다.

DB Connection 문제점

기존 데이터베이스의 연결 흐름은 다음과 같습니다.

  1. 응용 프로그램이 데이터 소스에 데이터베이스 연결을 요청
  2. 데이터 소스는 데이터베이스 드라이버를 사용하여 데이터베이스 연결 수행
  3. 연결이 생성되고 TCP 소켓이 열림
  4. 응용 프로그램이 데이터베이스 작업 수행
  5. 연결이 닫히고 소켓이 닫힘

이 흐름에서 문제점은 연결을 열고 닫는 과정이 연결 흐름에 계속 포함되어 있다는 것입니다.

데이터베이스 연결은 TCP연결입니다. 따라서 클라이언트와 서버 사이의 연결을 위해서 3-way-handshaking 작업이 일어나게됩니다. 결국 DB에 쿼리를 요청할 때마다 3번의 패킷 교환을 통해 소켓을 형성하고 통신을 준비하는 과정을 거치게 되고 이러한 과정이 계속해서 반복된다면 네트워크 구간에서 병목의 원인이 될 수 있습니다.

결론적으로 기존 DB커넥션의 문제점은 WAS와 DB사이의 커넥션이 매우 느리며 많은 비용이 든다는 점이며, 다수의 사용자가 동시다발적으로 DB에 커넥션을 요청할 경우 병목현상이 발생할 수 있으며 최악의 경우엔 서버가 다운될 수 도 있다는 점입니다.

이러한 문제점을 해결하기 위한 방법으로는 DBCP가 있습니다.

DBCP

DBCP는 DataBase Connection Pool의 약자로, 데이터베이스에 연결되는 패턴의 일종입니다. 기존 DB연결 방식은 사용자 요청에 따라 커넥션을 생성할 경우 최악의 경우 서버가 다운될 수 있다는 문제점이 있다고 했습니다. DBCP는 이러한 문제점을 해결하기 위해 DBCP에서는 다음과 같은 DB연결 방식을 제공합니다.

  1. 미리 일정 갯수의 Connection을 만들어 Pool에 저장한다.
  2. 사용자의 요청이 발생하면 Connection을 제공한다.
  3. 사용자와의 연결이 종료된다면 Pool에 다시 반환하여 보관한다.(재사용을 위함)

좀 더 자세히 DBCP의 동작 원리를 살펴보겠습니다.

  1. Connection 요청
  2. 이전에 사용했던 Connection 정보 존재 여부 확인
  3. 이전에 사용했던 Connection 목록 중 사용 가능한 Connection 존재 여부 확인
  4. 전체 Connection 목록 중 사용 가능한 Connection 존재 여부 확인
  5. 사용 가능한 Connection이 존재하지 않으면 HandOffQueue를 Polling 하면서 다른 Thread가 Connection을 반납하기를 기다림
    • 지정한 TimeOut 시간까지 대기하다가 시간이 만료되면 Exception 던질 수 있음
  6. Connection 반환
  7. 사용자는 Connection을 반납하면 Connection Pool이 사용내역을 기록하고 HandOffQueue에 반납된 Connection을 삽입함
    • HandOffQueue를 Polling 하던 Thread는 Connection을 획득하고 작업을 이어나갈 수 있게 됨
    • Connection Pool이 사용내역을 기록하는 이유는 Connection 객체 중 이전 연결한 Connection Pool 객체의 우선순위를 높여주기 위함

이러한 동작으로 쓰레드들은 커넥션을 획득,반납함으로써 상대적으로 비싼 비용이 드는 커넥션 생성을 줄일 수 있습니다.

DBCP를 사용할 때 주의할 점이 있습니다.

Connection 최대 개수 maxActive는 성능에서 중요한 요소입니다. 커넥션 풀의 크기가 너무 작으면 커넥션을 얻기 위해 대기하는 쓰레드가 많아지고 병목현상이 발생할 수 있습니다. 그렇다고 커넥션 풀을 쓰레드 풀보다 훨씬 크게 설정하면 쓰레드가 실질적으로 사용하는 커넥션 외의 남는 커넥션들로 인해 메모리 낭비가 발생합니다. 따라서 모든 요청이 DB로 접근하는 요청은 아니기 때문에 보편적으로 WAS 쓰레드 풀은 커넥션 풀보다 크게 설정합니다.

DBCP의 종류

DBCP의 종류는 다양합니다. 대표적인 DBCP 3가지만 간략히 설명하고 포스트를 마치겠습니다.

  1. Apache Commons DBCP
  • 아파치에서 제공하는 가장 많이 사용되는 DBCP 중 하나
  • Apache 2.0에 따라 라이선스가 부여됨
  • PreparedStatements의 캐싱 및 재사용을 지원함
  • DBCP에서 커넥션을 빌릴 때 커넥션 객체에 대한 유효성 검증을 하지 않음
  • 코드 기여 및 개발이 활발하게 일어남 https://github.com/apache/commons-dbcp
  • 설정하기 쉬움
  1. Tomcat DBCP
  • Tomcat에 내장되어 사용
  • 고도의 동시성 환경 및 다중 코어 시스템 지원
  • 매우 활동적인 커뮤니티에서 코드 관리 https://github.com/apache/tomcat
  • Apache Commons DBCP 라이브러리를 바탕으로 만들어짐
  • Apache Commons DBCP 라이브러리의 장점을 가짐
  • Apache Commons DBCP 라이브러리의 속성 설정 방법과 동일함
  1. HikariCP
  • Brett Wooldridge가 2012년 경 개발함
  • 가장 빠른 DBCP 라이브러리
  • 약 130KB의 매우 가벼운 라이브러리
  • 버려진 연결 객체를 추적하고 닫음
  • JDBC, c3p0 등 CP 들의 느린 속도를 개선한 빠른 컨셉을 가지고 개발함
  • “zero-overhead” 라고 홍보
  • 다른 CP에 비해 역사가 짧아서 안정성의 문제가 존재함
  • 현재도 개발과 커뮤니티가 활성화되어 안정성 확보 및 버그 관련 피드백 제공함
  • 스프링부트 2.0부터 default JDBC connecrion pool으로 지정
  • Apache 2.0에 따라 라이선스가 부여됨
profile
github : https://github.com/kiaeh2323 , email : kiaeh9269@gmail.com

0개의 댓글