Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags more
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

HikariPool...!! 본문

단체개발일지

HikariPool...!!

최밤빵 2024. 9. 8. 22:34

포스트맨 테스트를 하면서 처음 겪는 에러였다. 실행 돌리고 콘솔에서 가끔 봤던 단어였는데 이 에러를 겪고나서 다른 사람들한테 보여주려니 발생이 되지 않고있다가 곧 다시 발생할거라고 기술매니저님이 말씀하셨는데 정말 다시 발생해버렸다. 와 히카리풀이다!! 하고 개발일지 소재 생겼다고 좋아하다가 고치느라 많은 시간을 소모하고, 어찌어찌 사라졌다. 결제 기능을 구현하면서 볼 만한 에러도 아닌데 이런걸 다 보다니... 알아가는게 참 많은 시기구나...! 

히카리풀 에러..... 개발하면서도 커넥션 누수 라는게 있다는걸 처음 알게 됐다.

HikariCP는  스프링 부트에서 데이터베이스 연결을 관리하는 데 자주 사용하는 고성능 JDBC 커넥션 풀이다. 하지만... 잘못된 설정이나 특정 상황에서 연결 풀의 문제가 발생할 수 있기때문에  에러의 원인과 해결 방안을 정리해보았다! 

 

▶ HIkariCP 에러 

HikariCP는 Java 애플리케이션에서 효율적인 데이터베이스 커넥션 풀링을 제공하는 경량화된 라이브러리이다. 하지만 제대로 설정되지 않으면 "HikariPool-1 - Connection is not available, request timed out"과 같은 오류가 발생할 수 있다. 이 에러는 애플리케이션이 데이터베이스와의 연결을 실패했음을 의미하고, 내 에러코드에서는 HikariPool이 사용 가능한 커넥션을 찾을 수 없어 타임아웃이 발생했다. 

 

▶ 에러 로그 분석 

1. 주요 에러 메세지 :

→ HikariPool-1 - Connection is not available, request timed out after 30021ms (total=10, active=10, idle=0, waiting=0)

→ 이 메세지는 총 10개의 연결이 생성되었고, 그 중 10개가 활성화 상태이고, 가용 가능햔 유휴(idle)연결이 없다는 것을 의미한다. 결국 새 연결 요청은 3021ms(30초 쯤?)후에 타임아웃되었다. 

 

2. Exception의 종류:

→ org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction

→ org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection

→ java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available

→ 이 에러는 데이터베이스 연결을 얻을 수 없어 트랜잭션을 시작할 수 없음 이라는 뜻이다. 

 

3. 원인 

→ HikariCP 풀의 설정 문제로 인해, 애플리케이션이 데이터베이스 커넥션을 가져오는데 실패했다. 연결 풀의 크기 제한이 잘못 설정 되었거나, 데이터베이스 연결이 오래 지속되면서 닫히지 않아 발생할 수 있다. 

 

▶ 원인 분석 

→ Connection Pool 크기 문제 :

HikariCP의 기본 maximumPoolSize가 너무 작게 설정되었거나 애플리케이션의 트래픽이 급격히 증가하여 연결 풀의 크기가 부족할 수 있다. 

→ 오래된 커넥션 문제 :

연결이 제대로 반환되지 않거나 유효하지 않은 상태로 남아있어 풀에서 재사용되지 못할 수 있다. 

→ 커넥션 누수(Connection Leak) :

코드에서 데이터베이스 커넥션을 열고 닫지 않는 경우 커넥션 누수가 발생할 수 있다. 

→ 네트워크 문제 :

네트워크 장애로 인해 데이터베이스와의 연결이 끊어질 수 있다. 

 

▶ 해결 방법?

1. HikariCP 설정 확인 및 조정 :

→ maximumPoolSize를 현재 애플리케이션의 트래픽에 맞게 적절히 조정한다. 일반적으로 기본값은 10. 필요한 경우 더 늘린다. 

spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.connection-timeout=30000

→ maximum-pool-size를 20으로 늘리고, minimum-idle을 5로 설정하여 최소 5개의 유휴 연결을 유지하도록 한다. 

 

2. 커넥션 누수 방지 :

→  모든 데이터베이스 작업 후에 커넥션이 제대로 닫히는지 확인한다. 예를 들어 try-with-resources 문을 사용하여 커넥션을 자동으로 닫도록 한다. 

try (Connection connection = dataSource.getConnection()) {
        // 비즈니스 로직
        } catch (SQLException e) {
        log.error("DB 커넥션 오류", e);
}

 

3. Connection Validation 설정 :

→ 데이터베이스 연결이 유효한지 확인하는 테스트 쿼리를 설정한다. 오래된 연결이 제거되고, 유효한 연결만 유지될 수 있다. 

spring.datasource.hikari.connection-test-query=SELECT 1

 

4. 트랜잭션 관리 개선 :

→ 트랜잭션이 너무 오래 지속되지 않도록 트랜잭션 범위를 가능한 작게 유지한다. 트랜잭션이 길어지면 다른 연결이 대기 상태로 빠질 수 있다. 

 

5. 로그 모니터링 및 경고 설정 :

→ 애플리케이션 로그를 모니터링하여, 연결 풀과 관련된 경고나 오류가 발생하면 빠르게 대응할 수 있도록 합니다. 

 

6. 스레드 덤프를 통한 문제 분석 :

→ 커넥션 풀과 관련된 문제를 해결할 때, JVM의 스레드 덤프(Thread Dump)를 활용하면 어떤 스레드가 연결을 사용 중이고, 어떤 스레드가 연결을 기다리고 있는지 분석할 수 있다. 이를 통해 병목 현상이나 비정상적인 연결 사용 패턴을 확인할 수 있다.

 

7. 시간 초과 & 재시도 

→ 커넥션 시간 초과(connection timeout)를 적절히 설정하고, 시간 초과 시의 재시도 로직을 도입해서 네트워크 문제나 일시적인 장애에 대한 복구 가능성을 높일 수 있다. 

→ 예를 들어, RetryTemplate을 사용하여 Spring에서 재시도 로직을 추가할 수 있다. 

 

▶ 정리 

HikariCP 관련 에러는 대부분 데이터베이스 연결 풀의 크기 문제, 커넥션 누수, 네트워크 문제 등으로 발생할 수 있다. 이를 해결하기 위해 설정을 최적화하고, 코드에서 커넥션을 올바르게 관리하며, 네트워크 환경을 점검하는 것이 중요하다. 사실 해결방법이나 원인이 어마무시한데.. 나는 재실행 계속 하다보니 히카리풀이 없어졌다. 그동안 데이터베이스도 드롭했다가 다시 연결했고, 코드도 어느부분 수정했는데 그 부분을 기억하지 못 한다😢 아무튼 성능이 이렇게 멍청해지는구나 라고 느꼈던 히카리풀 에러였다.