포스트

2023-08-11-TIL

2023-08-11-TIL

Today I Learned

HikariCP and DBCP

DB 커넥션을 맺는 일은 TCP 연결, 인증, 세션 초기화를 거치므로 비싸다. 요청마다 커넥션을 새로 만들지 않고 미리 만들어 둔 커넥션을 빌려 쓰고 반납하게 하는 것이 DBCP(Database Connection Pool)다. 애플리케이션은 DataSource.getConnection()으로 풀에서 커넥션을 빌리고, close()를 호출하면 실제로 연결을 끊는 대신 풀에 돌려준다.

HikariCP는 Spring Boot가 우선 선택하는 커넥션 풀이다. Spring Boot 문서는 성능과 동시성 때문에 HikariCP를 선호하며, 클래스패스에 있으면 항상 HikariCP를 고른다고 설명한다. spring-boot-starter-jdbc나 spring-boot-starter-data-jpa를 쓰면 의존성도 자동으로 들어온다. HikariCP README에 정리된 주요 설정과 기본값은 이렇다.

설정의미기본값
maximumPoolSize사용 중인 것과 유휴 상태를 합친 최대 커넥션 수10
minimumIdle유지하려는 최소 유휴 커넥션 수maximumPoolSize와 같음
connectionTimeout풀에서 커넥션을 받기까지 기다리는 최대 시간30초
idleTimeout유휴 커넥션이 풀에 머무를 수 있는 최대 시간10분
maxLifetime커넥션 하나의 최대 수명30분

풀이 가득 차고 유휴 커넥션이 없으면 getConnection()은 connectionTimeout만큼 기다리다 SQLException을 던진다. README는 성능과 급격한 부하 대응을 위해 minimumIdle을 따로 두지 말고 고정 크기 풀로 쓰기를 권한다. 풀 크기는 클수록 좋은 것이 아니라 DB가 동시에 처리할 수 있는 양에 맞춰야 한다는 점도 함께 강조한다.

  • https://www.baeldung.com/hikaricp
  • https://adjh54.tistory.com/73
  • https://medium.com/javarevisited/choosing-the-right-jdbc-connection-pool-c9ef90588d55
  • https://www.oreilly.com/library/view/hands-on-high-performance/9781788838382/8e813392-debe-49a5-9d83-8c807542045a.xhtml
  • https://kakaocommerce.tistory.com/45
  • https://hudi.blog/dbcp-and-hikaricp/
  • https://choitaetae.tistory.com/99#:~:text=DBCP%20(DataBase%20Connection%20Pool)&text=%EB%AF%B8%EB%A6%AC%20%EC%9D%BC%EC%A0%95%20%EA%B0%9C%EC%88%98%EC%9D%98%20Connection,%ED%95%98%EB%8A%94%20%EA%B2%83%EC%9D%84%20%EC%9D%98%EB%AF%B8%ED%95%9C%EB%8B%A4.
  • https://zzang9ha.tistory.com/376
  • https://d2.naver.com/helloworld/5102792

HikariCP and Connection Leak

커넥션 누수는 빌린 커넥션을 반납하지 않는 것이다. 누수가 쌓이면 풀의 커넥션이 모두 빌려진 상태로 남고, 이후 요청은 connectionTimeout 동안 기다리다 실패한다. HikariCP의 leakDetectionThreshold를 설정하면 커넥션이 그 시간보다 오래 풀 밖에 있을 때 누수 가능성을 알리는 로그를 남긴다. README 기준으로 기본값은 0(비활성)이고, 켜려면 최소 2초 이상이어야 한다.

같이 자주 보는 문제가 maxLifetime과 DB 쪽 타임아웃의 관계다. MySQL은 wait_timeout(기본 8시간)이 지나도록 쓰이지 않은 연결을 서버 쪽에서 끊는다. 풀은 그 사실을 모른 채 끊긴 커넥션을 빌려주게 되고, 그러면 Possibly consider using a shorter maxLifetime value. 같은 경고나 통신 오류가 난다(perfectacle 블로그). README도 maxLifetime을 DB나 네트워크 장비가 강제하는 연결 시간 제한보다 몇 초 짧게 두라고 강하게 권한다. 유휴 연결이 중간 장비에서 끊기는 환경이라면 keepaliveTime으로 주기적으로 연결 상태를 확인할 수 있다.

  • https://do-study.tistory.com/97
  • https://stackoverflow.com/questions/74097987/what-should-be-the-hikari-maxlifetime-for-mysql-wait-time-out-value-28800
  • https://jaehoney.tistory.com/337
  • https://github.com/brettwooldridge/HikariCP/issues/1600
  • https://perfectacle.github.io/2022/09/25/hikari-cp-time-config/
  • https://jobc.tistory.com/226
  • https://velog.io/@haron/%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85-DB-%EB%B0%9C%EC%83%9D%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%97%90%EB%9F%AC%EB%A5%BC-%EC%A0%95%EB%A6%AC%ED%95%B4%EB%B3%B4%EC%9E%90

JDBC Connection Pool

커넥션 풀은 애플리케이션 라이브러리만의 개념이 아니다. WebLogic이나 JEUS 같은 WAS도 서버 차원에서 커넥션 풀을 만들고 JNDI 이름으로 DataSource를 등록해 애플리케이션에 제공한다. 애플리케이션은 JNDI로 DataSource를 찾아 쓰기만 하고, 풀 크기나 연결 검사 같은 설정은 서버 관리 콘솔에서 관리한다. 아래 WebLogic 8.1과 JEUS 문서는 이런 서버 관리형 풀의 설정 항목을 설명한다.

  • https://docs.oracle.com/cd/E13222_01/wls/docs81/ConsoleHelp/jdbc_connection_pools.html
  • https://docs.oracle.com/cd/E13222_01/wls/docs81/ConsoleHelp/jdbc.html
  • https://technet.tmaxsoft.com/upload/download/online/jeus/pver-20141117-000001/server/chapter_datasource.html
이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다