HikariCP Dead lock & java.lang.OutOfMeomoryError:Java heap space

박건영(Parkgunyoung)·2022년 7월 30일
0

TroubleShooting

목록 보기
2/2

이제 실전 프로젝트를 배포까지 하여 마무리되어 가면서 그동안 하지 못했던 트러블슈팅 정리와 공부한 내용을 블로그에 적어보려 한다 ㅜㅠㅜㅠ (감격🥺🥺🥺)

개발바닥(사이드프로젝트 멤버 모집 서비스)

한 번 씩 아니 두 번... 아니 계속 이용해주세요😍😍😍😍
https://dogpaw.kr/

정식 배포전 프론트와 연결하여 테스트를 하던 중 계속해서 서버가 불규칙하게 다운이 되는 현상이 생겼다.

이유를 찾기 위해 구축해둔 로그파일을 확인하였고

java.sql.SQLTransientConnectionExecption: HikariPool-1 - Connection is not available,request timed out …

의 에러를 확인하였다. 에러로그를 확인 하였을 때 무언가 hikari pool과 관련된 문제로 db와의 연결이 끊어져 서버가 다운이 된 것으로 보였다.

찾아보니 hikari pool은 @Transactional과 관련이 있었고 처음에는 hikari pool을 늘려보기로 하였다. 기존 deafault 10으로 잡혀있는 hikari pool을 40으로 주었고

다시 테스트를 해보았다. 잘 유지되나 싶더니 조금더 오래 버틴 후 다시 다운이 되었고 설정해둔 hikari pool status 로그를 확인해보았다. 40으로 설정해둔 hikari pool이 모두 꽉 찼고 waiting이 걸리다 exeception이 발생하였다.

팀원들과 다시 원인 분석을 해보았다. @Trantional 과 관련이 있고 transaction이 시작할 때 Entitimanager가 open이 되는데 transaction이 끝나고 entitymanager의 closing이 이루어지지 않고 pool을 반납하지 못한채 계속해서 쌓여가는 것 같다는 생각이 들었다.

현재 서비스에서 SSE를 이용한 알림 서비스를 제공하고 있었고 로그 확인 시 이 부분에서 pool 문제가 발생하는 것 같아 try catch문을 써 예외처리를 해주었고 구글링을 통해 OSIV라는(OpenSessionInView = OpenEntityManagerInView)것을 찾게 되었다.

OSIV

(OpenSessionInView = OpenEntityManagerInView)

JPA를 사용할 경우 spring에서는 이 OSIV가 default로 true가 되어있고 이 경우 transaction이 끝나도 Db connection을 반환하지 않고, 영속성 컨텍스트를 계속 살려두고, 클라이언트가 요청한 View또는 API가 반환되어어야 connection을 반환하고 영속성 컨텍스트를 끝낸다. 우리는 이것을 flase로 바꿔주기로 하였고 transaction이 끝나는 순간 Db Connection을 반환하게 하였다.

이렇게 다시 테스트를 하였을 때 hikariPool은 default값인 10으로 돌려도 문제없이 잘 돌아갔다. 그런데…..

java.lang.OutOfMemoryError:Java heap space

이번에는 java.lang.OutOfMemoryError:Java heap space라는 heapSpace 부족의 에러가 발생하였다.🤮🤮

먼저 free -m 명령어로 우리가 프리티어로 빌린 ubuntu 컴퓨터의 메모리를 확인해보았다. 대략 1GB의 메모리가 할당되어 있었다.

그 중 서비스를 가볍게 작동시키며 테스트를 한 결과 800 후반에서 900중반의 메모리가 사용되고 있었다.

구글링을 해보니 프리티어에서는 1GB의 ram이 주어진다고 한다. 그럼 이 안에서 해결을 해보아야 할 것 같은 느낌이 들었다.

프리티어 안에서 추가적인 메모리를 늘릴 수 있는 방법을 찾아보니 SWAP메모리라는게 존재 했다. SWAP메모리는 OS에서 메모리를 full로 사용하고 있으면 사용하지 않는 메모리 안의 페이지를 하드드라이브에 저장하게 되는데, 이게 SWAP메모리의 기본 개념이다.

메모리의 대체 개념으로 사용가능하지만, 메모리를 100% 대체할 수는 없다고 한다!(처음에는 이걸 가볍게 무시했다….)

또한 SWAP메모리를 늘리면 자동으로 heap memory도 증가 할 줄 알았다…🤔🤔

우선 SWAP메모리를 구축해보았다.

SWAP Memory를 사용하기 위해선 SWAP Space를 마련해야 하는데 Space를 마련하는 방법은 SWAP partitions와 SWAP File을 사용하는 방법이 존재했다.

또한 SWAP Space를 설정해주어야 하는데 물리적인 RAM 용량에 비례해서 SWAP Space를 마련해야 한다고 한다. 최소량은 32MB 이상 이라고 한다.


SWAP SPACE 구축방법

Swap space의 기본 용량 단위는 128MB라고 한다.
AWS 프리티어는 RAM이 1GB이기 때문에 2GB의 SWAP Space를 할당하기 위해
count=16으로 설정해준다.

1) $ sudo dd if=/dev/zero of=/swapfile bs=128M count=16

스왑 파일 Read/ Write 권한을 변경한다.

2) $ sudo chmod 600 /swapfile

Linux SWAP File을 사용해서 영역을 설정한다.

3) $ sudo mkswap /swapfile

SWAP SPACE에 SWAP File을 추가해준다.

4) $ sudo swapon /swapfile 

추가된 SWAP 영역을 확인한다.

5) $ sudo swapon -s

서버를 Reboot(재실행) 할 경우 SWAP을 자동으로 활성화 하기 위해
/etc/fstab 파일을 열어서 해당 내용을 추가해준다.

6) $ sudo vi /etc/fstab
/swapfile swap swap default 0 0


위와 같이 구축을 하였고 아래와 같이 SWAP Memory가 할당 되어졌다!

이제 memory도 더 할당되어졌겠다 더이상 OutOfMemory에러가 뜨지 않겠지 라는 생각과 함께 다시 같은 에러를 마주하게 되었다…😱😱😱

좀 더 heapSpace에 대한 공부를 해보니 heapSpace는 JVM(자바 가상 머신)에서 할당하는 메모리로 실행시키는 컴퓨터의 램의 1/4로 할당되어 진다고 한다.

프리티어에서는 1GB의 램이 할당 되어지니 HeapSpace는 대략 250MB가 할당 되어졌다. 명령어를 통해 확인한 결과 대략 250MB가 할당되어져 있는 것을 확인 할 수 있었다. heapSpace를 늘리는 방법도 존재하였으나 서버 테스트 시 meomory 사용량이 주어진 1GB의 max치를 왔다갔다 하는 것을 확인하였고 팀과 합의 후

EC2 프리티어를 벗어나기로 하였다. 트레픽이 몰렸을 때를 고려하여 현재 프리티어 사양보다 두 단계 높은 4GB의 램을 갖고 있는 t2-medium으로 스펙업을 하였고 더 이상 이 에러를 마주하지 않았다.(역시 돈이 좋구나....🤑🤑🤑)

(4기가 램의 컴퓨터를 빌려 1/4인 1GB의 HeapSize가 할당된 것을 확인 할 수 있다.)

유저 테스트 시 첫 날 접속자가 대략 30명 정도 들어왔지만 서버 hikaripool 로그와 free -m을 통한 현재 사용 메모리 체크 시 아주 안정적으로 돌아가고 있는 것을 확인할 수 있었다. 다만 현재 유저 테스트를 진행하면서 사용중인 메모리를 계속해서 체크한 결과 메모리사용량이 1.3GB를 넘지 않는 것으로 보아 아직은 4GB의 램 사양의 컴퓨터는 오버스펙인 것 같다는 생각과 함께 t2-small로 스펙다운을 하려한다!

profile
쓰러지면어때일어나면그만인걸

0개의 댓글