• 개인 공부 목적으로 작성한 포스팅입니다.
  • 아래 출처를 참고하여 작성하였습니다. :)

상황

  • 재배포 과정 중 AWS 인스턴스 상태 검사가 실패해서 로그를 확인해보니 HikariPool - Thread starvation or clock leap detected라는 메시지가 있었습니다.
  • 이게 어떤 오류인지 확인한 내용을 정리합니다.
  • 요약하자면, 해당 오류는 consumer thread 갯수에 따른 충분한 HikariCP의 maximum pool size를 설정하지 못해 Dead lock이 발생하면 나타나는 메시지입니다.

Hikari Default maximumPoolSize(10개)

스크린샷 2022-08-19 오전 9 48 18

Spring Default min-spare Thread(10개)

  • server.tomcat.threads.min-spare 속성은 Minimum amount of worker threads 의미로 기본값은 10개입니다.
  • 즉, 스프링부트 서버의 Worker thread 갯수의 기본값은 10개입니다.

Tn x (Cm - 1) + 1

  • HikariCP에서 제공하는 데드락을 피하기 위한 최적의 커넥션 풀 갯수를 구하는 공식입니다.
  • Tn은 Worker Thread 갯수(maximum number of threads)를 의미합니다.
  • Cm은 하나의 쓰레드가 작업을 하면서 동시에 필요로 하는 맥시멈 Connection 갯수입니다.
    • 필요한 커낵션은 2개입니다.

필요한 커넥션 갯수: 2개

JPA를 사용하여 데이터를 처리하는 경우 필요한 커넥션 갯수는 2개입니다.

  • Service의 메소드가 사용될 때 Service의 트랜잭션이 시작됩니다.
  • 그리고 Service의 메소드에서 Repository를 사용할 때 Repository의 트랜잭션이 시작됩니다.
  • 스프링 컨테이너는 트랜잭션 범위의 영속성 컨텍스트 전략을 사용한다고 합니다.
    • 즉, 요청을 처리하는 한 개의 Thread에서 Service의 트랜잭션과 Repository의 트랜잭션 때문에 2개의 영속성 컨텍스트가 생깁니다.
    • 그리고 2개의 영속성 컨텍스트를 위한 엔티티 매니저도 2개가 생겼으므로, Connection이 2개가 필요한 상황입니다.
  • 그러나 충분한 maximum pool size를 제공하지 않아서, 남은 Connection이 없는 상황이 발생해서 쓰레드는 작업을 끝내지 못하고 데드락에 걸리는 상황이 발생한 것입니다.

결론: 수정사항

  • 위 계산 공식에 맞게 10 * (2-1) + 1개 즉, 11개 이상의 커넥션 풀을 제공하도록 수정했습니다.
spring:
  datasource:
    hikari:
      maximum-pool-size: 20