JVM 옵션에 OnError 이벤트에 대해 스레드 덤프가 남도록 하여 실마리를 잡을 수도 있다.
-XX:OnError="kill -3 %p" -XX:ErrorFile=파일경로
2 . 시스템 느려짐
가장 많이 발생하는 현상으로 시스템이 느려진다면 다음과 같은 순서로 확인하는 것이 좋다.
1. CPU, 메모리와 같은 리소스 사용량 점검 2. 외부와 연동하는 리소스 사용량 점검 3. WAS 메모리 및 스레드 설정 및 사용량 점검 4. Web 서버 설정 점검 5. OS 설정 점검 6. 스레드 상태 점검 7. 메모리 상태 점검
위 절차를 도식화한 것은 다른 글에서 정리하도록 하겠다. 여기서는 6번의 스레드 상태를 점검하는 것만 알아보자.
Application의 성능이 느려졌을 때는 APM(Application Performance Monitoring)을 사용하여 프로파일링을 해보는 것이 좋다.
Web Application에서 대부분의 응답 시간이 느려지는 원인 중 대부분(약 80% 정도)은 DB와 같은 WAS와 연동되는 외부 서버들 때문이다. DB SQL 성능이나 DB서버의 CPU 사용량은 어떤지, DB에 Lock이 발생하지 않았는지, 다른 외부 연동 서버들의 상태는 괜찮은지를 먼저 확인해 봐야 한다.
3 . 시스템 응답 없음
스레드 덤프가 가장 큰 효과를 발휘하는 경우로, 어떤 스레드에서 응답을 주지 않아 시스템이 멈추어 버렸는지 매우 쉽게 찾을 수 있다.
시스템이 응답하지 않을 때 보통 WAS가 정해 놓은 스레드 풀이나 DB 커넥션 풀이 꽉 찼을 확률이 높다.
이 때, 스레드 덤프를 30초에서 1분 단위로 발생시킨 후 APM을 통해 확인을 해본다.
응답이 없는 경우 다음 순서로 확인 해보자
1. 전체 스레드의 개수를 확인한다. 2. Java 6 이상일 경우, 스레드 덤프의 루트 노드를 클릭하여 메모리 사용량을 확인하고, 여러 개의 덤프 파일을 비교해 가며 값의 변화를 확인 한다. 3. 모니터 목록에서 빨간색으로 표시되어 여러 스레드를 잡는 녀석이 없는지 확인한다. 4. 해당하는 문제가 보이지 않을 때, Runnable 상태의 스레드를 확인하자. 5. 지속해서 수행중인 스레드가 존재하지 않는지 "Long running threads detect" 기능을 사용하여 확인한다.
그래도 원인이 없어 보인다면... 다른 원인을 찾을 수 밖에...
if 웹서버 설정?, 웹서버 문제? then웹서버 설정이나 로그도 확인 해보자.
if JVM 힙 메모리 부족? then 스레드 단면 + 메모리 단면을 같이 사용하면 문제 원인 빠르게 확인 가능하다. 왜냐하면 메모리 부족할 경우 GC관련 스레드가 상태(Runnable)이면서 CPU 코어를 하나 이상 100% 점유하고, 나머지 모든 스레드는 아무런 작업을 하지 않을 수 있기 때문이다.
스레드 실행 중인 상태 → CPU 코어 하나가 100% 이상 사용 → 메모리 상태 모니터링
이러한 상황에서는 다음과 같이 분석하자.
1. 스레드 덤프를 주기적으로 떠놓는다. 2. 스레드 덤프를 뜰 때, ps -Lf -p pid 명령어도 같이 수행하여 주기적으로 떠 놓는다. 3. CPU 사용 시간이 지속해서 증가하는 스레드가 있다면, pid확인 후 APM을 통해 어떤 스레드인지 확인해 본다. 4-1. 해당 스레드가 GC관련 스레드라면, 메모리가 부족하거나 GC알고리즘에 문제가 발생했을 확률이 높다. 따라서 jstat 명령어로 메모리 사용량을 확ㅇ인한 후 메모리가 부족하면 메도리 단면을 떠서 어떤 객체가 메모리를 가장 많이 잡고 있는지를 확인해 본다.
> jstat -gcutil 5s (*메모리 단면을 발생시키는 동안에는 해당 JVM이 완전 중단되어 WAS가 각종 사용자의 요청을 처리하지 못하므로 유의해서 작업해야 한다.)
4-2. GC 관련 스레드가 아닌 다른 스레드라면 해당 스레드가 지속해서 수행되고 있는지(무한 루프) 확인해 본다.
※ TimeoutExcept이 지속 반복되는 경우...
DB sql 성능 저하로 WAS에 설정해 놓은 Timeout 시간내에 리턴이 오지 않은 경우.