Narrowing the Cause From Logs
한국어 원문으로 표시합니다.
목표
운영 로그(catalina.out, GC 로그, 액세스 로그, nginx 에러 로그)에서 근거를 뽑아 장애 원인을 좁히고, 숫자가 들어간 장애 보고서를 작성할 수 있게 됩니다.
왜 중요한가
장애 대응에서 가장 흔한 실패는 502 에 타임아웃을 늘리는 것입니다.
502 는 "유효하지 않은 응답을 받았다"이고 504 가 "시간 안에 응답하지 않았다"입니다.
둘을 섞으면 몇 시간을 낭비합니다. 또 OOM 은 종류(Java heap space /
Metaspace / unable to create native thread)에 따라 조치가 완전히 달라서,
메시지를 안 읽고 -Xmx 만 올리면 오히려 나빠질 수 있습니다.
로그에서 숫자를 뽑는 손이 있으면 이 판단이 추측에서 근거로 바뀝니다.
단계
/root/ts를 만들고/opt/lab/fixtures/tomcat/logs/의 네 파일을 그대로 복사합니다. (catalina-oom.log,gc.log,access.log,nginx-error.log) 내용이 원본과 동일해야 합니다.catalina-oom.log에서 OutOfMemoryError 를 찾아/root/ts/oom.txt를 만듭니다. 두 줄이고 형식은 정확히 아래와 같습니다.time=<로그에 적힌 타임스탬프> type=<OOM 종류 문자열>type은Java heap space/Metaspace/GC overhead limit exceeded/unable to create native thread중 하나입니다.gc.log를 분석해/root/ts/gc.txt를 만듭니다. 두 줄입니다.fullgc=<Full GC 발생 횟수> maxpause=<가장 긴 정지 시간, 밀리초, 소수점 포함 그대로>access.log에서 처리 시간이 긴 URL 상위 5개를 뽑아/root/ts/slow.csv를 만듭니다. 첫 줄은url,count,max_ms,max_ms내림차순 정렬입니다.access.log에서 5xx 응답을 URL 별로 집계해/root/ts/5xx.csv를 만듭니다. 첫 줄은url,status,count, 건수 내림차순 정렬입니다.nginx-error.log에서 업스트림 오류를 원인별로 집계해/root/ts/upstream.csv를 만듭니다. 첫 줄은code,cause,count.code는502또는504,cause는connection refused또는timeout입니다.- Tomcat 을 기동하고 스레드 덤프를 떠서
/root/ts/threads.txt에 저장한 뒤,/root/ts/threadstat.txt를 만듭니다. 두 줄입니다.
두 값은total=<덤프에 있는 전체 스레드 수> waiting=<WAITING 상태 스레드 수>threads.txt의 내용과 일치해야 합니다. /root/ts/rca.md를 작성합니다.## 현상,## 원인,## 조치,## 재발방지네 개의 h2 제목이 있어야 하고, 2단계의 OOM 종류 문자열과 3단계의fullgc숫자가 본문에 그대로 인용돼야 합니다.
참고
- URL 별 최대값:
awk -F'|' '{ if ($3 > m[$2]) m[$2]=$3; c[$2]++ } END {...}' - 스레드 덤프:
jcmd <PID> Thread.print > /root/ts/threads.txt - 덤프에서 스레드 수: 큰따옴표로 시작하는 줄이 스레드 하나입니다.
- 흔한 실수 1: Full GC 를 셀 때 Young GC 까지 함께 세는 것.
- 흔한 실수 2: 정렬할 때
sort -n대신 사전순 정렬을 써서9.5가12.3보다 크게 나오는 것. - 흔한 실수 3: 보고서에 숫자 없이 "메모리가 부족했다"고만 쓰는 것.
로그 사본 확보
/root/ts 를 만들고 /opt/lab/fixtures/tomcat/logs/ 의 네 파일을 그대로 복사합니다.
(catalina-oom.log, gc.log, access.log, nginx-error.log)
내용이 원본과 동일해야 합니다.
장애 분석의 첫 행동은 원본 보존입니다. 분석 중에 로그가 로테이션되거나 덮어써지는 일이 실제로 일어납니다.
OOM 발생 시각과 종류 확인
catalina-oom.log 에서 OutOfMemoryError 를 찾아 /root/ts/oom.txt 를 만듭니다.
두 줄이고 형식은 정확히 아래와 같습니다.
time=<로그에 적힌 타임스탬프>
type=<OOM 종류 문자열>
type 은 Java heap space / Metaspace / GC overhead limit exceeded /
unable to create native thread 중 하나입니다.
OutOfMemoryError 는 종류에 따라 조치가 완전히 다릅니다. 메시지 뒷부분에 종류가 적혀 있습니다.
GC 로그 분석
gc.log 를 분석해 /root/ts/gc.txt 를 만듭니다. 두 줄입니다.
fullgc=<Full GC 발생 횟수>
maxpause=<가장 긴 정지 시간, 밀리초, 소수점 포함 그대로>
Full GC 만 세어야 합니다. 정지 시간은 각 줄 끝의 밀리초 값입니다. 소수점이 있으니 정렬 방식에 주의하세요.
느린 URL 상위 추출
access.log 에서 처리 시간이 긴 URL 상위 5개를 뽑아
/root/ts/slow.csv 를 만듭니다. 첫 줄은 url,count,max_ms,
max_ms 내림차순 정렬입니다.
액세스 로그의 마지막 필드가 처리 시간입니다. URL 별로 묶어 최대값을 구해야 합니다. awk 의 연관 배열을 쓰면 한 번의 스캔으로 끝납니다.
5xx 발생 분포
access.log 에서 5xx 응답을 URL 별로 집계해 /root/ts/5xx.csv 를 만듭니다.
첫 줄은 url,status,count, 건수 내림차순 정렬입니다.
상태코드 필드를 정확히 지목해야 합니다. 5로 시작하는 세 자리만 골라 URL 별로 집계하세요.
502 와 504 원인 구분
nginx-error.log 에서 업스트림 오류를 원인별로 집계해
/root/ts/upstream.csv 를 만듭니다. 첫 줄은 code,cause,count.
code 는 502 또는 504, cause 는 connection refused 또는 timeout 입니다.
nginx 에러 로그의 문구가 원인을 말해 줍니다. 연결 자체가 거부된 것과 시간이 초과된 것은 다른 문구로 남습니다.
실제 스레드 덤프 분석
Tomcat 을 기동하고 스레드 덤프를 떠서 /root/ts/threads.txt 에 저장한 뒤,
/root/ts/threadstat.txt 를 만듭니다. 두 줄입니다.
total=<덤프에 있는 전체 스레드 수>
waiting=<WAITING 상태 스레드 수>
두 값은 threads.txt 의 내용과 일치해야 합니다.
실행 중인 톰캣에서 덤프를 뜬 뒤, 상태별로 스레드 수를 셉니다. 덤프에서 스레드 상태는 대문자 키워드로 나타납니다.
장애 보고서 작성
/root/ts/rca.md 를 작성합니다.
## 현상, ## 원인, ## 조치, ## 재발방지 네 개의 h2 제목이 있어야 하고,
2단계의 OOM 종류 문자열과 3단계의 fullgc 숫자가 본문에 그대로 인용돼야 합니다.
보고서의 가치는 숫자에 있습니다. 앞 단계에서 뽑은 값을 그대로 인용하세요. 재발 방지 항목에는 '주의한다' 대신 구체적인 설정이나 감시 항목을 적습니다.