자사 서비스 중 예약 서비스에서 특정 순간에 예약 시간이 조회되지 않는 현상이 있었습니다. 데이터 로그를 찍어봐도 알 수가 없어 헤매던 중 원인은 JNDI 커넥션 설정에 있다는 것을 알게 되었습니다.
JNDI는 DB 커넥션을 WAS 단에서 제어하면서 커넥션 객체를 공유하는 방법입니다. DB 정보 및 커넥션 설정등을 따로 할 수 있는데 속성 중에 maxTotal과 maxIdle 값의 차이가 심해 발생한 오류였습니다.
먼저 문제가 생긴 설정값은 maxTotal="200" maxIdle="15" 입니다. 아래 속성값을 확인하면 알 수 있듯이 최대 200개까지 동시에 커넥션이 가능하고, 커넥션풀에 반납 후 유지되는 커넥션의 개수가 15인 것입니다. 사용을 마치고 커넥션을 반환되면 maxIdle 값인 15까지 연결이 해제되어 제거되고, 일부 커넥션이 닫혔다가 열리는 현상이 발생한 것으로 확인됐습니다. 이 과정에서 어플리케이션 오류가 발생했고 maxIdle값을 maxTotal과 동일하게 맞춰주자 해당 현상이 사라졌습니다.
사용 중인 WAS는 Tomcat9로 DBCP2 라이브러리를 사용합니다.
Tomcat JNDI - DBCP 설정
InitialSize : 최초 커넥션 풀에 채워넣을 커넥션 개수 (기본 : 0)
minIdle : 최소한으로 유지할 수 있는 커넥션 개수 (기본 : 0)
maxTotal : 동시 사용 커넥션 최대 개수 (기본 : 8)
maxIdle : 커넥션풀에 반납 후 유지되는 커넥션의 최대 개수 (기본 : 8)
maxIdle과 maxTotal은 동일하게 설정하는 것이 좋다.
maxWaitMillis : 커넥션풀 고갈시 최대 대기 시간 (기본 : -1, 단위 : ms)
validationQuery : 일정 시간 사용하지 않은 커넥션 풀 사용시 지연되는 현상 방지, 주기적으로 연결을 확인할 수 있는 쿼리문.
Oracle : SELECT 1 FROM DUAL
MySQL : SELECT 1
timeBetweenEvictionRunMillis : 유효하지 않은 커넥션을 풀에서 제거 한다. (기본 : 5000, 단위 : ms)