태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

[임종민]OutOfMemory 해결 방법론 – 그때 그 시절

엑셈 사람들 2009.04.09 16:39


을 간직하고 있으면 실현할 때가 온다. 괴테의 말이 아닌 나의 삶 자체가 그랬다.

JAVA OOM(OutOfMemory) 원시적 해결기법

2005년도 무렵의 일이다. 지금은 원시적 방법일 수 있지만 APM이나 메모리 프로파일링 툴이 없을때 급할 때는 간간이 쓰는 fast memory leak 특정유형의 대처방법에 대해서 살펴본다. 예전 모 사이트에서 SUN, HP계열에서 OutOfMemory가 났을 때 유일하게 썼던 방법들이 가비지 콜렉션 로그 및 thread dump 이다. 그 외 수행되었던 history를 아는 access log정도? 

그때는 APM은 커녕 관련 문제를 디버깅하기 위한 효과적 툴이 부족했던 것이 사실이었고 메모리문제를 해결하기가 정말 어려운 과제여서 엔지니어들이 두려워하는 영역이었다. 그 때 한참 IBM에서는 heapdump라는 유용한 기능을 내놓아 여러 사이트에서 재미를 본 게 사실인데 이곳은 SUN jvm이라 그런 효과를 기대하기 어려웠었다.
현장에 출동하니 옆에서 고객 분이 노발대발 하시는 상황이었고 모니터링 하는데 결론도 안 나는 잦은 회의를 하였다. 실무담당자 중 직책이 제일 높은 고객 분이 소리를 질러가며 공포 분위기를 조성하는데 이런 분위기에서 흔들리지 않고 일할 수 있는 사람이라면 정말 프로중의 프로라 칭하고 싶다.
이런 와중에 정신차리자고 마음을 되새겼으며, 문제가 될만한 것이 어느 것인지 하나 둘씩 짚어보기로 하였다.

첫째로 성능저하가 예상되지만 메모리 heap profiling을 생각 하였는데 적용 하지 않는 것으로 생각을 바꿨다. 장애상황이 해결 안된 시간이 꽤 흘렀고 현재 상황보다 더 안 좋게 만드는 것은 페널티라도 물릴 상황이어서 모두 두려워 그랬던 것도 있고, 사실 개인적 생각은 hprof파일로 dump를 떨군다고 해서 전문적으로 그 dump를 분석할 수 있는 툴이 없었기 때문이다. 하여 가비지콜렉션 log를 확인하였는데 예상대로 메모리부족에 의한 Full GC로 인해서 performance 저하로 이어지는 상황이었다. 하지만 해당 로그 가지곤 현재 메모리문제를 일으키는 주범을 찾기엔 정보가 부족하다.

과연 여러 Application이 돌고 있는 환경에서 메모리부족을 야기시키는 application을 thread dump로 찾는 것이 가능할까? Fast memory leak이고 운 좋게 looping logic이 들어 있다면  그 순간 thread dump를 통하여 해당 application을 찾을 수도 있을 것이다. 하지만 thread들이 매우 많다라고 하면? 다수의 thread dump를 통하여 촘촘이 있는 thread를 보고 분석할 수도 있겠지만 그순간의 snapshot이 어떻게 메모리를 많이 쓴다라는 것을 보장할까? 그 순간 메모리만 늘어나는 것일까?

엄밀히 이야기해서 fast memory leak이라 해서 꼭 looping 로직으로 인해서 발생하는 것은 아니다. 굉장히 큰 array에 의해서 그 array를 collection에 다량으로 많이 저장할 때도 발생한다. 이런 경우는 looping 로직에 의해서가 아니더라도 몇 번만 실행 하여도 발생하므로 해당 방법론으론 검출이 안될 소지가 크다.
하여 썼던 방법이 사용자 요청이 적은 새벽시간에 문제가 발생했던 시점의 여러 thread dump에 공통적으로 자주 등장했던 Application 위주로 실행 해보는 것이었다.
불과 몇 분이 지나지 않아 문제의 근원을 검출하였다. 어떤 특정 Application이 실행할 때마다 CPU리소스가 마구 올라가는 것이었다. 그 순간 WAS가 사용하는 heap메모리 사용률을 보니 메모리가 급진적으로 고갈되고 있는 것이었다. 장애상황과 비슷한 상황이 재현되었다. 

Thread 상태를 보니 해당 Application은 계속 수행 중이었고, 이제 남은 것은 thread dump를 통하여 어떤 작업 중인지 확인하는 작업만 남아 있었다. 굳이 CPU리소스 성능 factor가 아니더라도 루핑에 의해서 application이 돌고 있으면 thread dump에 나오리라…..
결론적으로 application 로직중 특정 날짜에만 실행되도록 하는 로직이 있었는데 버그로 인하여 무한루프가 돌아서 해당 장애상황을 일으켰던 것이다.
원인을 알아내서 해결했지만, 몬가 2%부족했고, 허탈감이 밀려왔다. 관련문제를 잡기 위해서 많은 인력과 노가다성 작업이 대부분이었는데 전문 모니터링 툴의 부재가 너무 아쉬웠었다.
현재시점으로 돌아와서 지금은 이렇게 무식한 방법이 아니더라도 APM을 통한 Collection element 개수추적 기능 및 일정이상 버전의 JVM이면 OOM 자동 메모리덤프 기능을 이용하여 트러블슈팅 할 수 있다.

시간이 되면 현재 쓰이고 있는 여러 메모리 관련 트러블슈팅 방법을 다뤄 보고자 하며 이 글을 마칠까 한다.

  • 박상욱 2009.04.13 19:56 신고 ADDR 수정/삭제 답글

    좋은글 잘 읽고 갑니다.