• 티스토리 홈
starryeye
  • 프로필사진
    starryeye
    • 분류 전체보기 (189)
      • C++ (17)
      • Java (24)
      • OOP (5)
      • Spring Reactive Stack (12)
        • Reactive Streams (3)
        • Netty (4)
        • Reactor (1)
        • Webflux (3)
        • DB, Cache 연동 (1)
      • Spring (90)
        • Core (17)
        • MVC (33)
        • Client (2)
        • Security (4)
        • DB, Cache 연동 (33)
      • DataBase (12)
        • RDBMS (2)
        • NoSQL (10)
      • Message Broker (6)
      • Web (4)
      • Network (4)
      • 대규모 시스템 설계 (15)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • DBCP (HikariCP)
        2024년 04월 22일
        • starryeye
        • 작성자
        • 2024.04.22.:21
        반응형

        오늘 포스팅으로는
        Database Connection Pool (DBCP) 에 대해 정리해보겠다.
         

        배경

        Application 과 Database 간의 통신은 TCP 기반으로 통신한다.
        따라서, 본격적으로 데이터를 주고 받기 이전에 연결을 하는 과정을 거친다. (TCP 연결 지향 특성)
        -> 3 way-handshaking
        또한, 데이터를 주고 받은 다음 연결을 끊어주는 과정도 거친다. (TCP 연결 지향 특성)
        -> 4 way-handshaking
         
        실제 데이터를 주고 받기 전 후로 연결을 맺고 끊는 과정이 시간이 오래 걸리므로
        Backend API 응답 시간에 영향을 주게 되며
        이는 처리량에 영향을 주게된다
         

        또한, Database Connection 개수의 제한을 두지 않으면 DB 과부하 상태가 될 수 있다.

         

        DBCP

        따라서, Backend Application 이 띄워질때

        "미리 Database 와 연결"을 맺어서 "일정 갯수 제한"을 둔 Connection 들을 Pool 로써

        관리할 필요가 생겼고 이를 DBCP 라 부른다.
         

        동작 (happy case)

        1. Backend Application 에 요청이 들어와서 DB 에 쿼리 보낼 일이 생겼다.
        2. 요청 스레드는 Connection Pool 에 connection 을 하나 요청한다. (getConnection Call)
        3. Connection Pool 은 idle 상태의 connection 을 할당해준다. (해당 connection 은 in-use 상태가 된다.)
        4. 요청 스레드는 할당받은 in-use 상태의 connection 을 가지고 원하는 쿼리를 수행한다.
        5. 요청 스레드는 connection 을 Connection Pool 에 반환한다. (closeConnection Call, 다시 idle 상태가 된다.)
         
        참고
        Connection Pool 에서 getConnection 으로 connection 을 할당 받으면,
        connection pool 에서 사라지는게 아니다. 그냥 상태가 변하는 것이다. (idle -> in-use)
         

        HikariCP

        HikariCP 는 JDBC Connection pool 이다.
        DataSource 인터페이스를 구현한 객체는 HikariCPDataSource 이며,
        Spring 에서 기본으로 사용된다.
         
        HikariCP 공식 문서를 보면서 HikariCP 의 설정 값들에 대해 정리해보겠다.
         

        필수 설정

        필수 설정들은 기본 값이 존재하지 않는다.
         
        [driverClassName]
        각 Database 밴더에서 제공하는 JDBC Driver 구현체 이름을 적어준다.
         
        ex.
        org.h2.Driver
        com.mysql.cj.jdbc.Driver
        ...
         
        [username]
        Database 접속을 위한 사용자 이름
         
        [password]
        Database 접속을 위한 사용자 비밀번호
         

        자주 사용되는 옵션 설정

        [autoCommit]
        connection pool 에서 관리하는 connection 의 Auto-commit 동작을 지정해준다.
        기본 값 : true
         
        참고
        대다수의 Database 는 auto-commit 트랜잭션 모드와 명시적 트랜잭션 모드를 지원한다.
        JDBC Driver 는 auto-commit 모드가 true 이면 auto-commit 트랜잭션 모드로 실행하고,
        auto-commit 모드가 false 이면 명시적 트랜잭션 모드로 실행한다.
        -> Connection::setAutoCommit(false) // 이 코드가 트랜잭션을 명시적으로 실행하는 코드이다.
         
        [connectionTimeout]
        사용자가 Connection pool 에 connection 을 하나 요청했을 때, 할당 될 때 까지의 임계 시간이다.
        특징
        웹 응답을 기다리고 있는 Client 의 인내심을 고려해야한다.
        기본 값 : 30000 (단위는 ms, 최소 허용 값은 250)
         
        [maxLifetime]
        Connection pool 이 관리하는 connection 이 최대로 살아있을 수 있는 최대 시간이다.
        idle 상태의 connection 중 maxLifetime 에 도달한 connection 은 Connection Pool 에서 삭제한다.
        특징
        1. maxLifetime 에 도달했지만, in-use 상태의 connection 이면 즉시 삭제 되지 않고 idle 상태가 되어야 삭제된다.
        1. 대량 멸종을 방지하고자 커넥션 별로 값이 조금 씩 다르다. (minor negative attenuation)
        2. Database 자체 커넥션 시간 제한(MySQL, wait_timeout)보다 몇 초 짧게 둬야한다.
        (MySQL, wait_timeout 옵션 : DB 자체적으로 idle 상태의 커넥션에 시간제한을 둔다. idle 상태 벗어나면 시간 reset)
        -> maxLifetime 과 wait_timeout 을 동일하게 10 초로 두면..
        application 에서 9초에 SQL 을 보냈지만 DB 에는 11 초에 도착한다면 DB 에서는 이미 커넥션이 끊긴 이후다..
        3. 값을 0 으로 두면 시간 제한이 없는 무한이다.
        기본 값 : 1800000 (단위는 ms, 최소 허용 값은 30000)
         
        [idleTimeout]
        Connection pool 이 관리하는 connection 이 idle 상태로 존재할 수 있는 최대 시간이다.
        특징
        1. maximumPoolSize 보다 minimumIdle 이 작을 때 적용된다.
        2. Connection Pool 에 존재하는 connection 이 miniumIdle 값 이하라면 connection 은 만료되지 않는다.
        3. 값을 0 으로 두면 시간 제한이 없는 무한이다.
        기본 값 : 600000 (단위는 ms, 최소 허용 값은 10000)
         
        [keepaliveTime]
        Database 에도 자체적으로 커넥션에 대해 시간 제한을 둔다. (MySQL, wait_timeout)
        따라서, HikariCP 가 관리하는 커넥션 풀에 존재하는 커넥션이
        Database 에 의해 의도하지 않게 커넥션이 종료 되는 것을 방지해야한다.
        HikariCP 는 연결 유지를 위해 특정 행동(keepalive)을 수행하는데 해당 행동의 빈도에 관한 설정이다.
        특징
        1. keepaliveTime 은 maxLifetime 보다 작아야한다.
        2. 특정행동(keepalive) 은 커넥션이 idle 상태일 때 수행된다.
        3. keepalive 시간이 되면, connection pool 에서 빠지고
        "pinged"(keepalive) 된 다음 다시 connection pool 에 넣어진다.
        4. ping 은 JDBC 버전 4 이상부터 지원되는 Connection::isValid 메서드로 수행하거나
        hikariCP 의 connectionTestQuery 로 수행한다.
        5. 값을 0 으로 두면 시간 제한이 없는 무한이다.
        기본 값 : 0 (단위 ms, 최소 허용 값 30000, "분" 단위의 값으로 할 것을 추천)
         
        [connectionTestQuery]
        idle 상태의 connection 이 아직 유효한지 확인할 때 수행되는 쿼리이자,
        connection 이 사용자로 부터 할당되기 직전에 아직 유효한지 확인할 때 수행되는 쿼리이다.
        특징
        JDBC 의 Connection::isValid 가 지원되지 않는 드라이버용으로,
        JDBC 버전 4 이상이라면, 해당 설정은 하지 않는 것을 추천한다.
        기본 값 : none
         
        [minimumIdle]
        HikariCP 가 Connection Pool 에 idle 상태의 Connection 을 최소한 몇개를 가지고 있으려고 하는 설정이다.
        특징
        1. Connection Pool 전체 connection 수 (idle + in-use) 가 maximumPoolSize 값 보다 작은 상태에서,
        idle connection 수가 minimumIdle 값 보다 작으면 그 때 추가로 connection 을 생성한다.
        -> "참고 - minimumIdle vs maximumPoolSize" 에서 좀 더 자세하게 알아보겠다.
        2. 갑작스럽게 급증하는 connection 수요가 생길 것을 대비해 이 설정은 하지말고
        고정 크기의 connection pool 로 사용할 것을 추천
        기본 값 : maximumPoolSize 와 동일
         
        [maximumPoolSize]
        idle 상태의 connection 과 in-use 상태의 connection 갯수를 모두 합한 값인 connection pool 최대 사이즈 임계 값이다.
        즉, 해당 application 와 데이터 베이스간의 최대 연결 수를 설정하는 옵션이다.
        특징
        1. Application scale out 을 고려하고 Database 자체의 최대 커넥션 수 보다는 작아야한다.
        (MySQL 의 max_connections 옵션과 관련)
        2. tomcat thread pool 의 thread 최대 갯수(server.tomcat.threads.max 값)를 고려해야한다.
        3. 현재 connection pool 사이즈가 해당 값이며 idle 상태의 connection 이 없는 상태에서,
        getConnection 요청을 받으면 connectionTimeout 값 동안 요청이 "blocking" 된다.
        4. https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
        기본 값 : 10
         
        참고 - minimumIdle vs maximumPoolSize
        Connection Pool 에 idle 상태의 Connection 수가
        minimumIdle 수 보다 작으면 추가 Connection 을 맺는다고 했는데
        maximumPoolSize 을 초과한다면 어떻게 될까?
        -> maximumPoolSize 는 minimumIdle 보다 우선순위가 높게 동작한다.
        (포스팅 아래에 동작 예시를 보면 쉽게 알아볼 수 있다.)
         
        [metricRegistry]
        connection pool 에서 다양한 "metric" 을 기록하는데 사용할
        인스턴스(Codahale/Dropwizard MetricRegistry)를 지정하는 옵션이다.
        특징
        1. IoC container 에서 사용 가능
        2. https://github.com/brettwooldridge/HikariCP/wiki/Dropwizard-Metrics
        기본 값 : none
         
        [healthCheckRegistry]
        connection pool 의 현재 상태를 기록하는데 사용할
        인스턴스(Codahale/Dropwizard HealthCheckRegistry)를 지정하는 옵션이다.
        특징
        1. IoC container 에서 사용 가능
        2. https://github.com/brettwooldridge/HikariCP/wiki/Dropwizard-HealthChecks
        기본 값 : none
         
        [poolName]
        Connection pool 의 사용자 정의 이름을 지정한다.
        기본 값 : auto-generated
         

        자주 사용되지 않는 옵션 설정

        [initializationFailTimeout]
        [isolateInternalQueries]
        [allowPoolSuspension]
        [readOnly]
        [registerMbeans]
        [catalog]
        [connectionInitSql]
        [driverClassName]
        [transactionIsolation]
        [validationTimeout]
        [leakDetectionThreshold]
        [datasource]
        [schema]
        [threadFactory]
        [scheduledExecutor]
         
         

        동작 예시

        설정은 minimumIdle : 3, maximumPoolSize : 4 인 상태라 가정한다.
        connection pool 에 idle, in-use 상태의 connection 갯수를 같이 보면서 동작을 보자
         
        1. 초기 상태  (connection pool : idle(3), in-use(0))
        2. idle connection 하나가 in-use 로 되었다. (connection pool : idle(2), in-use(1))
        3. HikariCP 는 idle connection 을 생성한다. (connection pool : idle(3), in-use(1))
        -> minimumIdle 조건 따름
        4. idle connection 하나가 in-use 로 되었다. (connection pool : idle(2), in-use(2))
        -> minimumIdle 조건을 따라 idle connection 을 생성해야하지만,
        maximumPoolSize 조건에 의해 생성하지 않는다. (maximumPoolSize 는 minimumIdle 보다 우선)
        5. idle connection 두개가 in-use 로 되었다. (connection pool : idle(0), in-use(4))
        6. 이 상태에서 idle connection 한개를 얻어보면 connectionTimeout 값 동안 요청이 "blocking" 된다.
        7. in-use connection 4개가 idle 로 반환 되었다. (connection pool : idle(4), in-use(0))
        8. HikariCP 는 각 connection 을 maxLifetime, idleTimeout 에 따라 idle connection 을 종료하고 
        minimumIdle 에 따라 다시 생성한다. 이 때, 초과분으로 존재하던 idle connection 갯수를 유지할 필요는 없다.
        (connection pool : idle(3), in-use(0))
         
        하지만, HikariCP 에서는 minimumIdle 과 maximumPoolSize 를 동일한 값으로 사용하여
        고정크기의 Connection Pool 을 사용하기를 권장한다. 기본 값도 그렇게 되어있으며,
        이유는 DBCP 자체가 미리 connection 을 맺어두는 것인데 minimumIdle 이 maximumPoolSize 보다
        작은 값으로 설정한 상황에서 갑자기 idle connection 수 보다 많은 요청이 생기면
        connection 을 그때그때 생성하여 반환하고 해야하기 때문에 DBCP 의 존재 의의가 퇴색되기 때문이다.
         
         
        참고
        HikariCP
        https://github.com/brettwooldridge/HikariCP
        https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
        https://github.com/brettwooldridge/HikariCP/wiki/Dropwizard-Metrics
        MySQL
        https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html
        Commons DBCP
        https://d2.naver.com/helloworld/5102792
         
         

        반응형

        'Spring > DB, Cache 연동' 카테고리의 다른 글

        DBCP 설정 값 정하기  (0) 2024.05.01
        Spring Data JPA (Hibernate), N + 1 Query Problem  (0) 2024.02.20
        Spring 과 JPA  (0) 2024.02.14
        JPA 등록, 기본 키 생성 전략  (0) 2023.06.19
        JPA 변경 감지와 플러시  (0) 2023.06.15
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바