티스토리 뷰
애플리케이션에서 발생한 메트릭을 그 순간만 확인하는 것이 아니라 과거 이력까지 함께 확인하려면 메트릭을 보관하는 DB가 필요하다. 이렇게 하려면 어디선가 메트릭을 지속해서 수집하고 DB에 저장해야 한다. 프로메테우스가 바로 이런 역할을 담당한다.
전체 구조
- 스프링 부트 액츄에이터와 마이크로미터를 사용하면 수 많은 메트릭을 자동으로 생성한다.
1.1 마이크로미터 프로메테우스 구현체는 프로메테우스가 읽을 수 있는 포멧으로 메트릭을 생성한다. - 프로메테우스는 이렇게 만들어진 메트릭을 지속해서 수집한다.
- 프로메테우스는 수집한 메트릭을 내부 DB에 저장한다.
- 사용자는 그라파나 대시보드 툴을 통해 그래프로 편리하게 메트릭을 조회한다. 이때 필요한 데이터는 프로메테우스를 통해서 조회한다.
프로메테우스 아키텍처
프로메테우스 - 애플리케이션 설정
프로메테우스는 메트릭을 수집하고 보관하는 DB이다.
이번에는 프로메테우스가 우리 애플리케이션의 메트릭을 수집하도록 연동해보겠다. 여기에는 2가지 작업이 필요하다.
- 애플리케이션 설정: 프로메테우스가 애플리케이션의 메트릭을 가져갈 수 있도록 애플리케이션에서 프로메테우스 포멧에 맞추어 메트릭 만들기
- 프로메테우스 설정: 프로메테우스가 우리 애플리케이션의 메트릭을 주기적으로 수집하도록 설정
프로메테우스가 애플리케이션의 메트릭을 가져가려면 프로메테우스가 사용하는 포멧에 맞추어 메트릭을 만들어야 한다.
참고로 프로메테우스는 /actuator/metrics
에서 보았던 포멧(JSON)은 이해하지 못하지만, 마이크로미터가 이런 부분은 모두 해결해준다.
각각의 메트릭들은 내부에서 마이크로미터 표준 방식으로 측정되고 있다. 따라서 어떤 구현체를 사용할지 지정만 해주면 된다.
build.gradle 추가
implementation 'io.micrometer:micrometer-registry-prometheus'
- 마이크로미터 프로메테우스 구현 라이브러리를 추가하면, 스프링 부트와 액츄에이터가 자동으로 마이크로미터 프로메테우스 구현체를 등록해서 동작하도록 설정해준다.
- 또한, 액츄에이터에 프로메테우스 메트릭 수집 엔드포인트가 자동으로 추가된다.
/actuator/prometheus
localhost:8080/actuator/prometheus 접속 결과
# HELP jvm_threads_states_threads The current number of threads
# TYPE jvm_threads_states_threads gauge
jvm_threads_states_threads{state="runnable",} 9.0
jvm_threads_states_threads{state="blocked",} 0.0
jvm_threads_states_threads{state="waiting",} 11.0
jvm_threads_states_threads{state="timed-waiting",} 7.0
jvm_threads_states_threads{state="new",} 0.0
jvm_threads_states_threads{state="terminated",} 0.0
# HELP tomcat_global_received_bytes_total
# TYPE tomcat_global_received_bytes_total counter
tomcat_global_received_bytes_total{name="http-nio-8080",} 0.0
# HELP system_cpu_usage The "recent cpu usage" of the system the application is running in
# TYPE system_cpu_usage gauge
system_cpu_usage 0.0
# HELP hikaricp_connections_idle Idle connections
# TYPE hikaricp_connections_idle gauge
hikaricp_connections_idle{pool="HikariPool-1",} 10.0
# HELP application_started_time_seconds Time taken (ms) to start the application
# TYPE application_started_time_seconds gauge
application_started_time_seconds{main_application_class="hello.ActuatorApplication",} 6.228
# HELP tomcat_threads_config_max_threads
# TYPE tomcat_threads_config_max_threads gauge
tomcat_threads_config_max_threads{name="http-nio-8080",} 200.0
# HELP executor_completed_tasks_total The approximate total number of tasks that have completed execution
# TYPE executor_completed_tasks_total counter
executor_completed_tasks_total{name="applicationTaskExecutor",} 0.0
# HELP jvm_buffer_memory_used_bytes An estimate of the memory that the Java virtual machine is using for this buffer pool
# TYPE jvm_buffer_memory_used_bytes gauge
jvm_buffer_memory_used_bytes{id="mapped - 'non-volatile memory'",} 0.0
jvm_buffer_memory_used_bytes{id="mapped",} 0.0
jvm_buffer_memory_used_bytes{id="direct",} 40960.0
# HELP jdbc_connections_min Minimum number of idle connections in the pool.
# TYPE jdbc_connections_min gauge
jdbc_connections_min{name="dataSource",} 10.0
...
- 모든 메트릭이 프로메테우스 포멧으로 만들어 진 것을 확인할 수 있다.
포멧 차이
localhost:8080/actuator/metrics/jvm.info 접속 결과
{
"name": "jvm.info",
"description": "JVM version info",
"measurements": [
{
"statistic": "VALUE",
"value": 1.0
}
],
"availableTags": [
{
"tag": "vendor",
"values": [
"Eclipse Adoptium"
]
},
{
"tag": "runtime",
"values": [
"OpenJDK Runtime Environment"
]
},
{
"tag": "version",
"values": [
"17.0.5+8"
]
}
]
}
localhost:8080/actuator/prometheus에서 살펴본 jvm.info 정보
jvm_info{runtime="OpenJDK Runtime Environment",vendor="Eclipse Adoptium",version="17.0.5+8",} 1.0
jvm.info
->jvm_info
: 프로메테우스는.
대신에_
포멧을 사용한다.
프로메테우스 - 수집 설정
이제 프로메테우스가 애플리케이션의 /actuator/prometheus
를 호출해서 메트릭을 주기적으로 수집하도록 설정하기 위해 프로메테우스 폴더에 있는 prometheus.yml
파일에 아래 내용을 추가하자.
prometheus.yml
- job_name: "spring-actuator"
metrics_path: '/actuator/prometheus'
scrape_interval: 1s
static_configs:
- targets: ['localhost:8080']
- 앞의 띄어쓰기 2칸에 유의하자
job_name
: 수집하는 이름이다. 임의의 이름을 사용하면 된다.metrics_path
: 수집할 경로를 지정한다./actuator/prometheus
의 내용을 수집한다.scrape_interval
: 수집할 주기를 설정한다.targets
: 수집할 서버의 IP, PORT를 지정한다.
이렇게 설정하면 프로메테우스는 다음 경로를 1초에 한번씩 호출해서 애플리케이션의 메트릭들을 수집한다.
참고scrape_interval
의 값을 빠르게 확인하기 위해서 수집 주기를 1s
로 했지만, 수집 주기의 기본 값은 1m
이다. 수집 주기가 너무 짧으면 애플리케이션 성능에 영향을 줄 수 있으므로, 운영에서는 10s ~ 1m
정도를 권장한다. (물론 시스템 상황에 따라서 다르다.)
프로메테우스 연동 확인
터미널에서 프로메테우스 설치 폴더로 이동하여 ./prometheus
명령어로 프로메테우스를 실행한 뒤, http://localhost:9090/config
에 접속해보면 prometheus.yml
에 설정한 내용이 반영되어 있는 모습을 확인할 수 있다.
localhost:9090/config 접속 결과
프로메테우스 연동 확인 화면
http://localhost:9090/targets
로 접속해보면, 방금 연동한 애플리케이션의 메트릭 정보가 연동된 모습을 확인할 수 있다.
localhost:9090/targets 접속 결과
prometheus
: 프로메테우스 자체에서 제공하는 메트릭 정보이다. (프로메테우스가 프로메테우스 자신의 메트릭을 확인하는 것이다.)spring-actuator
: 우리가 연동한 애플리케이션의 메트릭 정보이다.State
가UP
으로 되어 있으면 정상이고,DOWN
으로 되어 있으면 연동이 안된 것이다.
프로메테우스를 통한 데이터 조회
프로메테우스 홈 화면으로 이동한 뒤, jvm_info
를 검색창에 넣고 실행해보면 수집한 메트릭을 조회할 수 있다.
프로메테우스 - 기본 기능
프로메테우스를 사용하는데 필요한 간단한 기능들을 알아보자. 검색창에 http_server_requests_seconds_count
를 입력하고 실행해보자
http_server_requests_seconds_count 검색 결과
- 태그, 레이블:
error
,exception
,instance
,job
,method
,outcome
,status
,uri
는 각각의 메트릭 정보를 구분해서 사용하기 위한 태그이다. 마이크로미터에서는 이것을 태그(Tag
)라 하고, 프로메테우스에서는 레이블(Label
)이라 한다. 둘을 구분하지 않고 사용할 것이다. - 숫자: 끝에 마지막에 보면
800
,1
과 같은 숫자는 해당uri
로 요청한 횟수를 나타낸다.
Graph
를 눌러 메트릭을 그래프로 조회할수도 있다.
필터
중괄호({}
) 문법을 사용하여 레이블을 기준으로 필터를 사용할 수 있다.
레이블 일치 연산자
=
: 제공된 문자열과 정확히 동일한 레이블 선택!=
: 제공된 문자열과 같지 않은 레이블 선택=~
: 제공된 문자열과 정규식 일치하는 레이블 선택!~
: 제공된 문자열과 정규식 일치하지 않는 레이블 선택
예시
uri=/log
,method=GET
조건으로 필터:http_server_requests_seconds_count{uri="/log", method="GET"}
/log
는 제외한 조건으로 필터:http_server_requests_seconds_count{uri!="/log"}
method
가GET
,POST
인 경우를 포함해서 필터:http_server_requests_seconds_count{method=~"GET|POST"}
/actuator
로 시작하는uri
는 제외한 조건으로 필터:http_server_requests_seconds_count{uri!~"/actuator.*"}
http_server_requests_seconds_count{uri="/log"} 실행 결과
uri
의 정보가/log
인 내역만 조회 된다.
프로메테우스 - 게이지와 카운터
메트릭은 크게 보면 게이지와 카운터라는 2가지로 분류할 수 있다.
게이지(Gauge)
- 임의로 오르내일 수 있는 값
- 예) CPU 사용량, 메모리 사용량, 사용중인 커넥션
카운터(Counter)
- 단순하게 증가하는 단일 누적 값
- 예) HTTP 요청 수, 로그 발생 수
게이지(Gauge)
게이지는 오르고 내리고 하는 값으로, 현재 상태를 그대로 출력한다.
- 게이지는 가장 단순하고 사용하기 쉬운 메트릭이다
- CPU 사용량의 현재 상태를 계속 측정하고 그 값을 그대로 그래프에 출력하면 과거부터 지금까지의 CPU 사용량을 확인할 수 있다.
카운터(Counter)
카운터는 단순하게 고객의 HTTP 요청수와 같이 증가하는 단일 누적 값이다.
카운터는 계속 누적해서 증가하는 값이기 때문에 계속 증가하는 그래프만 보게 된다. 이렇게 증가만 하는 그래프에서는 특정 시간에 얼마나 고객의 요청이 들어왔는지 한눈에 확인하기 매우 어렵다. 이런 문제를 해결하기 위해 increase()
, rate()
같은 함수를 지원한다.
increase()
increase()
를 사용하면 지정한 시간 단위별로 증가를 확인할 수 있다. 마지막에 [시간]
을 사용해서 범위 벡터를 선택해야 한다.예) increase(http_server_requests_seconds_count{uri="/log"}[1m])
- 09.28 ~ 09.30: 약 60건 요청
- 09.28 ~ 09.33: 0건 요청
- 09.28 ~ 09.35: 약 13건 요청
분당 얼마나 고객의 요청이 어느정도 증가했는지 한눈에 파악할 수 있다.
rate()
범위 백터에서 초당 평균 증가율을 계산한다. increase()
가 숫자를 직접 카운트 한다면, rate()
는 여기에 초당 평균을 나누어서 계산한다.
increase(data[1m])
에서[1m]
이라고 하면 60초가 기준이 되므로 60을 나눈 수이다.increase(data[2m])
에서[2m]
이라고 하면 120초가 기준이 되므로 120을 나눈 수
Reference
김영한. 스프링 부트 - 핵심 원리와 활용. 인프런.
'Spring' 카테고리의 다른 글
[Spring Webflux] Cold Sequence & Hot Sequence (0) | 2024.01.07 |
---|---|
[Spring] 메트릭(metric)을 직접 등록해보자 (0) | 2023.04.17 |
[Spring] 메트릭 (metric) (0) | 2023.04.13 |
[Spring] actuator (액츄에이터) (0) | 2023.04.10 |
[Spring] YAML , @Profile (0) | 2023.04.09 |
- Total
- Today
- Yesterday
- 백준
- mysql 8.0
- MySQL
- 코테
- 스프링
- Real MySQL
- 문자열
- 노마드코더
- spring boot
- Algorithm
- 정렬
- 북클럽
- kotlin
- 알고리즘
- 파이썬
- 스프링부트
- 자료구조
- 스프링 부트
- 릿코드
- 그리디
- 김영한
- 노마드
- 코틀린
- 구현
- 데이터베이스
- 리팩토링
- leetcode
- Spring
- webflux
- 인프런
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |