대용량 Job 처리시 Hibernate Session Memory leak 경험

안녕하세요. 이경일입니다.

그동안 illuminati 개발을 하느라고 블로그에 정리를 하는 것을 소홀히 했네요.

Project illuminati git : https://github.com/LeeKyoungIl/illuminati <- 허접하지만..별 좀 주세요… (굽신굽신)

오늘은 hibernate를 사용하는데 대용량 Job 처리 시에 발생할 수 있는 OOM 에 관해서 정리를 해보려고 합니다.

제가 하는 업무에서 외부와 연동하는 Job을 돌릴 일이 있었는데요. 종종 오류가 발생을 하는 현상이 발견되었습니다.

해당 Job은 실행이 될 때마다 대상의 개수가 변하기 때문에 작게는 몇백 개 많게는 몇십만 개가 넘을 때도 있었죠.

현상은 몇백 개 돌 때는 괜찮은데 10만 개가 넘어가면 오류가 발생을 하더라구요…

오류부터 보겠습니다.

 

 

OOM 이 발생하고 있는 것을 볼 수 있습니다.

해당 잡은 하루에 한 번 돌고 한번 돌면 한 시간 이상을 그냥 돌아가는 대용량의 잡이죠…

Job 서버라 10만 개가 넘어갈 무렵 heap Dump를 떠 보았습니다.

보니 메모리 릭이 발생하고 있네요.

전체 Heap의 74%를 점유하고 있는 부분을 찾아보았습니다. StatefulPersistenceContext 에 메모리가 누적이 되어있어서 자세하게 어떤 Object 인지 찾아보았습니다.

 

헐… HashMap 노드 개수 보이시나요?

 

동일한 이슈가 있나 구글링을 한 결과 발견을 했고.

(구글신 없으면 개발 어떻게 할지 막막하네요 ㅜㅜ…)

대강 핵심만 정리해 보면 Hibernate session 이 열려서 객체를 영속화 하면 당연히 cache를 하는데요. job의 경우 보통은 jenkins를 이용해서 실행을 시키면 빌드를 하고 -> Job 실행 -> 종료 이런 라이프 사이클을 가지죠 그러면 ORM을 사용하면 Hibernate session 은 Job이 실행을 하고 종료를 할 때까지 살아 있다고 보면 됩니다. 따라서 해당 Job에서 100개던 20만 개던 데이터를 DB에서 영속화 시키는 object를 전부다 cache 해서 가지고 있겠죠. 이게 Heap 용량을 넘어가지 않는다면 잡이 종료되며 클리어가 되겠지만 넘어가면 OOM이 발생하며 Job이 중지가 되는 상황인 겁니다. 따라서 session을 flush 하고 clear를 해줘야 하는 이슈가 생기는 것이죠.

 


따라서 코드에 해당 부분을 추가해 주었습니다.

 

결과는 짠~? 해결 되었습니다.

오늘도 이렇게 하루를 넘기는군요.

 

 

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다