LabHub
배우기 러닝패스 코스

Tomcat & nginx Operations

Narrowing the Cause From Logs

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

운영 로그(catalina.out, GC 로그, 액세스 로그, nginx 에러 로그)에서 근거를 뽑아 장애 원인을 좁히고, 숫자가 들어간 장애 보고서를 작성할 수 있게 됩니다.

왜 중요한가

장애 대응에서 가장 흔한 실패는 502 에 타임아웃을 늘리는 것입니다. 502 는 "유효하지 않은 응답을 받았다"이고 504 가 "시간 안에 응답하지 않았다"입니다. 둘을 섞으면 몇 시간을 낭비합니다. 또 OOM 은 종류(Java heap space / Metaspace / unable to create native thread)에 따라 조치가 완전히 달라서, 메시지를 안 읽고 -Xmx 만 올리면 오히려 나빠질 수 있습니다. 로그에서 숫자를 뽑는 손이 있으면 이 판단이 추측에서 근거로 바뀝니다.

단계

  1. /root/ts 를 만들고 /opt/lab/fixtures/tomcat/logs/ 의 네 파일을 그대로 복사합니다. (catalina-oom.log, gc.log, access.log, nginx-error.log) 내용이 원본과 동일해야 합니다.
  2. catalina-oom.log 에서 OutOfMemoryError 를 찾아 /root/ts/oom.txt 를 만듭니다. 두 줄이고 형식은 정확히 아래와 같습니다.
    time=<로그에 적힌 타임스탬프>
    type=<OOM 종류 문자열>
    
    typeJava heap space / Metaspace / GC overhead limit exceeded / unable to create native thread 중 하나입니다.
  3. gc.log 를 분석해 /root/ts/gc.txt 를 만듭니다. 두 줄입니다.
    fullgc=<Full GC 발생 횟수>
    maxpause=<가장 긴 정지 시간, 밀리초, 소수점 포함 그대로>
    
  4. access.log 에서 처리 시간이 긴 URL 상위 5개를 뽑아 /root/ts/slow.csv 를 만듭니다. 첫 줄은 url,count,max_ms, max_ms 내림차순 정렬입니다.
  5. access.log 에서 5xx 응답을 URL 별로 집계해 /root/ts/5xx.csv 를 만듭니다. 첫 줄은 url,status,count, 건수 내림차순 정렬입니다.
  6. nginx-error.log 에서 업스트림 오류를 원인별로 집계해 /root/ts/upstream.csv 를 만듭니다. 첫 줄은 code,cause,count. code502 또는 504, causeconnection refused 또는 timeout 입니다.
  7. Tomcat 을 기동하고 스레드 덤프를 떠서 /root/ts/threads.txt 에 저장한 뒤, /root/ts/threadstat.txt 를 만듭니다. 두 줄입니다.
    total=<덤프에 있는 전체 스레드 수>
    waiting=<WAITING 상태 스레드 수>
    
    두 값은 threads.txt 의 내용과 일치해야 합니다.
  8. /root/ts/rca.md 를 작성합니다. ## 현상, ## 원인, ## 조치, ## 재발방지 네 개의 h2 제목이 있어야 하고, 2단계의 OOM 종류 문자열과 3단계의 fullgc 숫자가 본문에 그대로 인용돼야 합니다.

참고

로그 사본 확보

/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 종류 문자열>

typeJava 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. code502 또는 504, causeconnection 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 숫자가 본문에 그대로 인용돼야 합니다.

보고서의 가치는 숫자에 있습니다. 앞 단계에서 뽑은 값을 그대로 인용하세요. 재발 방지 항목에는 '주의한다' 대신 구체적인 설정이나 감시 항목을 적습니다.