[SpringBoot] Prometheus, Grafana를 이용한 모니터링
애플리케이션의 메트릭과 상태를 모니터링하는 것은 애플리케이션의 성능을 개선하고, 보다 나은 관리를 가녕하게 하며, 최적화되지 않은 동작을 발견하는데 큰 도움이 됩니다.
이번 포스팅에서는 데이터 메트릭을 수집하는 `Prometheus`, 이를 시각화 하는 `Grafana`를 활용하여 `SpringBoot`에서 모니터링 환경을 구축하는 방법에 대해 알아보겠습니다.
Prometheus
`Prometheus`는 애플리케이션 트래픽에 대한 데이터를 수집합니다. 이를 통해 `CPU 사용량`, `메모리 사용률`, `요청 수`, `응답 시간` 등의 애플리케이션 성능 데이터를 추적할 수 있습니다.
애플리케이션의 `/actuator/prometheus` 엔드포인트를 통해 이러한 메트릭 데이터를 확인할 수 있으며, `Prometheus`는 이 데이터를 수집하여 시계열 데이터로 저장합니다. 이를 기반으로 애플리케이션의 상태를 실시간으로 분석하거나 경고를 설정할 수 있습니다.
사용 라이브러리
implementation("org.springframework.boot:spring-boot-starter-web") // HTTP를 통한 접속
implementation("org.springframework.boot:spring-boot-starter-actuator") // 애플리케이션의 성능과 상태를 모니터링할 수 있는 엔드포인트 제공
runtimeOnly("io.micrometer:micrometer-registry-prometheus") // 메트릭 수집과 모니터링을 제공
micrometer란?
애플리케이션의 메트릭 데이터를 수집하고 다양한 모니터링 시스템과 연동할 수 있도록 지원하는 애플리케이션 메트릭 라이브러리 입니다.
`SpringBoot`에서 기본적으로 `Actuator`와 통합되어 있으며, 다양한 모니터링 도구와 통합이 가능합니다.
모니터링 도구 (Prometheus, Grafana, Datadog, InfluxDB, New Relic, AWS CloudWatch 등)
`메트릭 데이터 수집` → `데이터 포맷팅 및 노출` → `외부 시스템과 통합`
한마디로, `Micrometer`는 `SpringBoot` 애플리케이션과 외부 모니터링 시스템 간의 다리 역할을 합니다. `SpringBoot` 내부 데이터를 모니터링 시스템에서 이해할 수 있는 형식으로 변환하고 전달해주는 도구입니다.
application.yml 설정
management:
endpoints:
web:
exposure:
include: health, info, metrics, prometheus
- management: SpringBoot의 관리 기능으로, 애플리케이션은 내장된 모니터링 엔드포인트를 제공합니다.
- endpoints: 애플리케이션에서 제공하는 다양한 모니터링 엔드포인트를 정의합니다.
- web: endpoints에 정의된 엔드포인트가 `웹 기반`으로 접근 가능한지에 대한 여부, `HTTP` 요청을 통해 엔드포인트에 접근할 수 있드록 설정합니다.
- exposure: 접근 제어 정책을 설정합니다. 해당 설정을 통해 어떤 엔드포인트가 웹에서 접근 가능하게 될지를 정의합니다.
- include
- health: 애플리케이션의 상태 `/actuator/health`
- info: 애플리케이션의 정보 `/actuator/info`
- metrics: 애플리케이션의 메트릭 데이터를 수집하고 제공 `/actuator/metrics`
- prometheus: `prometheus`와 통합된 메트릭 데이터를 수집, 메트릭 데이터를 수집하고 시각화 `/actuator/prometheus`
`application.yml`설정을 마치고 난 후, `Actuator`가 제공하는 URL을 확인할 수 있습니다.
docker-compose.yml 설정
`docker-compose.yml` 설정에서 `Prometheus` 컨테이너를 정의합니다.
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
container_name: prometheus
- image: Docker 컨테이너의 이미지를 정의하며, `latest`는 최신버전을 의미합니다.
- ports: 사용할 포트를 지정하며, 위의 설정에서는 localhost:9090을 통해 Prometheus 웹 인터페이스에 접근이 가능합니다.
- volumes: 외부 파일을 컨테이너에 매핑하여 설정 파일 등을 사용할 수 있게 합니다. 위의 설정에서는 `Prometheus` 설정 파일을 프로젝트의 `./prometheus.yml` 경로에서 컨테이너 내의 `/etc/prometheus/prometheus.yml`로 마운트 합니다.
- container_name: Docker 컨테이너의 이름을 지정합니다.
# docker-compose 실행
$ docker-compose up -d
# docker-compose 정리
$ docker-compose down
Prometheus 접속
`docker-compose`를 실행한 뒤, `http://localhost:9090`을 통해 `Prometheus`에 접속합니다.
상단 메뉴에서 `Status` → `Target health`로 이동하여 SpringBoot 애플리케이션을 수신하고 있는지 확인이 가능합니다.
Grafana
`Grafana`는 오픈 소스 시각화 및 대시보드 도구로, 여러 데이터 소스의 메트릭을 시각적으로 표현하고 분석할 수 있습니다.
`Prometheus`와 함께 사용하여 애플리케이션의 성능, 상태, 트래픽 데이터를 시각적으로 모니터링할 때 주로 사용됩니다.
docker-compose.yml 설정
`Grafana`도 `Prometheus`와 마찬가지로 `docker-compose`를 통해 관리가 가능합니다.
grafana:
image: "grafana/grafana:latest"
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=1234
container_name: grafana
위의 `Prometheus`에서 설정한 docker-compose.yml 파일의 `services depth`에 해당 설정을 추가합니다.
- environment
- GF_SECURITY_ADMIN_USER: 사용자 이름 설정
- GF_SECURITY_ADMIN_PASSWORD: 사용자 비밀번호 설정
설정 후 마찬가지로 `docker-compose up -d` 를 통해 실행합니다.
Grafana 접속
docker-compose를 실행한 뒤, `http://localhost:3000`을 통해 `Grafana`에 접속합니다.
`docker-compose`에서 지정한 사용자 이름과 비밀번호를 입력하여 로그인합니다.
data source 추가
로컬에 존재하는 `Prometheus`에 메트릭 데이터가 저장되어 있는 data source를 추가합니다.
경로 이동 후 해당 입력란에 `http://host.docker.internal:9090`을 입력합니다.
`Prometheus`의 포트를 앞서 설정하여 `http://localhost:9090`을 통하여 접속했었습니다.
Docker 컨테이너 내에서 외부 네트워크에 접근할 수 있도록 포트번호를 `Prometheus`의 포트로 설정하여 입력합니다.
`Save & test`를 클릭해 `Successfully queried the Prometheus API.`문구가 나온다면 정상적으로 추가된 것입니다.
Dashboards 추가
data source를 추가한 뒤 추가하는 대시보드는 `Grafana` 유저들이 공유하는 community dashboard 입니다. SpringBoot 애플리케이션에 널리 사용되는 `JVM dashboard`를 추가합니다.
Grafana Labs 에 접속합니다.
`Grafana Labs`에 접속하여 `SpringBoot 검색` → `JVM`을 선택합니다.
스크롤을 내리면 나오는 우측의 `ID`값을 복사합니다.
다시 `Grafana`로 이동하여 `Import dashboard`를 검색합니다.
복사한 `ID`를 입력 후 `Load`를 클릭합니다.
`Prometheus`로 앞서 생성한 `data source`를 선택 후 `import`를 클릭합니다.
import 후 `Prometheus`의 정보를 바탕으로 대시보드가 표현되는 모습을 볼 수 있습니다.
Grafana 대시보드 메트릭
표현되는 대시보드 메트릭은 다음과 같습니다.
카테고리 | 메트릭 | 설명 |
Quick Facts | Uptime | 애플리케이션이 시작된 이후 경과 시간 (초 단위) |
Start Time | 애플리케이션이 시작된 시간 | |
Heap Used | JVM에서 사용중인 힙 메모리 크기 (MB 단위) | |
Non-Heap Used | JVM에서 사용중인 논힙 메모리 크기 (MB 단위) | |
I/O Overview | Rate | I/O 작업의 초당 요청 속도 |
Errors | 발생한 I/O 작업 오류 수 | |
Duration | I/O 작업의 평균 실행 시간 | |
Utillisation | I/O 리소스의 사용률 | |
JVM Memory | JVM Heap | JVM에서 힙 메모리 사용량 |
JVM Non-Heap | JVM에서 논힙 메모리 사용량 | |
JVM Total | JVM에서 전체 메모리 사용량 | |
JVM Process Memory | JVM 프로세스가 사용하는 메모리 양 | |
JVM Misc | CPU Usage | 애플리케이션의 CPU 사용량 |
Load | 시스템의 CPU 부하 | |
Threads | JVM에서 실행 중인 스레드 수 | |
Threads States | JVM 스레드의 상태 (RUNNABLE, WAITING 등) | |
GC Pressure | 가비지 컬렉션 활동의 빈도 | |
Log Events | 로깅 이벤트 수 | |
File Descriptors | JVM에서 열려 있는 파일 디스크립터 수 | |
JVM Memory Pools (Heap) | G1 Eden Space | G1 GC의 Eden 메모리 공간 |
G1 Old Gen | G1 GC의 Old Generation 메모리 공간 | |
G1 Survivor Space | G1 GC의 Survivor 메모리 공간 | |
JVM Memory Pools (Non-Heap) | Metaspace | JVM Metaspace 메모리 공간 |
Compressed Class Space | JVM에서 압축된 클래스 공간 | |
CodeCache | JVM 코드 캐시 메모리 | |
Garbage Collection | Collections | GC가 실행된 횟수 |
Pause Durations | GC로 인해 발생한 애플리케이션 일시 중지 시간 | |
Allocated/Promoted | GC에 의해 힙 메모리에서 이동된 객체 크기 | |
Classloading | Classes Loaded | JVM에서 로드된 클래스 수 |
Class Delta | 클래스 로드 및 언로드의 변화량 | |
Buffer Pools | Direct | JVM Direct Buffer Pool 사용량 |
Mapped | JVM Mapped Buffer Pool 사용량 | |
Mapped - 'Non-Volatile Memory' | JVM Mapped Buffer Pool 중 비휘발성 메모리 사용량 |
마무리
애플리케이션의 성능과 상태를 지속적으로 모니터링하는 것은 안정성과 확장성을 유지하는 데 매우 중요한 역할을 하며, `Prometheus`와 `Grafana`는 이를 효과적으로 지원하는 도구입니다.
`Prometheus`는 애플리케이션의 성능 지표를 수집하고 시계열 데이터로 저장하여, 실시간으로 애플리케이션 상태를 추적할 수 있게 합니다.
`Grafana`를 통해 수집된 데이터를 시각적으로 표현하여 다양한 메트릭을 분석하고, 직관적인 대시보드 형테로 제공하여 사용자는 쉽게 시스템의 상태와 성능을 모니터링하고 관리할 수 있습니다.
'Spring' 카테고리의 다른 글
[SpringBoot] AWS SES로 이메일 전송 기능 구현하기 (0) | 2025.01.12 |
---|---|
[SpringBoot] 다양한 동시성 제어 방법 (2) | 2024.12.20 |
[Spring] Redis를 사용한Session 로그인 구현, Security없이 인증, 인가 구현 (26) | 2024.11.14 |
[Spring] offset, no offset 차이점과 페이지네이션 구현예제 (6) | 2024.10.23 |
[Spring] RequestBody, Response의 값이 null 일 때, JSON의 직렬화 역직렬화 (0) | 2024.10.10 |