서비스를 운영할 때 애플리케이션의 CPU, 메모리, 커넥션 사용, 고객 요청 수 같은 많은 지표들을 확인하는 것이 필요하다.
그래야 어디에 어떤 문제가 발생했는지에 따라 대응할 수 있고 실제 문제가 발생하더라도 원인을 빠르게 파악해 대처할 수 있다.
예를 들어 메모리 사용량이 가득 찬 경우라면 메모리 문제와 관련있는 곳을 빠르게 찾아 대응할 수 있다.
이를 확인하기 위해 모니터링 툴을 사용하는데, 시스템의 다양한 정보를 이 모니터링 툴에 전달해 사용하게 된다.
- 그라파나 대시보드
- 핀포인트
이러한 모니터링 툴이 동작하려면 시스템의 다양한 지표들을 각각의 모니터링 툴에 맞추어 만들어 보내주어야 한다. (물론 라이브러리등을 통해 자동화되는 경우가 많다.)
마이크로미터
예를 들어 위와 같이 CPU, JVM, 커넥션 정보 등을 JMX 툴에 전달한다고 가정해보자.
그렇다면 각각의 정보를 JMX 모니터링 툴이 정한 포맷에 맞게 전달해야 한다.
그런데 만약 중간에 사용하는 모니터링 툴을 변경해야 한다면?
기존에 측정했던 코드를 모두 변경한 툴에 맞도록 다시 변경해야 한다. 개발자 입장에서는 단순하게 모니터링 툴 하나를 변경했을 뿐인데, 측정하는 코드까지 모두 변경해야 한다.
이런 문제를 해결할 수 있도록 도와주는 것이 마이크로미터라는 라이브러리이다.
마이크로미터 추상화
CPU, JVM, 커넥션 같은 여러 메트릭을 마이크로미터가 제공하는 표준 측정 방식에 맞추어 전달한다.
그러면 그 표준 측정 방식에 맞는 마이크로미터 구현체를 모니터링 툴에 맞게 구현하면 된다.
이 구현체는 구현이 이미 되어있고 우리는 선택만 하면 된다.
- 마이크로미터는 애플리케이션 메트릭 파사드라고 불린다.
- 애플리케이션의 메트릭(측정 지표)을 마이크로미터가 정한 표준 방법으로 모아 제공해준다.
- 마이크로미터가 추상화를 통해 구현체를 쉽게 갈아끼울 수 있도록 한 것이다.
- 보통 스프링이 이러한 추상화를 직접 만들어 제공하지만, 마이크로미터라는 잘 만들어진 추상화가 있어 스프링이 이것을 활용한다.
- 스프링부트 액츄에이터는 마이크로미터를 내장해 사용한다.
- 로그를 추상화하는 SLF4J와 비슷하다고 보면 된다.
- 개발자의 입장에서는 마이크로미터가 정한 표준 방법으로 메트릭을 전달하면 된다. 그리고 사용하는 모니터링 툴에 맞는 구현체를 선택하면 된다.
- 애플리케이션 코드는 모니터링 툴이 변경되어도 유지할 수 있다.
메트릭
CPU, JVM, 커넥션 사용 등 많은 지표들을 수집하는 방법을 알아보자.
개발자가 각각의 직접 수집해 그것을 마이크로미터가 제공하는 표준 방법에 따라 등록해야 한다.
그러나 마이크로미터가 다양한 지표 수집 기능을 이미 만들어 제공하고, 스프링 부트 액츄에이터가 마이크로미터가 제공하는 지표 수집을 @AutoConfiguration을 통해 자동으로 등록해준다.
따라서 스프링 부트 액츄에이터를 활용하면 수 많은 메트릭을 편리하게 사용할 수 있다.
기본으로 제공하는 메트릭들을 확인해보자.
/actuator/metrics를 통해 확인할 수 있다.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
{
"names": [
"application.ready.time",
"application.started.time",
"disk.free",
"disk.total",
"executor.active",
"executor.completed",
"executor.pool.core",
"executor.pool.max",
"executor.pool.size",
"executor.queue.remaining",
"executor.queued",
"hikaricp.connections",
"hikaricp.connections.acquire",
"hikaricp.connections.active",
"hikaricp.connections.creation",
"hikaricp.connections.idle",
"hikaricp.connections.max",
"hikaricp.connections.min",
"hikaricp.connections.pending",
"hikaricp.connections.timeout",
"hikaricp.connections.usage",
"http.server.requests",
"http.server.requests.active",
"jdbc.connections.active",
"jdbc.connections.idle",
"jdbc.connections.max",
"jdbc.connections.min",
"jvm.buffer.count",
"jvm.buffer.memory.used",
"jvm.buffer.total.capacity",
"jvm.classes.loaded",
"jvm.classes.unloaded",
"jvm.compilation.time",
"jvm.gc.live.data.size",
"jvm.gc.max.data.size",
"jvm.gc.memory.allocated",
"jvm.gc.memory.promoted",
"jvm.gc.overhead",
"jvm.gc.pause",
"jvm.info",
"jvm.memory.committed",
"jvm.memory.max",
"jvm.memory.usage.after.gc",
"jvm.memory.used",
"jvm.threads.daemon",
"jvm.threads.live",
"jvm.threads.peak",
"jvm.threads.states",
"logback.events",
"process.cpu.usage",
"process.start.time",
"process.uptime",
"system.cpu.count",
"system.cpu.usage",
"tomcat.sessions.active.current",
"tomcat.sessions.active.max",
"tomcat.sessions.alive.max",
"tomcat.sessions.created",
"tomcat.sessions.expired",
"tomcat.sessions.rejected"
]
}
- HTTP 요청
- 쓰레드
- 메모리 사용량
여러 정보가 있다.
1
http://localhost:8080/actuator/metrics/{name}
이 정보로 해당 정보에만 접근이 가능하다.
1
2
http://localhost:8080/actuator/metrics/jvm.memory.used
http://localhost:8080/actuator/metrics/http.server.requests
HTTP 요청은 상세하게 필터링하여 볼 수도 있다.
1
localhost:8080/actuator/metrics/http.server.requests?tag=uri:/log
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{
"name": "http.server.requests",
"baseUnit": "seconds",
"measurements": [
{
"statistic": "COUNT",
"value": 6.0
},
{
"statistic": "TOTAL_TIME",
"value": 0.0147571
},
{
"statistic": "MAX",
"value": 0.0040493
}
],
"availableTags": [
{
"tag": "exception",
"values": [
"none"
]
},
{
"tag": "method",
"values": [
"GET"
]
},
{
"tag": "error",
"values": [
"none"
]
},
{
"tag": "outcome",
"values": [
"SUCCESS"
]
},
{
"tag": "status",
"values": [
"200"
]
}
]
}
메트릭 종류
위에 어떤 메트릭이 있는지 보았는데 관련 메트릭들을 설명해본다.
마이크로미터와 액츄에이터가 기본으로 제공하는 다양한 메트릭을 확인해보자.
JVM 메트릭
JVM 관련 메트릭을 제공하고 jvm. 으로 시작한다.
- 메모리 및 버퍼 풀 세부 정보
- 가비지 수집 관련 통계
- 쓰레드 활용
- 로드 및 언로드된 클래스 수
- JVM 버전 정보
- JIT 컴파일 시간
시스템 메트릭
시스템 메트릭을 제공한다. system. , process. , disk. 로 시작한다.
- CPU 지표
- 파일 디스클비터 메트릭
- 가동 시간 메트릭
- 사용 가능한 디스크 공간
애플리케이션 시작 메트릭
애플리케이션 시작 시간 메트릭을 제공한다.
- application.started.time: 애플리케이션을 시작하는데 걸리는 시간
- ApplicationStartedEvent로 측정
- 스프링 컨테이너가 완전히 실행된 상태. 이후 커맨드 라인 러너가 호출된다.
- application.ready.time: 애플리케이션이 요청을 처리할 준비가 되는데 걸리는 시간
- ApplicationReadyEvent로 측정
- 커맨드 라인 러너가 실행된 이후 호출된다.
스프링 MVC 메트릭
스프링 MVC 컨트롤러가 처리하는 모든 요청을 다룬다. 자주 사용한다.
호출 빈도와 처리 최대 시간 같은 정보가 유용하게 사용될 수 있다.
http.server.requests
- Tag를 사용해 아래 정보를 분류하여 확인할 수 있다.
- uri: 요청 URI
- method: GET, POST 등 HTTP 메서드
- status: 200, 400, 500 같은 HTTP Status 메서드
- exception: 예외
- outcome: 상태코드를 그룹으로 모아 확인
- 1xx: INFORMATIONAL
- 2xx: SUCCESS
- 3xx: REDIRECTION
- 4xx: CLIENT_ERROR
- 5xx: SERVER_ERROR
데이터소스 메트릭
DataSource, 커넥션 풀에 관한 메트릭을 확인할 수 있다.
jdbc.connections. 로 시작한다.
최대 커넥션, 최소 커넥션, 활성 커넥션, 대기 커넥션 수 등을 확인할 수 있다.
히카리 커넥션 풀을 사용한다면 hikaricp. 를 통해 히카리 커넥션 풀의 자세한 메트릭을 확인할 수 있다.
로그 메트릭
logback 로그에 대한 메트릭을 확인할 수 있다.
logback.events
각각의 로그 레벨에 따른 로그 수를 확인할 수 있다.
예를 들어 ERROR 로그 수가 급격히 높아진다면 위험한 신호로 받을 수 있다.
톰캣 메트릭
tomcat. 으로 시작한다. 유용하게 사용된다.
톰캣 메트릭을 모두 사용하려면 아래옵션을 켜야한다. 켜지 않으면 tomcat.session. 관련 정보만 노출된다.
1
server.tomcat.mbeanregistry.enabled=true
톰캣의 최대 쓰레드, 사용 쓰레드 수를 포함한 다양한 메트릭을 확인할 수 있다.
기타
- HTTP 클라이언트 메트릭 (RestTemplate, WebClient)
- 캐시 메트릭
- 작업 실행과 스케줄 메트릭
- 스프링 데이터 리포지토리 메트릭
- 몽고 DB 메트릭
- 레디스 메트릭