ResourceManager 가 느려지거나 죽는 문제는 대개 힙과 GC 로 드러난다. 다만 힙 사용량 그래프 하나만 보면 판단할 수 없다. 힙이 올랐다가 GC 후에 원래 수준으로 내려오는지, 아니면 GC 를 해도 바닥이 계속 올라가는지가 핵심이다. 앞은 정상적인 부하이고 뒤는 누수나 자료구조 과다다.
따라서 힙 사용량과 GC 시간을 같은 시간축에 겹쳐 본다.
Cloudera Manager 는 tsquery 라는 자체 질의 언어로 차트를 그린다. 차트 추가 화면이나 Charts 메뉴에서 직접 입력한다.
SELECT jvm_heap_used_mb WHERE roleType = "RESOURCEMANAGER"
여러 값을 겹쳐 보려면 쉼표로 나열한다.
SELECT jvm_heap_used_mb, jvm_heap_committed_mb WHERE roleType = "RESOURCEMANAGER"
GC 관련 지표의 이름은 CM 버전과 역할에 따라 다르다. jvm_gc_time_ms 와 jvm_gc_count 계열이 일반적이지만, 그대로 쓰면 결과가 비는 경우가 있다. (확인 필요 — 쓰는 CM 버전에서 실제로 노출되는 이름을 확인해야 한다.)
정확한 이름은 추측하지 말고 화면에서 찾는다. 차트 추가 화면의 지표 검색창에 gc 나 heap 을 넣으면 그 역할이 실제로 내보내는 지표만 나온다. 또는 역할 상세 화면의 Charts Library 에서 기본 제공 차트를 열어 어떤 지표를 쓰는지 본다.
특정 인스턴스만 보려면 조건을 더한다.
SELECT jvm_heap_used_mb WHERE roleType = "RESOURCEMANAGER" AND hostname = "rm-host-01"
ResourceManager 는 JMX 를 HTTP 로 노출한다.
curl -s http://rm-host:8088/jmx | python3 -m json.tool | grep -A12 '"name": "java.lang:type=Memory"'
curl -s http://rm-host:8088/jmx | grep -i gc
프로세스에 직접 붙어도 된다.
jcmd <pid> GC.heap_info
jstat -gcutil <pid> 5s 20
jstat -gcutil 의 O(Old 영역 사용률) 가 Full GC 뒤에도 내려오지 않고 계속 올라가면 누수를 의심한다.
| 원인 | 신호 |
|---|---|
| 동시 실행 애플리케이션 급증 | 제출 건수 그래프가 함께 튄다 |
| 완료된 애플리케이션을 너무 많이 기억 | yarn.resourcemanager.max-completed-applications 가 크다 |
| 노드 수 · 컨테이너 수 증가 | 클러스터 확장 직후 |
| 상태 저장소 지연 | ZooKeeper 나 HDFS 응답이 느려 큐가 쌓인다 |
| 실제 누수 | GC 후에도 바닥이 계속 상승 |
완료된 애플리케이션 보관 수는 힙을 직접 먹는다. 기본값이 큰 편이라 애플리케이션이 많은 클러스터에서는 줄이는 것이 효과가 있다.
<property>
<name>yarn.resourcemanager.max-completed-applications</name>
<value>1000</value>
</property>
최근 JDK 의 기본 수집기는 G1GC 다. G1 은 힙을 작은 리전으로 나누고, 쓰레기가 많은 리전부터 골라 정리해 일시 정지 시간을 목표치에 맞추려 한다. 정지 시간 목표를 직접 지정할 수 있다는 점이 CMS 와의 큰 차이다.
-Xms8g -Xmx8g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-Xlog:gc*:file=/var/log/hadoop-yarn/rm-gc.log:time,uptime:filecount=10,filesize=50M
-Xms 와 -Xmx 를 같게 두면 힙을 늘였다 줄였다 하면서 생기는 흔들림이 없어진다. GC 로그는 반드시 남긴다. 사후에 원인을 가릴 유일한 근거다. JDK 8 은 로그 옵션 표기가 다르다(-XX:+PrintGCDetails -Xloggc:...).
Cloudera Manager 에서는 ResourceManager 의 Java Heap Size 와 Java Configuration Options 항목에 넣는다.
수집기가 고장 난 것이 아니라, 살아 있는 객체가 많아 회수할 것이 없는 상태를 말한다. Full GC 가 반복되는데 힙은 그대로이고 CPU 만 태우는 형태로 나타난다. 이 지경이면 힙을 늘려도 시간만 벌 뿐이다.
원인을 찾으려면 힙 덤프를 떠서 어떤 객체가 차지하는지 본다.
jmap -dump:live,format=b,file=/tmp/rm.hprof <pid>
덤프는 힙 크기만큼의 파일을 만들고 뜨는 동안 프로세스가 멈춘다. 운영 중이라면 영향을 감안한다. OOM 시 자동으로 뜨게 해 두는 편이 낫다.
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/hadoop-yarn/