본문 바로가기
이슈 기록

배치에서 socket was closed by server가 터진 후 원인 파악

by 대우니 2024. 3. 30.
728x90
반응형

목적

대개체 작업을 진행 한 후, 여러 배치에서 SQLNonTransientConnectionException이 터졌는데,

문제가 되었던 배치가 있었다.

그러나 해당 배치와 동일한 DB를 사용하는데도 커넥션 문제가 없이 작동하여 DB 상의 문제가 아닌지 혼선을 주었다.

따라서 이에 대한 원인 파악 후, 팀원 분들과 논의해보고 찾아본 것들을 기록하고자 작성한다.

문제 이유

풀 설정이 잡혀있고, quartz 등으로 프로세스가 늘 떠있다가 스케줄링 설정이 돼있는데,

배치서버 혹은 was 서버 중 사용자가 새벽 시간에 아무도 접속하지 않다가 아침에 접속하는 등 query 요청을 장시간 하지 않는 경우에 빈번하게 발생된다.

이런 경우 connection 시간 설정과 DB 연결 시간 설정을 맞춰줘야 한다.

배경

  • MySQL은 기본적으로 자신에게 맺어진 Connection 중 일정 시간 이상 사용하지 않은 Connection을 종료, 여기서 일정 시간으로 지정되는 값이 바로 wait_timeout (default 값: 8시간)
  • 기존 Connection Pool 라이브러리들은 연결을 맺은 Connection들이 일정 시간이 지났을때 종료되는 것을 방지하기 위해 SELECT 1 등의 query를 주기적으로 날려 이 문제를 회피
  • 그러나 HikariCP는 maxLifetime(default 값: 30분) 설정값에 따라 스스로 미사용된 Connection을 제거하고 새로 생성 (참고로 사용중이지 않을 때만 제거)

hikariCP가 이렇게 만든 이유는 아래와 같은 단점을 해결하기 위함.

  1. DB에 지속적인 쿼리를 실행하게 되어 부하를 주고
  2. DB에 설정된 유휴 타임아웃들 (idle timeouts)을 완전히 무시

원인 파악

대개체 작업 전,mysql의 wait_timeout을 조회해본 결과 기본 값인 8시간 으로 설정되어있었기에 maxLifeTime 값을 설정하지 않아도 이와 같은 문제가 터진 적이 없었음. 

대개체 작업 전 설정

 

그러나 대개체 작업 후, mysql은 wait_timeout이 3600으로 조회되었으며 1시간 정도로 설정되었고, mysql이 종료되었음에도 불구하고, 쿼리를 요청함으로써 Exception이 발생하게 된 것 같음.

대개체 작업 후 설정

따라서 maxLifeTime 값을 1분으로 설정함으로써 이러한 문제를 회피할 수 있게 되었음. 

즉 기존에는, 유휴 상태가 30분이 지나기 전까지는 커넥션이 풀에 남아있었고, 따라서 mysql이 종료되었음에도 커넥션이 풀에 남아있는 상황이 발생했는데,

유휴 상태가 1분이 지난 커넥션은 제거되니까 mysql이 종료되었음에도 커넥션이 풀에 남아있을 상황이 기존보다 줄어들게 됨. 

참조

https://jojoldu.tistory.com/526

반응형