서비스를 전부 재기동하고 나면 정상이다가 이삼 일 지나면 DI Studio 에서 잡 배포가 실패한다. 이때 미들티어 웹 서비스를 내리면(sas.servers.mid stop) 배포가 다시 된다. 다시 이삼 일이 지나면 같은 일이 반복된다. 배포가 안 되는 시점에는 미들티어에 올라간 웹 애플리케이션도 함께 느려진다.
재기동으로 회복되고 시간이 지나면 재발하는 형태는 고장이 아니라 자원이 서서히 소진되는 형태다. 어느 자원인지를 좁히는 것이 전부다.
이 증상의 가장 큰 문제는 재기동하면 증거가 사라진다는 점이다. 다음번에 실패했을 때 아무것도 재시작하지 않은 상태에서 아래를 먼저 받아 둔다.
# 자바 프로세스의 메모리 추이
ps -eo pid,rss,vsz,etime,cmd | grep -i [j]ava
# 미들티어 프로세스의 스레드 수와 열린 파일 수
ls /proc/<PID>/task | wc -l
ls /proc/<PID>/fd | wc -l
cat /proc/<PID>/limits | grep -E 'open files|processes'
# 힙 사용 추이 (JDK 동봉 도구가 있을 때)
jstat -gcutil <PID> 5s 12
jstack <PID> > /tmp/midtier_threads.txt
로그에서는 다음 문자열을 찾는다. 어느 것이 나오는지에 따라 원인이 갈린다.
grep -nE 'OutOfMemoryError|unable to create new native thread|GC overhead limit exceeded|Too many open files' \
<SASConfig>/Lev1/Web/WebAppServer/SASServer1_1/logs/*.log
| 찍힌 것 | 가리키는 것 |
|---|---|
OutOfMemoryError: Java heap space · GC overhead limit exceeded |
힙 누수. 웹 애플리케이션 쪽 |
unable to create new native thread |
스레드 누수 또는 nproc 한도 |
Too many open files |
파일 디스크립터 누수 또는 nofile 한도 |
| 아무것도 없는데 느림 | 연결 풀 고갈 또는 메타데이터 서버 쪽 대기 |
RES 값을 비교한다. 단조 증가하면 누수다.ulimit -n, ulimit -u. 기동 스크립트에서 올려 두지 않으면 기본값이 적용된다.미들티어 전체를 내리면 무엇이 원인이었는지 알 수 없다. 다음 재현 때 한 가지씩만 재시작해 어느 것이 회복시키는지 본다.
원인이 확정될 때까지는 야간에 미들티어를 정기 재기동해 자원을 초기화한다. 근본 대응이 아니라 장애 간격을 늘리는 조치이므로, 재기동 직전에 위의 지표를 파일로 남겨 추세를 모으는 일을 함께 한다. 힙을 늘리는 것도 같은 성격이다. 누수가 있으면 도달 시점만 늦출 뿐이다.