문제 상황
개발 서버에서 갑자기 데이터베이스 커넥션 획득 실패로 인한 'Connection is not available, request timed out after 30000ms' 에러가 엄청 발생했다.
처음에는 커넥션을 오래 잡고있는 트랜잭션이 있는지 찾아봤는데, 원인을 알 수 없었다. 그런데 원래 해당 오류가 발생하지 않다가 프론트 측에서 sse를 구현하며 sse 연결 요청을 보낸 후부터 해당 문제가 발생한 것이다. 따라서 sse와 연관지어 생각해봤고, 검색해보니 sse 연결과 osiv 간 관계로 인해 발생한 문제였다.
osiv 옵션을 설정하지 않으면 default는 true이다. 즉, 요청과 응답 내내 영속성 컨텍스트가 살아있으며 커넥션을 점유한다. 이때 SSE 연결을 맺으면 sse 연결이 만료될 때까지 HTTP 연결이 이뤄져있으므로 내내 영속성 컨텍스트가 살아있으며 커넥션을 쥐고있는 것이다.
osiv를 true로 설정했을 때
osiv가 true일 때 겪었던 문제 상황을 재연해보자.
다음과 같이 jpa.open-in-view를 true로 설정해줬다. default가 true이므로 명시해주지 않아도 된다.
기본 커넥션 풀 사이즈는 10이다. 따라서 포스트맨을 통해 10명의 사용자가 sse 연결 요청을 보내도록 했다. 다음 로그를 통해 연결된 사용자가 총 10명임을 알 수 있다.
그리고 이어서 다른 요청을 보내면 데이터베이스 커넥션을 획득하기 위해 대기하다가 타임아웃 오류가 발생한다.
osiv를 false로 설정했을 때
이번에는 jpa.open-in-view를 false로 설정해줬다.
그리고 마찬가지로 포스트맨을 통해 10개의 sse 연결을 생성했다.
그러나 이번에는 이어서 다른 요청을 보내더라도 정상적으로 처리된다. 즉, osiv를 false로 설정함으로써 영속성 컨텍스트의 생존 범위가 HTTP 요청-응답 범위가 아닌 트랜잭션 범위로 줄어들었다. 따라서 sse 연결이 유지되고 있더라도 데이터베이스 커넥션을 점유하고 있지 않게 된다.