본문 바로가기

프로그래밍/JAVA

Java trouble shooting

scouter를 활용한 시스템 장애 진단 및 해결 노하우 자바 트러블 슈팅 책을 보고 대충 작성함.

장애 case

  • 시스템이 느림

    • 전체
    • 특정 화면
    • 특정 시간대 전체
    • 특정 시간대 특정 화면
    • 특정 화면, 점점 느려짐
    • 특정 사용자
  • 응답 없음

    • 전체
    • 특정
  • 예외 발생

    • 모든 사용자, 특정 기능
    • 특정 사용자, 특정 기능
    • 특정 시간대, 전체
    • 특정 시간대, 특정 기능
  • 시스템 뻗음

병목 지점들

  • 웹 서버
  • WAS
  • 각종 API 서버들
  • DB
  • Daemon
  • Legacy system
  • Etc

Thread 진단

Thread에서 발생하는 대표적인 문제점은?

  • Dead Lock
    • 데이터를 안전하게 처리하기 위한 Lock
    • 서로 풀리기만을 기다리는 상황

Lock 경합을 피하자

  • 코드가 아닌 데이터를 보호할 것(synchronized)
  • Atomic 작업을 사용할 것
  • Read-only data 사용할 것
  • Thread-local storage

Thread 개수?

WAS에는 Thread pool이 존재
최대 1000~2000개 정도 잡으라고 권장한다고 하네?
가장 적절한 개수는?
- 상위 80% URL을 추출하여 성능테스트
- 최대 50명 처리 가능
- 최대 초당 처리량이 200건
- 60명의 사용자가 있다면? 10명은 대기, 50명 처리할 것임
- 초당 200건? 50명 사용자니, 평균 응답 속도가 0.25초
- 상위 80%만 했으니 나머지 20%도 계산 필요
- 50개 + 20% = 60개 정도가 적당

Thread dump

APM 도구(scouter)를 활용하는게 가장 편함
없다면 Thread dump를 뜰 것(10~30초에 한번씩 10번 정도 할 것)

포함정보

  • 시간
  • JVM
  • Thread status
  • Deadlock
  • Heap usage

Thread status에서 문제가 될 만한 상태는 RUNNABLE, BLOCKED임
(WAITING도 문제가 될 수 있으나 대부분 pool 구성이라 WAITING 상태임)

방법

$ kill -3 pid
# or
$ jstack -h pid 

jstack은 시스템 성능에 영향을 끼치므로 운영서버에서 하면 안됨

Thread logic 이란 도구도 좋음

시스템이 느림, 시스템 응답이 없는 경우는 Thread dump가 해결에 많은 도움이 됨.

예외 발생, 시스템 뻗는 경우는 좀 다름
DB에서 응답이 없거나 GC가 오래 걸리거나, API 서버에서 응답이 없거나 등 점검해봐야 한다.

Parsing, I/O, 무한루프, 정규표현식 등을 유의할 것

Memory

Java memory 영역

  • JVM Stack
    • 메서드 호출 및 리턴 관련 정보들, 지역변수
  • Heap
    • 모든 클래스의 인스턴스, 배열, GC 대상
  • Method Area
    • JVM 모든 Thread가 공유, 각 클래스 정보, 필드, 메서드 데이터 등
  • Runtime Constant pool
    • 여러 종류의 상수 정보

Heap

  • Eden
  • Survivor 0 1
  • Old
  • Permanent(JDK8부터 없어짐)

보통 minor GC를 하면 eden -> survivor 0 -> survivor 1 -> Old 순으로 남은 객체들이 옮겨 가는데
G1 GC는 이동하는 비용을 줄여 그 영역 자체를 Survivor, Old로 변경 해버린다. (데이터 영역자체가 바둑판처럼 되어 있음)

OutOfMemoryError

GC가 새로운 객체를 생성할 공간을 만들어주지 못할 때
그 외는 Low 영역

  • …: Java heap space
    • 힙이 너무 작거나: -Xms512m -Xmx512m 등으로 설정을 바꿀 것
    • Memory Leak 발생… (GC 대상이 안되는 현상)
    • finalize…
  • …: Metaspace
    • (JDK8부터 생김, 이전에는 Permanent 였음)
    • 너무 많은 클래스로 인해 Metaspace 부족함
    • -XX:MaxMetaspaceSize=128m
  • …: Requested array size exceeds VM limit

그 외 메모리 문제?

  • 너무 잦은 GC
    GC 튜닝은 가장 마지막에 함
    그 전에 GC가 많이 발생하지 않도록 할 것

    • 임시 메모리 사용 최소화
    • 객체 재사용
  • jstat를 사용하면 GC 상태를 알 수 있음

Memory Dump

APM이나 jstat을 이용하면 됨

$ jstat -gcutil pid ls

Old 영역의 메모리 사용량은 수시로 증가하는 것이 기본임
Full GC 이후 메모리 사용량이 증가하는 경우 메모리 릭 의심을 하는게 좋음

동시 100~1000명 인기 어플은 Full GC가 자주 일어나는게 보통임

메모리 덤프를 뜨면 서비스가 불가능 해지고, 시간 소요, 큰파일 등 유의해야 한다.
map, gcore 등의 명령어도 쓸만함

$ jmap -finalizerinfo pid

$ jmap -clstats pid

$ jmap -histo pid

$ jmap -dump:format=b,file=holdmem.bin pid 

$ gcore -o holdmem.core pid

# 자동으로 힙 덤프 생성
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=경로
$ java -Xms128m -Xmx128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/HoldMemory

$ java -XX:OnOutOfMemoryError="gcore -o gcore.dump %p" 클래스 이름

분석

MAT
IBM Heap Analyzer

.

'프로그래밍 > JAVA' 카테고리의 다른 글

디자인 패턴 몇가지 정리  (0) 2020.06.03
자바 Thread 순서 보장하기  (0) 2020.05.26
Thread Dump & Heap Dump  (0) 2019.08.31
자바8 Optional  (0) 2019.04.23
WebFlux & Non-blocking  (0) 2019.04.22