안녕하세요 "미들웨어" 입니다.
이번에는 미들웨어를 운영하면서 가장 많이 어려움에 봉착하고 가장 흔하게 접하지만,
분석이 어려워서, 분석하는 방법을 몰라서.. 애먹는 OutOfMemory 에 대해 시리즈 가이드를 만들어 보려합니다.
OutOfMemory 는 일명 OOM 이라고도 하면서, OOM 발생시 서비스가 멈추는... 현상이 발생합니다.
그건 사용되고 있는 메모리가 부족해서 발생되는 현상으로 부족한 메모리를 회수하거나, 반환해서 할당하는 시간으로 인해 서비스 멈춤 현상 이라 보시면 됩니다.
간혈적으로 한번은 그려러니 하겠지만, 한시간에 2,3번씩 발생하게 된다면.. 서비스는 망한거조.
그럼 OOM 이 발생하면 heapdump 란 것을 생성해야하고, heapdump를 생성했으면 분석해야 하는데.
어디서 어떤걸 어떻게 설정하는 지 부터 진행해보겠습니다.
진행 순서는 아래처럼 가이드를 준비하고 있습니다.
(OutOfMemory-1) OutOfMemnory 란? OOM & HeapDump 파일생성 및 분석 가이드
(OutOfMemory-2) OutOfMemoryError 원인과 대책 & "GC란?..튜닝방법 공개"..Jstat, Jmater, Visual GC
(OutOfMemory-3) OutOfMemory 발생시 slack 알람으로 메세지 전송 스크립트
그럼 1장 시작하겠습니다.
1. OOM 발생시키는 스크립트 (spring, wildfly)
spring 와 wildfly 두가지 내용을 공유해드립니다.
아래 내용은 기동되는 start.sh 안에 넣으시면 됩니다.
#export JAVA_OPTS=" $JAVA_OPTS -XX:OnOutOfMemoryError=/app/spring/oom.sh" <--- 해당 내용은 oom 발생시 어떠한 스크립트를 실행시켜라 인데 이 내용은 다음에 다루겠습니다.
### springboot
#GC 로그 설정 DATE=`date +%Y%m%d%H%M%S` export JAVA_OPTS="-server $JAVA_OPTS" export JAVA_OPTS=" $JAVA_OPTS -XX:+PrintGCTimeStamps " export JAVA_OPTS=" $JAVA_OPTS -XX:+PrintGCDetails " export JAVA_OPTS=" $JAVA_OPTS -XX:+PrintGCDateStamps " export JAVA_OPTS=" $JAVA_OPTS -Xloggc:$INSTANCE_BASE/logs/gc_$DATE.log " export JAVA_OPTS=" $JAVA_OPTS -XX:+UseGCLogFileRotation " export JAVA_OPTS=" $JAVA_OPTS -XX:NumberOfGCLogFiles=10 " export JAVA_OPTS=" $JAVA_OPTS -XX:GCLogFileSize=10M " export JAVA_OPTS=" $JAVA_OPTS -XX:+UseParallelGC " export JAVA_OPTS=" $JAVA_OPTS -XX:+ExplicitGCInvokesConcurrent " export JAVA_OPTS=" $JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError " export JAVA_OPTS=" $JAVA_OPTS -XX:HeapDumpPath=$INSTANCE_BASE/logs/heapDump_$DATE.hprof " export JAVA_OPTS=" $JAVA_OPTS -XX:-OmitStackTraceInFastThrow " #export JAVA_OPTS=" $JAVA_OPTS -XX:OnOutOfMemoryError=/app/spring/oom.sh" |
### Wildfly & JBoss
경로 : standalone.conf export JAVA_OPTS="-server $JAVA_OPTS" export JAVA_OPTS=" $JAVA_OPTS -XX:+PrintGCTimeStamps " export JAVA_OPTS=" $JAVA_OPTS -XX:+PrintGCDetails " export JAVA_OPTS=" $JAVA_OPTS -XX:+PrintGCDateStamps " export JAVA_OPTS=" $JAVA_OPTS -Xloggc:log/gc_$DATE.log " export JAVA_OPTS=" $JAVA_OPTS -XX:+UseGCLogFileRotation " export JAVA_OPTS=" $JAVA_OPTS -XX:NumberOfGCLogFiles=10 " export JAVA_OPTS=" $JAVA_OPTS -XX:GCLogFileSize=10M " export JAVA_OPTS=" $JAVA_OPTS -XX:+UseParallelGC " export JAVA_OPTS=" $JAVA_OPTS -XX:+ExplicitGCInvokesConcurrent " export JAVA_OPTS=" $JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError " export JAVA_OPTS=" $JAVA_OPTS -XX:HeapDumpPath=log/heapDump_$DATE.hprof " export JAVA_OPTS=" $JAVA_OPTS -XX:-OmitStackTraceInFastThrow " #export JAVA_OPTS=" $JAVA_OPTS -XX:OnOutOfMemoryError='/app/wildfly/oom.sh $INSTANCE_ID' " |
|
2. jmap를 이용해서 수동으로 heapdump 생성하는 방법
1) java_home 이 path에 잡혀있어야 한다.
그게 아니라면, java_home/bin 에 가서 jmap 실행되는 경로에서 실행해야한다. 2) 프로세서가 기동된 계정으로 jmap을 실행해야 한다. (root 계정으로는 생성되지 않음) JMAP 사용 | jmap -dump:format=b,file=heapdump.hprof (pid) ex) jmap -dump:format=b,file= heapdump.hprof 56631 | JMAP live 옵션 추가 | ex) jmap -dump:live,format=b,file=heapdump.hprof 56631 위 명령어에서 실제 동작하고 있는 객체만 덤프를 받고 싶을때는 -live 옵션을 주면 heap dump분석시 용량을 줄이고 사용하고자 하는 범위만 지정할 수도 있다. |
|
3. JDK 1.8.92 버전부터 추가된 기능
JDK 1.8_92 버전부터 OOM발생시 추가할 수 있는 기능이 생겼습니다. 기존에는 OOM 발생하면 heapdump만 생성했는데, 1.8.0_92 버전 이후부터는 2가지 기능을 더 사용할 수 있을 것 같습니다. 문제는 이 기능을 그냥 가져다 사용하게 되면 OOM 발생시 원인분석 전에 재기동을 할 수도 있습니다. 우선순위는 없습니다,. 저라면 일반적으로 사용하는 heapdump 파일 생성을 수행하고 -> Instance stop 이나 restart 를 진행하도록 스크립트를 만들것 같습니다. 예를들면.. heapdump.sh 를 만들어서 우선순위를 넣어주는 거조.
1번으로.. -XX:OnOutOfMemoryError="./heapsump.sh" 실행 2번으로.. ./heapsump.sh 실행 하는 스크립트 안에 -XX:+HeapDumpOnOutOfMemoryError, -XX:HeapDumpPath=/test 옵션 수행 하고 -XX:+ExitOnOutOfMemoryError 옵션으로 인스턴스 restart 수행 하면 어떨까요? |
아직은 방법론이고.. 이걸 구현해볼까 고민 중 입니다. ## JDK 1.8.0_96에 추가된 옵션에 대해 공유해드립니다. 새로운 JVM 옵션 추가 : ExitOnOutOfMemoryError 및 CrashOnOutOfMemoryError - ExitOnOutOfMemoryError
: 이 옵션을 활성화하면 JVM은 메모리 부족 오류가 처음 발생할 때 종료됩니다. 메모리 부족 오류를 처리하는 대신 JVM 인스턴스를 다시 시작하는 것이 좋을 때 사용할 수 있습니다.
- CrashOnOutOfMemoryError
: 이 옵션을 사용하면 메모리 부족 오류가 발생하면 JVM이 충돌하고 텍스트 및 이진 크래시 파일이 생성됩니다 (코어 파일이 활성화 된 경우).
좀 더 자세한 내용은 아래 오라클 홈페이지를 참고하세요. http://www.oracle.com/technetwork/java/javase/8u92-relnotes-2949471.html |
|
이번장은 내용이 좀 많긴하네요..
2장으로 나눠서 설명드릴까 하다가 한장에 모두 적어봤습니다.
OOM은 언제든지 발생 가능합니다.
다음 장에는 분석하는 방법에 대해서 좀 더 심도있게 진행해보겠습니다.