Spring Boot 3.x JVM 통계, Grafana 대시보드로 분석하기
by rowing0328※ 본 내용은 그라파나 공식 홈페이지 독스를 참고하여 제작되었습니다.
Basic Statistics
- 기본 통계 (Basic Statistics)
Update : 시스템 가동 시간을 의미한다.
Start time : 시스템이 시작된 시간을 표시한다. - 메모리 사용률
Heap Userd : 힙 메모리의 사용률로, 70% 이하를 정상 범위로 간주한다.
Non-Heap Used : 논힙 메모리의 사용률로, 20% 이하를 정상 범위로 간주한다.
- 열려 있는 파일 수 (Process Open Files)
그래프를 통해 프로세스가 열고 있는 파일 수가 약 40~50개 사이에서 변동하고 있음을 확인할 수 있다.
- CPU 사용률
System CPU Usage와 Process CPU Usage가 함께 표시된다.
- 시스템 부하 평균 (Load Average)
CPU 코어 수에 비례해 시스템 부하를 나타낸다.
예를 들어, 값이 1.0이면 코어 1개가 100% 활용된 상태를 의미하며, 코어가 4개인 경우 4.0까지는 정상 범위로 볼 수 있다.
JVM Statistics - Memory
- Eden Space (heap)
사용량이 주기적으로 증가하고 감소하며, 이는 빈번한 GC 발생을 의미한다.
이는 정상적인 현상으로, 사용률이 일시적으로 높아져도 문제가 없다.
- Survivor Space (heap)
Minor GC 후 생존한 객체가 이동되는 공간으로, Eden Space의 10~20% 사용률이 정상 범위로 간주된다.
- Tenured Gen (heap)
Young Generation을 거친 후에도 생존한 오래된 객체가 저장되는 공간으로, 사용률 70~75% 이하일 때 정상 범위로 간주된다.
Full GC 후 메모리가 일정량 정상적으로 회수되며, 사용량이 완만하게 증가하는 것이 정상이다.
- Metaspace (non-heap)
JVM 클래스의 메타데이터를 저장하는 공간으로, 초기 로딩 후 안정화되어야 하며, 급격한 증가가 없는 것이 정상이다.
- Compressed Class Space (non-heap)
JVM 메타데이터 영역 중 하나로, Klass 포인터를 저장하는 공간이다.
이 영역은 사용률을 80% 이하로 유지하는 것이 권장되며, 급격한 증가가 발생하면 메모리 부족이나 GC 문제가 발생할 수 있다. - Klass
HotSpot JVM에서 사용되는 구조체로, 자바 클래스의 메타 데이터를 표현한다.
다음과 같은 정보를 포함한다 :- 클래스 이름
- 부모 클래스 및 상속 관계
- 메서드 테이블
- 필드 정보
- 접근 제어자
- 인터페이스 정보
- Static 및 Non-Static 멤버
- Code Cache
초기 로딩 후 점진적으로 증가하며, 급격한 변동 없이 안정적으로 관리되는 것이 정상이다.
일반적으로 ReservedCodeCacheSize의 80% 이하로 유지하는 것이 권장된다.
Code Cache가 가득 차면 JIT 컴파일이 중단되어 성능 저하가 발생할 수 있다.
Code Cache의 세가지 영역 (CodeHeap)
- non-nmethods
JIT 컴파일러가 사용하는 내부 데이터 구조와 JVM 운영에 필요한 코드(런타임 스텁, 버퍼 등)를 저장하는 영역이다.
이 영역에는 컴파일된 애플리케이션 코드가 아닌, JVM 자체의 운영에 필요한 코드가 포함된다. - profiled nmethods
자주 실행되는 메서드(Hot Methods)를 최적화하여 컴파일된 코드가 저장되는 영역이다.
프로파일링 데이터를 기반으로 최적화가 수행되며, 성능이 중요한 코드가 저장된다.
이 영역에는 Level 1~3 수준의 중간 최적화된 코드가 포함된다. - non-profiled nmethods
덜 자주 실행되는 메서드를 JIT 컴파일러가 프로파일링 없이 변환한 코드가 저장되는 영역이다.
이는 프로파일링 없이 빠르게 컴파일된 코드로 구성된다.
이 영역에는 Level 4 수준의 높은 최적화 코드가 포함된다.
- Direct Buffers
JVM에서 네이티브 메모리를 사용하는 버퍼로, 주로 Non-blocking I/O 작업에 활용된다.
초기 할당 이후 안정적으로 유지되며, 급격한 변동이 없는 것이 정상적인 동작이다.
- Mapped Buffers
파일 내용을 메모리에 직접 매핑한 영역으로, 메모리 매핑 파일 처리와 대용량 파일 작업에 유용한 버퍼이다.
필요할 때만 할당되고 해제되며, 파일 처리량에 따라 변동이 발생하는 것이 정상적인 패턴이다.
- Memory Allocate/Promote
JVM 메모리 할당 및 승격(Young에서 Old 영역으로 이동) 패턴을 나타낸다.
일반적으로 Promoted 양은 Allocated 양보다 훨씬 적은 것이 정상이다.
Allocated의 급격한 증가와 Promoted의 지속적인 증가는 주의가 필요하다. - Allocated
Eden 영역에 새로 할당된 메모리 양으로, 객체 생성 속도를 나타낸다. - Promoted
Young에서 Old 영역으로 승격된 객체의 양으로, Survivor 영역에서 살아남은 객체들의 Old 영역 이동한 양을 나타낸다.
- Daemon Threads
백그라운드에서 실행되는 쓰레드로, JVM의 중요한 유지 보수 작업을 수행한다.
대부분의 애플리케이션에서 일정 수를 유지하며, 주로 시스템 관리 목적으로 사용된다.
사용자 요청 처리와는 독립적으로 동작한다. - Live Threads
현재 실행 중인 모든 쓰레드로, 여기에는 Daemon Threads와 Non-Daemon Threads(일반 사용자 쓰레드)를 포함한다.
애플리케이션의 실행 상태에 따라 변동될 수 있으며, 비정상적으로 높은 값은 쓰레드 누수나 과도한 병렬 작업을 나타낼 수 있다. - Peak Threads
JVM 시작 이후 생성된 쓰레드의 최대 개수를 나타낸다.
초기 부하나 스파이크로 인해 Peak 값이 증가할 수 있지만, 시스템이 안정화되면 더 이상 증가되지 않아야 한다.
Peak 값이 지속적으로 높게 유지되면 쓰레드 풀 관리 문제나 불필요한 쓰레드 생성이 의심된다.
JVM Statistics - GC
- Major GC
Old Generation(Tenured 영역)에 쌓인 오래된 객체를 정리하는 Full GC를 의미한다.
발생을 가급적 피해야 하며, 발생하더라도 빈도가 매우 낮아야 한다.
Major GC가 자주 발생하면 메모리 누수나 Old Generation의 포화 상태를 의심할 수 있다. - Minor GC
Young Generation(Eden, Survivor 영역)의 객체를 정리하는 GC를 의미한다.
주기적으로 발생하며 짧은 시간 내에 완료되는 것이 정상이다.
- Minor GC의 Stop the World (STW)
Young Generation에서 객체를 정리하는 작업으로, 매우 짧은 시간에 완료된다.
평균 STW 시간은 10~50ms 이내가 정상이며, 이를 초과하지 않아야 한다.
STW 시간이 100ms를 초과하면 경고가 발생한다. - Major GC의 Stop the World (STW)
Old Generation 객체를 정리하기 위한 작업으로, 높은 비용이 발생하며 성능 저하의 주요 원인이 된다.
발생 빈도는 매우 낮아야 하며, STW 시간은 100ms~1s 이내가 정상이다.
STW 시간이 1s를 초과하면 애플리케이션이 중단될 수 있다.
마무리
어떻게 보면 로깅은 우리에게 무언의 방향성을 제시하는 존재가 아닐까 싶다.
남겨진 수치와 로그들은 단순한 기록을 넘어, 우리가 놓쳤던 문제의 단서나 앞으로 나아갈 길의 힌트를 건네주기도 한다.
이번 JVM 대시보드 해석 또한 그랬다.
수치와 그래프를 통해 보이지 않는 JVM의 행동 패턴을 읽어내며, 마치 로깅이
"이쪽을 주목하라"는 작은 신호를 보내는 듯했다.
로그와 모니터링은 시스템과 소통하는 중요한 언어이며, 이를 제대로 해석하는 것이
문제 해결과 성능 최적화의 첫 걸음이라는 생각이 든다.
참고 자료 :
Grafana 공식 튜토리얼
'📌ETC > Development Log' 카테고리의 다른 글
K6와 InfluxDB를 활용한 성능 테스트 및 모니터링 설계하기 (2) | 2025.01.02 |
---|---|
Prometheus와 Grafana 활용한 Spring Boot 모니터링 설계하기 (0) | 2025.01.02 |
Spring Boot와 JSch 활용한 ElastiCache SSH 터널링 설계하기 (0) | 2024.12.17 |
블로그의 정보
코드의 여백
rowing0328