관리 메뉴

나구리의 개발공부기록

마이크로미터/프로메테우스/그라파나, 마이크로미터 소개, 메트릭 확인하기, 다양한 메트릭, 프로메테우스와 그라파나 소개, 프로메테우스(설치/애플리케이션 설정/ 수집 설정/ 기본 기능/게이지와 카운터), 그라파나(설치 및 연동/대시보드 만들기/공유 대시보드 활용/메트릭을 통한 문제 확인) 본문

인프런 - 스프링 완전정복 코스 로드맵/스프링 부트 - 핵심 원리와 활용

마이크로미터/프로메테우스/그라파나, 마이크로미터 소개, 메트릭 확인하기, 다양한 메트릭, 프로메테우스와 그라파나 소개, 프로메테우스(설치/애플리케이션 설정/ 수집 설정/ 기본 기능/게이지와 카운터), 그라파나(설치 및 연동/대시보드 만들기/공유 대시보드 활용/메트릭을 통한 문제 확인)

소소한나구리 2024. 12. 8. 21:26

출처 : 인프런 - 스프링 부트 - 핵심 원리와 활용(유료) / 김영한님  
유료 강의이므로 정리에 초점을 두고 코드는 일부만 인용


1. 마이크로미터 소개

(1) 모니터링 툴

  • 회사의 환경마다 다르긴 하지만 대부분의 서비스 회사들은 개발자가 배포, 운영을 직접 다하여 개발의 전체 사이클을 직접 운영함
  • 이렇게 개발의 전체 사이클을 경험해 볼 수 있는 환경은 개발자가 성장하기위한 좋은 환경임
  • 서비스를 운영할 때는 애플리케이션의 CPU, 메모리, 커넥션 사용, 고객 요청수 같은 수많은 지표들을 확인하는 것이 필요함
  • 그래야 어디에 어떤 문제가 발생했는지 사전에 대응할 수도 있고 실제 문제가 발생해도 원인을 빠르게 파악해서 대처할 수 있음
  • 세상에는 수많은 모니터링 툴이 있고 시스템의 다양한 정보를 이 모니터링 툴에 전달해서 사용하게 되는데, 모니터링 툴이 작동하려면 시스템의 다양한 지표들을 각각의 모니터링 툴에 맞도록 만들어서 보내주어야 함
  • (실제로는 라이브러리등을 통해서 자동화 되는 경우가 많음)

(2) 모니터링 툴에 지표 전달

  • 예를 들어 CPU, JVM, 커넥션 정보 등을 JMX 툴에 전달한다고 가정해보면 각각의 정보를 JMX 모니터링 툴이 정한 포맷에 맞추어서 측정하고 전달해야함

(3) 모니터링 툴 변경

  • 그런데, 중간에 사용하는 모니터링 툴을 변경하게되면 기존에 측정했던 코드를 변경한 툴에 맞도록 다시 만들어서 보내주어야 함
  • 단순히 개발자 입장에서는 단순히 툴 하나를 변경했을 뿐인데 측정하는 코드까지 모두 변경해야 하는 문제가 발생하는데, 이런 문제를 해결하는 것이 마이크로미터(Micrometer)라는 라이브러리임

(4) 마이크로미터 추상화

  • 마이크로미터는 애플리케이션 메트릭 파사드라고 불리는데 애플리케이션의 메트릭(측정 지표)를 마이크로미터가 정한 표준 방법으로 모아서 제공해줌
  • 즉 마이크로미터가 추상화를 통해서 구현체를 쉽게 갈아끼울 수 있도록 해두었음
  • 보통은 스프링이 이런 추상화를 직접 만들어서 제공하지만 마이크로미터라는 이미 잘 만드러진 추상화가 있기 때문에 스프링은 이것을 활용하며 스프링 부트 액츄에이터는 마이크로미터를 기본으로 내장에서 사용함
  • 로그를 추상화 하는 SLF4J와 동작방식을 생각해보면 쉽게 이해가 될 것임
  • 개발자는 마이크로미터가 정한 표준 방법으로 메트릭(측정 지표)를 전달하면 되며 사용하는 모니터링 툴에 맞는 구현체를 선택하면됨
  • 이후에 모니터링 툴이 변경되어도 해당 구현체만 변경하면되며 애플리케이션 코드는 모니터링 툴이 변경되어도 그대로 유지할 수 있음

(5) 마이크로미터가 지원하는 모니터링 툴

  • AppOptics
  • Atlas
  • CloudWatch
  • Datadog
  • Dynatrace
  • Elastic
  • Ganglia
  • Graphite
  • Humio
  • Influx
  • Instana
  • JMX
  • KairosDB
  • New Relic
  • Prometheus
  • SignalFx
  • Stackdriver
  • StatsD
  • Wavefront

** 참고


2. 메트릭 확인하기

1) 메트릭 확인

(1) 지표 수집

  • CPU, JVM, 커넥션 사용 등등 수많은 지표들을 수집하려면 개발자가 각각의 지표를 직접 수집해서 그것을 마이크로미터가 제공하는 표준 방법에 따라 등록해야함
  • 하지만 다행이도 마이크로미터는 다양한 지표 수집 기능을 이미 만들어서 제공하며 스프링 부트 액츄에이터는 마이크로미터가 제공하는 지표 수집을 @AutoConfiguration으로 자동으로 등록해줌
  • 스프링 부트 액츄에이터를 사용하면 수많은 메트릭을 편리하게 사용할 수 있음

(2) metrics 엔드포인트

  • metrics 엔드포인트를 사용하면 기본으로 제공되는 메트릭들을 확인할 수 있음
  • localhost:8080/actuator/metrics

(3) 자세히 확인하기

  • metrics 엔드포인트는 아래의 패턴을 사용해서 더 자세히 확인할 수 있음
  • localhost:8080/actuator/metrics/{name}
  • 만약 메모리 현재 메모리 사용량을 확인하려면 localhost:8080/actuator/metrics/jvm.memory.used를 입력해주면 됨

(4) Tag 필터

  • 메트릭을 자세히 출력 후 출력 결과의 availableTags를 보면 아래와 같은 항목을 확인할 수 있음
    - tag:area, values:[heap, nonheap]
    - tag:id, values[G1 survivor Space, ...]
  • 해당 Tag를 기반으로 정보를 필터링해서 확인할 수 있으며 tag=KEY:VALUE와 같은 형식을 사용해야 하며 아래의 예시처럼 tag를 URL에 추가 입력하면 Tag로 필터링된 결과를 확인할 수 있음
  • localhost:8080/actuator/metrics/jvm.memory.used?tag=area:heap
  • localhost:8080/actuator/metrics/jvm.memory.used?tag=area:nonheap

(5) HTTP 요청수 확인해보기

  • localhost:8080/actuator/metrics/http.server.requests로 들어가보면 해당 서버가 시작되고난 이후의 HTTP 요청수를 확인할 수 있음
  • /log 요청만 필터: localhost:8080/actuator/metrics/http.server.requests?tag=uri:/log

3. 다양한 메트릭

1) 마이크로미터와 액츄에이터가 기본으로 제공하는 다양한 메트릭들

(1) JVM 메트릭

  • JVM 관련 메트릭을 제공하며 jvm.으로 시작함
  • 메모리 및 버퍼 풀 세부 정보
  • 가비지 수집 관련 통계
  • 스레드 활용
  • 로드 및 언로드된 클래스 수
  • JVM 버전 정보
  • JIT 컴파일 시간 등등...

(2) 시스템 메트릭

  • 시스템 메트릭을 제공하며 system., process., disk. 로 시작함
  • CPU 지표
  • 파일 디스크립터 메트릭
  • 가동 시간 메트릭
  • 사용 가능한 디스크 공간

(3) 애플리케이션 시작 메트릭

  • 애플리케이션 시작 시간 메트릭을 제공
  • application.started.time: 애플리케이션을 시작하는데 걸리는 시간(ApplicationStartedEvent로 측정)
  • application.ready.time: 애플리케이션이 요청을 처리할 준비가 되는데 걸리는 시간(ApplicationReadyEvent로 측정)
  • 스프링은 내부에 여러 초기화 단계가 있으며 각 단계별로 내부에서 애플리케이션 이벤트를 발행함
  • ApplicationStartedEvent: 스프링 컨테이너가 완전히 실행된 상태이며 이후에 커맨드 라인 러너가 호출됨
  • ApplicationReadyEvent: 커맨드 라인 러너가 실행된 이후에 호출됨

(4) 스프링 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

(5) 데이터소스 메트릭

  • DataSource, 커넥션 풀에 관한 메트릭을 확인할 수 있음
  • jdbc.connections. 로 시직함
  • 최대, 최소, 활성, 대기 커넥션 수 등을 확인할 수 있음
  • 히카리 커넥션 풀을 사용하면 hikaricp. 를 통해 히카리 커넥션 풀의 자세한 메트릭을 확인할 수 있음

(6) 로그 메트릭

  • logback.events: logback 로그에 대한 메트릭을 확인할 수 있음
  • trace, debug, info, warn, error 각각의 로그 레벨에 따른 로그 수를 확인할 수 있음
  • 예를 들어 error 로그 수가 급격히 높아진다면 위험한 신호로 받아들일 수 있음

(7) 톰캣 메트릭

  • 톰캣 메트릭은 tomcat. 으로 시작함
  • 톰캣 메트릭을 사용하려면 다음 옵션을 켜야하며 옵션을 켜지 않으면 tomcat.session. 관련 정보만 노출됨
  • 해당 정보는 유용하므로 옵션을 키는 것을 권장함
  • application.yml에 아래처럼 옵션을 적용하고 메트릭을 확인해 보면 톰캣의 최대 쓰레드, 사용 쓰레드 수를 포함하여 다양한 메트릭을 확인할 수 있음
  • 이중에서 tomcat.threads.busy와 tomcat.threads.config.max는 꽤 유용함
server:
  tomcat:
    mbeanregistry:
      enabled: true

 

(8) 기타

  • HTTP 클라이언트 메트릭(RestTemplate, WebClient)
  • 캐시 메트릭
  • 작업 실행과 스케줄 메트릭
  • 스프링 데이터 리포지토리 메트릭
  • 몽고DB 메트릭
  • 레디스 메트릭

(9) 사용자 정의 메트릭

  • 사용자가 직접 메트릭을 정의할 수도 있으며 주문 수, 취소 수 등의 정보들을 메트릭으로 만들 수 있음
  • 사용자 정의 메트릭을 만들기 위해서는 마이크로미터의 사용법을 먼저 이해해야하므로 뒤에서 다룸
  • 사용자 정의 메트릭은 핵심 비즈니스의 중요한 메트릭을 수집할 때 상당히 유용하므로 어떻게 구축하는지 알아두는 것을 권장함
  • 즉, 시스템 메트릭은 기본으로 깔고 비즈니스 로직에서 필요한 정보들을 직접 정의하여 깔아두면 다양한 문제들을 모니터링으로 확인할 수 있음

(10) 정리

  • 액츄에이터를 통해서 수많은 메트릭이 자동으로 만들어지는 것을 확인할 수 있었음
  • 이러한 메트릭들을 어딘가에 보관해야 과거의 데이터들도 확인할 수 있으므로 메트릭을 지속적으로 수집하고 보관할 데이터베이스가 필요함
  • 그리고 메트릭들을 그래프를 통해서 한눈에 쉽게 확인할 수 있는 대시보드도 필요한데 이것이 프로메테우스와 그라파나임
  • 다양한 메트릭들은 공식 메뉴얼을 참고

4. 프로메테우스와 그라파나 소개

1) 소개

(1) 프로메테우스 소개

  • 애플리케이션에서 발생한 메트릭을 그 순간만 확인하는 것이 아니라 과거 이력까지 함께 확인하려면 메트릭을 보관하는 DB가 필요하고 어디선가 메트릭을 지속해서 수집하고 DB에 저장해야하는데 프로메테우스가 이런 역할을 담당함

(2) 그라파나 소개

  • 프로메테우스가 DB라고 하면 DB에 있는 데이터를 불러서 사용자가 보기 편하게 보여주는 대시보드가 필요한데 그라파나가 그런역할을 담당함
  • 그라파나는 매우 유연하고 데이터를 그래프로 보여주는 툴이며 수많은 그래프를 제공하고 프로메테우스를 포함한 다양한 데이터소스를 지원함(2023년 2월 28일 강의 게시기준으로는 트랜드라고함)

(3) 전체 구조

  • 1. 스프링 부트 액츄에이터와 마이크로미터를 사용하면 수많은 메트릭을 자동으로 생성함
  • - 마이크로미터 프로메테우스 구현체는 프로메테우스가 읽을 수 있는 포멧으로 메트릭을 생성함
  • 2. 프로메테우스는 이렇게 만들어진 메트릭을 지속해서 수집함
  • 3. 프로메테우스는 수집한 메트릭을 내부 DB에 저장함
  • 4. 사용자는 그라파나 대시보드 툴을 통해 그래프로 편리하게 메트릭을 조회하고 필요한 데이터는 프로메테우스를 통해서 조회함

(3) 프로메테우스 아키텍터

** 참고

  • 프로메테우스와 그라파나는 그 내용만 다루는 책이 있을 정도로 내용이 매우 방대하므로 자세한 내용은 별도의 학습이 필요함
  • 프로메테우스와 그라파나에 대한 자세한 내용은 강의 범위를 벗어나므로 여기서는 각각의 기술들을 어떻게 다루고 활용해야는지, 기초 내용과 올바른 방향을 설명하는데에 초점을 맞춤

5. 프로메테우스 - 설치 및 애플리케이션 설정

1) 설치

(1) 다운로드

  • 사이트
  • Mac OS 애플실리콘: OS - darwin, Arch - arm64 선택
  • Mac OS 인텔: OS - darwin, Arch - amd64 선택
  • Windows: OS - windows, Arch =- amd 64 선택

(2) 실행

  • Windows: prometheus.exe 실행(보안 창이 뜰 경우 추가 정보 클릭하여 강제 실행)
  • Mac OS:  터미널에서 다운받은 파일 위치로 이동하여 ./prometheus 실행하면 보안으로 막힐 텐데, mac 설정의 개인정보 보호 및 보안으로 가서 그래도 허용을 눌러주고 다시 실행하면 됨
  • 실행 후 localhost:9090으로 접속하면 프로메테우스 사이트가 뜸

** 참고

  • 애플 실리콘 사용시 amd 64를 사용하면 bad CPU type in executable or Permission denied 오류가 발생하는데 rosetta2 설치하여 해결할 수 있음

2) 프로메테우스 설정 - 애플리케이션 설정

  • 프로메테우스가 애플리케이션의 메트릭을 수집할 수 있도록 연동하기 위해서는 2가지 작업이 필요함
  • 애플리케이션 설정: 프로메테우스가 메트릭을 가져갈 수 있도록 애플리케이션에서 프로메테우스 포멧에 맞추어 메트릭 만들기
  • 프로메테우스 설정: 프로메테우스가 애플리케이션의 메트릭을 주기적으로 수집하도록 설정

(1) 애플리케이션 설정

  • 프로메테우스는 /actuator/metrics에서 보았던 포멧(JSON)은 이해하지 못하고 프로메테우스 자체 포맷으로 이해함
  • 그러나 포멧에 대한 부분은 걱정할 필요가 없이 마이크로미터가 모두 해결해주는데 각각의 메트릭들은 내부에서 마이크로미터 표준방식으로 측정되고 있으므로 어떤 구현체를 사용할지 지정만 해주면 됨

(2) build.gradle 추가

  • build.gradle에 마이크로미터 프로메테우스 구현 라이브러리를 추가하면 스프링 부트와 액츄에이터가 자동으로 마이크로미터 프로메테우스 구현체를 등록해서 동작하도록 설정해줌
  • 액츄에이터에 프로메테우스 메트릭 수집 엔드포인트도 자동으로 추가됨
    - /actuator/prometheus
  • 애플리케이션 실행 후 localhost:8080/actuator/prometheus에 들어가보면 메트릭이 프로메테우스 포멧으로 만들어져있는 것을 확인할 수 있음
implementation 'io.micrometer:micrometer-registry-prometheus' //추가

 

(3) 포멧 차이

  • jvm.info -> jvm_info: 프로메테우스는 .대신에 _포멧을 사용하여 전부 _포멧으로 변환된 것을 확인할 수 있음
  • logback.events -> logback_events_total: 로그수 처럼 지속해서 숫자가 증가하는 메트릭을 카운터라고하는데 프로메테우스는 카운터 메트릭의 마지막에는 관례상 _total을 붙임
  • http.server.requests: 해당 메트릭은 내부에 요청수, 시간 합, 최대 시간 정보를 가지고 있는데, 프로메테우스에서는 3가지로 분리됨
    - http_server_requests_seconds_count: 요청 수
    - http_server_requests_seconds_sum: 시간 합(요청수의 시간을 합한 것)
    - http_server_requests_seconds_max: 최대 시간(가장 오래걸린 요청 수)
  • 대략 이런식으로 포멧들이 변경된다고 보면됨

3) 프로메테우스 설정 - 수집 설정

(1) prometheus.yml 파일 수정

  • 프로메테우스가 애플리케이션의 /actuator/prometheus를 호출해서 메트릭을 주기적으로 수집하도록 설정
  • yml파일이므로 띄어쓰기 2칸에 유의
  • job_name: 수집하는 이름, 임의의 이름을 사용하면 됨
  • metrics_path: 수집할 경로를 지정
  • scrape_interval: 수집할 주기를 설정
  • targets: 수집할 서버의 IP,PORT를 지정
  • 이렇게 설정하면 프로메테우스는 아래의 경로를 1초에 한번씩 호출해서 애플리케이션의 메트릭들을 수집함
    - localhost:8080/actuator/prometheus
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.

alerting:
  alertmanagers:
    - static_configs:
        - targets:

rule_files:

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]
      
  #추가
  - job_name: "spring-actuator"
    metrics_path: '/actuator/prometheus'
    scrape_interval: 1s
    static_configs:
      - targets: ['localhost:8080']

 

** 참고

  • scrape_interval: 여기서는 예제를 빠르게 확인하기 위해서 1s로 했지만 수집 주기의 기본 값은 1m임
  • 시스템 상황에 따라 다르겠지만 일반적으로 수집 주기가 너무 짧으면 애플리케이션 성능에 영향을 줄 수 있으므로 운영에서는 10s ~ 1m 정도를 권장함

(2) 연동 확인

  • 설정을 완료하면 프로메테우스 서버를 종료 후 재실행 하고 아래의 설정과 타겟 URL로 들어가서 연동이 잘 되었는지 확인해보면 prometheus.yml에 추가했던 설정이 잘 연동 된 것을 확인할 수 있음
  • http://localhost:9090/config
  • http://localhost:9090/targets

(3) 프로메테우스 연동 확인 화면

  • prometheus: 프로메테우스 자체에서 제공하는 메트릭 정보(프로메테우스 자신의 메트릭을 확인하는 것)
  • spring-actuator: 방금 설정으로 연동한 애플리케이션의 메트릭 정보
  • State가 UP으로 되어있으면 정상, DOWN으로 되어있으면 연동이 안된 것임

(4) 프로메테우스를 통한 데이터 조회

  • 프로메테우스 메인 화면에서(Query 탭) 조회할 프로메테우스 포멧의 메트릭을 검색해보면 수집한 메트릭이 조회되는 것을 확인할 수 있음

6. 프로메테우스 - 기본 기능

1) 기본

(1) 태그, 레이블

  • 검색창에 http_server_requests_seconds_count를 입력하고 실행 후 뜬 검색결과의 { } 을 살펴보면 error, exception, instance, job, method, outcome, uri가 보이는데 각각의 메트릭 정보를 구분해서 사용하기 위한 태그들임
  • 마이크로미터에서는 이것을 태그(Tag)라 하고, 프로메테우스는 레이블(Label)이라고 함
  • 맨 끝을 보면 숫자가 보이는데, 이 숫자가 해당 메트릭의 값임

(2) 기본 기능

  • Table: Evaluation time을 수정해서 과거 시간의 메트릭를 조회할 수 있음
  • Graph: 메트릭을 그래프로 조회할 수 있음

2) 필터

(1) 레이블 일치 연산자

  • 레이블을 기준으로 필터를 사용할 수 있으며 중괄호 문법을 사용함
  • =: 제공된 문자열과 정확히 동일한 레이블 선택
  • !=: 제공된 문자열과 같지 않은 레이블 선택
  • =~: 제공된 문자열과 정규식이 일치하는 레이블 선택
  • !~: 제공된 문자열과 정규식이 일치하지 않는 레이블 선택

(2) 예시

  • url=log, method=GET 조건으로 필터: http_server_requests_seconds_count{uri="/log", method="GET"}
  • /actuator/prometheus는 제외한 조건으로 필터: http_server_requests_seconds_count{uri!="/actuator/prometheus"}
  • method가 GET, POST인 경우를 포함해서 필터: http_server_requests_seconds_count{method=~"GET|POST"}
  • /actuator로 시작하는 uri는 제외한 조건으로 필터: http_server_requests_seconds_count{uri!~"/actuator.*"}

4) 연산자 쿼리와 함수

(1) 연산자 지원

  • +: 덧셈
  • -: 뺄셈
  • *: 곱셈
  • /: 분할
  • %: 모듈로
  • ^: 승수/지수

(2) sum

  • 값의 합계를 구함
  • sum(http_server_requests_seconds_count)

(3) sum by

  • SQL의 group by와 유사한 기능
  • sum by(method, status)(http_server_requests_seconds_count)

(4) count

  • 메트릭 자체의 수 카운트
  • count(http_server_requests_seconds_count)

(5) topk

  • 상위 n개 메트릭 조회
  • topk(n, http_server_requests_seconds_count)

(6) 오프셋 수정자

  • 현재를 기준으로 특정 과거 시점의 데이터를 반환
  • http_server_requests_seconds_count offset 10m

(7) 범위 벡터 선택기

  • 마지막에 [1m], [60s]와 같이 표현하며 1분간의 모든 기록값을 선택
  • 범위 벡터 선택기는 차트에 바로 표현할 수 없고 데이터로는 확인할 수 있음
  • 범위 벡터 선택의 결과를 차트에 표현하기 위해서는 약간의 가공이 필요한데 뒤에서 설명하는 상대적인 증가 확인 방법을 참고하면 됨
  • http_server_requests_seconds_count[1m]

7. 프로메테우스 - 게이지와 카운터

1) 메트릭 분류

  • 메트릭은 크게 게이지와 카운터 2가지로 분류할 수 있음

(1) 게이지(Gauge)

  • 임의로 오르내릴 수 있는값
  • ex) CPU사용량, 메모리 사용량, 사용중인 커넥션 등
  • 게이지는 값이 올라갔다가 내렸갔다 하는 값으로 현재 상태를 그대로 출력하면됨
  • 대표적인 게이지인 CPU 사용량(system_cpu_usage)을 생각해보면 CPU 사용량의 현재 상태를 계속 측정하고 그 값을 그대로 그래프에 출력하면 과거부터 지금까지의 CPU 사용량을 확인할 수 있음
  • 게이지는 가장 단순하고 사용하기 쉬운 메트릭이므로 크게 고민없이 있는 그대로를 사용하면 됨

(2) 카운터(Counter)

  • 단순하게 증가하는 단일 누적 값으로 특정 이벤트가 발생할 때 마다 그 수를 계속 누적하는 값
  • ex) HTTP 요청 수, 로그 발생 수

2) 카운터의 그래프

(1) 계속 증가하는 그래프

  • http_server_requests_seconds_count{uri="/log"}로 HTTP 요청 메트릭을 표현한 후 /log를 계속 HTTP 요청을 보내보면 카운터가 계속 누적해서 증가하므로 계속 카운터값이 증가만 하는 그래프만 보게 될 것임
  • 이렇게 증가만 하는 그래프에서는 특정 시간에 얼마나 고객의 요청이 들어왔는지 한눈에 확인하기가 매우 어려움
  • 이런 문제를 해결하기 위해 increase(), rate()같은 함수를 지원함

(2) 시간 단위 요청 그래프 - increase()

  • increase(http_server_requests_seconds_count{uri="/log"}[1m])
  • increase()를 사용하면 지정한 시간 단위별로 증가를 확인할 수 있어서 이런 문제를 해결할 수 있음
  • 마지막에[시간]을 사용해서 범위 벡터를 선택해야함
  • 지금 예제처럼 1m을 적용하면 분당 얼마나 고객의 요청이 어느정도 증가했는지 한눈에 파악할 수 있음

(3) 시간 단위 요청 그래프 - rate()

  • rate(http_server_requests_seconds_count{uri="/log"}[1m])
  • 범위 벡터에서 초당 평균 증가율을 계산함
  • increase()와 그래프 모양은 동일하지만 y축의 값을 보면 increase()가 숫자를 직접 카운트 한다면, rate()는 여기에 초당 평균을 나누어서 계산함
  • rate(data[1m])이면 60초가 기준이되어 60을 나눈 수이며 rate(data[2m])이면 120을 나눈 수인데, 복잡하게 생각할 것 없이 초당 얼마나 증가하는지 나타내는 지표로 보면 됨

(4) 시간 단위 요청 그래프 - irate()

  • irate(http_server_requests_seconds_count{uri="/log"}[1m])
  • rate와 유사한데 범위 벡터에서 초당 순간 증가율을 계산함
  • 급격하게 증가한 내용을 확인하기 좋음

(5) 정리

  • 값이 계속 변하는 게이지는 현재 값을 그대로 그래프로 표현하면 됨
  • 카운터: 값이 단조롭게 증가하는 카운터는 increase(), rate()등을 사용하여 표현하여 특정 시간에 얼마나 고객의 요청이 들어왔는지 확인할 수 있음
  • 그러나 프로메테우스는 한눈에 들어오는 대시보드를 만들어보기 어렵다는 단점이 있는데 이부분은 그라파나를 사용하면됨

** 참고


8. 그라파나 - 설치 및 연동

1) 설치

(1) 다운로드

(2) 실행

  • Windows: 압축을 풀고 bin 폴더로 이동하여 grafana-server.exe 실행
  • Mac OS: 압축을 풀고 터미널로 해당 폴더의 bin폴더로 이동하여 ./grafana-server실행
  • 보안이 있다면 보안 해제 후 다시 실행해야하고 프로메테우스의 메트릭을 받아야하므로 프로메테우스도 켜져 있어야 함
  • 최초 접속하면 로그인 페이지로 뜨는데, admin / admin 입력 하면 계정을 만들라는 페이지가 또 뜨는데 skip을 누르면 그라파나 메인 페이지로 들어갈 수 있음
  • 물론 실제로 적용할 때는 계정을 만들어서 접속해야함

(3) 애플 실리콘 사용시

  • 애플 실리콘 맥에서는 위의 사이트에서 다운받으면 arm64지원이 없어서 Permission denied 혹은 bad CPU type in executable 오류가 발생할 수 있는데 rosetta2를 설치하여 해결할 수 있음
  • 만약 homebrew가 설치되어있다면 brew update, brew install grafana로 설치하면 애플 실리콘에서 실행 할 수 있는 그라파나로 설치가 됨
  • 실행은 brew services start grafana 로 실행 후 localhost:8080으로 접속하면 그라파나 페이지로 들어갈 수 있음
  • 종료는 brew services stop grafana으로 할 수 있고 restart명령어로 재실행도 할 수 있음

2) 연동

(1) 데이터 읽어오기

  • 그라파나에서 프로메테우스를 데이터소스로 사용하여 데이터를 읽어오기
  • 왼쪽 카테고리에서 Connections -> DataSource 로 진입 후 Add data source를 선택(그라파나 v11.3.1 버전)
  • 교안의 버전에서는 왼쪽 하단의 톱니바퀴(Configuration) -> Data sources -> add data source를 선택
  • Prometheus 선택 후 Connection 탭의 URL에 http://localhost:9090 (프로메테우스 서버)를 입력 후 save & test 클릭하면 연동이 됨

9. 그라파나 - 대시보드 만들기

1) 메트릭 대시보드 만들기

  • 애플리케이션, 프로메테우스, 그라파나 3가지를 모두 실행 후 진행해야 함

(1) 대시보드 저장

  • 1. 왼쪽 Dashboards 클릭
  • 2. 우측 상단 New -> New dashboard 클릭
  • 3. 오른쪽 상단의 Save dashboard 클릭
  • 4. Dashboard name을 원하는 이름으로 입력 후 저장

(1-2) 대시보드 확인

  • 다시 왼쪽 Dashboards 클릭
  • 앞서 만든 대시보드가 있는지 확인 후 클릭

2) 패널 만들기

(1) 대시보드에 패널 만들기

  • 대시보드가 큰 틀이라면 패널은 그 안에 모듈처럼 들어가는 실제 그래프를 보여주는 컴포넌트임
  • 1.  화면 중앙의 Add visualization클릭 후 맨 앞에 창을 x 클릭(그라파나 v11.3.1 버전)
  • 교안 버전에서는 오른쪽 상단의 Add panel 버튼(차트 모양) 클릭 후 Add a new panel 선택
  • 하단의 Run queries 버튼 오른쪽에 Builder, Code 버튼이 있는데 Code를 클릭
  • Metrics browser> Enter a PromQL query... 부분에 메트릭을 입력하면 됨

3) 메트릭 만들기

(1) CPU 메트릭

  • 아래의 메트릭을 패널에 추가하려면 메트릭을 입력 후 Run queries 버튼을 선택하면 패널에 시스템 CPU 사용량을 그래프로 확인할 수 있음
  • 두가지를 함께 입력하려면 Add query 버튼을 클릭하면 추가로 쿼리를 입력할 수 있는 칸이 나오는데 여기에 추가 쿼리를 입력 후 Run queries를 크릭하면 됨
  • system_cpu_usage: 시스템의 CPU 사용량
  • process_cpu_usage: JVM 프로세스 CPU 사용량

(2) 그래프의 데이터 이름 변경

  • 패널 그래프 하단에는 범례(Legend)라고 하는 차트에 제공하는 데이터 종류를 구분하는 테스트가 JSON으로 표시되어있는데 이부분을 보기 좋게 수정할 수 있음
  • 쿼리를 입력한 곳의 하단을 보면 Options가 있는데 이를 클릭 후 Legend 부분이 Auto로 되어있는것을 Custom으로 변경한 뒤 내용을 지우고 원하는 이름으로 변경할 수 있음

(3) 패널 이름 설정

  • 우측을 보면 Panel options가 있는데 Title을 수정하면 패널 이름을 설정할 수 있음

(4) 패널 저장

  • 상단의 Save dashboard (교안의 버전에서는 Apply)를 누르면 대시보드가 저장됨
  • 다시 Dashboards -> 내가만든 대시보드로 접속하면 대시보드에 추가된 패널을 확인할 수 있음

 

3) 디스크 사용량 메트릭 추가해보기

  • 위와 동일한 방법으로 디스크 사용량 추가
  • 우측 상단의 Add -> Visualization을 클릭하면 메트릭을 추가할 수 있음
  • 교안 버전은 기존과 동일함

(1) 패널 옵션

  • Title: 디스크 사용량

(2) PromQL

  • disk_total_bytes, Legend: 전체 용량
  • disk_total_bytes - disk_free_bytes, Legend: 사용 용량

(3) 그래프 데이터 사이즈 변경

  • 그래프를 보면 데이터 사이즈가 byte로 표시되는데 오른쪽 Option 창에서 변경할 수 있음
  • Standard options -> Unit -> Data -> bytes(SI) 선택하면 GB, TB 단위로 읽기 편하게 변함

(4) 최소값 변경

  • 그래프는 최적화가 되었지만 최소값이 임의의 값으로 표시가 되는데 이를 변경할 수 있음
  • Standard options -> Min -> 0을 입력하면 0부터 시작하는 그래프로 변경 된 것을 확인할 수 있음
  • 마찬가지로 Max도 조절할 수 있음

(5) 저장

  • Save dashboard 혹은 Apply을 클릭하여 대시보드를 저장하고 다시 나의 대시보드리스트로 돌아가면 메트릭이 추가되어있음
  • 해당 메트릭들을 선택하여 원하는 위치에 옮길 수도 있고 크기도 자유롭게 조정할 수 있음

 

(6) 정리

  • 위와 같은 방법으로 대시보드와 패널에 원하는 메트릭을 대시보드에 추가할 수 있었으며 JVM 메트릭, 시스템 메트릭, 애플리케이션 시작 메트릭, 스프링 MVC 메트릭, 톰캣 메트릭, 데이터소스 메트릭, 로그 메트릭, 기타 메트릭들을 추가해주면 됨
  • 그런데, 이렇게 하나하나 직접 대시보드를 입력하는 것은 생각보다 시간이 많이 소요되는데 그라파나는 이미 만들어둔 대시보드가 있어 이를 가져다가 사용할 수 있는 기능을 제공함

10. 그라파나 - 공유 대시보드 활용

1) 공유 대시보드 활용

(1) 사이트 접속

  • 사이트
  • 해당 사이트에 접속해보면 이미 누군가 만들어둔 수많은 대시보드가 공개되어있음
  • 예제로는 스프링 부트와 마이크로미터를 사용해서 만든 대시보드를 사용할 것이므로 검색창에 spring이라고 검색하면 JVM(Micrometer)와 Spring Boot 2.1 System Monitor를 확인할 수 있음
  • 이 두개가 2023년 3월 강의 기준으로는 가장 인기가 높다고 함

(2) 스프링 부트 시스템 모니터 대시보드 불러오기

  • https://grafana.com/grafana/dashboards/11378-justai-system-monitor/ 
  • 해당 사이트에 접속(검색 후 접속해도 됨)한 다음 Copy ID to clipboard를 선택하거나 ID:11378이라고 되어있는 부분을 복사 해도 됨
  • 1. 그라파나에 접속 후 왼쪽 Dashboards클릭
  • 2. 우측 New -> mport 클릭
  • 3. 복사한 값을 Grafana.com dashboard URL or ID라고 적혀있는 부분에 붙여넣기 후 Load를 클릭
  • 4. Prometheus탭에서 데이터 소스를 prometheus로 선택 후 Import를 클릭하면 대시보드가 불러와짐
  • 대시보드를 확인해보면 거의 대부분의 메트릭을 대시보드에 표현해 두었기 때문에 각각의 항목들을 보고 대시보드를 어떻게 구성해야 할지 학습할 수도 있음
  • 일부 데이터의 경우 스프링 부트나 기타 라이브러리의 버전이 변함에 따라서 동작하지 않는 기능들도 있는데 이런부분은 수정해서 사용하면 됨

(3) 불러온 대시보드 수정

  • 오른쪽 상단의 Make editable 클릭 후 원하는 메트릭에 마우스를 대면 우측 상단에 점3개가 뜨는데, 해당 버튼을 클릭 후 edit으로 들어가면 해당 메트릭을 수정할 수 있음 (교안 버전은 톱니바퀴 클릭 후 Make editable클릭 한 뒤에 대시보드를 저장해야 수정모드로 변경된다고 함)
  • 아무 메트릭이나 edit으로 들어가보면 해당 메트릭을 어떤 쿼리로 가져왔는지 확인할 수 있어 해당 내용을 보고 학습할 수 있음

2) Jetty 통계 -> Tomcat 통계

(1) 패널 타이틀 변경

  • 지금 불러온 스프링 부트 2.1 대시보드는 톰캣이 아니라 Jetty라는 웹 서버를 기준으로 통계를 수집하므로 이부분을 수정
  • Jetty Statistics로 이동한 뒤 톱니 바퀴를 눌르면 패널 타이틀을 변경할 수 있음
  • Title을 Tomcat Statistics로 변경

(2) Thread Conf Max 패널 설정 변경

  • Thread Config Min은 없으므로 패스
  • Thread Config Max패널의 edit으로 이동하여 메트릭을 변경
  • jetty_threads_config_max -> tomcat_threads_config_max_threads로 변경하면 톰캣 최대 쓰레드 수가 표시됨

(3) Thread 패널 설정 변경

  • jetty_threads_current -> tomcat_threads_current_threads 으로 변경
  • jetty_threads_busy -> tomcat_threads_busy_threads 으로 변경
  • jetty_threads_idle 제거
  • jetty_threads_jobs 제거
  • 이렇게 설정 하면 현재 톰캣 쓰레드가 활동하고 있는 것을 확인할 수 있으며 대시보드를 저장하면 됨

(4) 정리

  • 이미 잘 만들어진 대시보드를 활용하면 편리하게 모니터링 환경을 구성할 수 있음
  • 가져온 대시보드들을 분석해보면 필요한 데시보드를 만드는데 좋은 참고가 됨

** 참고

  • JVM(Micrometer) 대시보드도 매우 유용한 많은 정보를 제공하므로 추가해서 사용하는 것을 권장함

11. 그라파나 - 메트릭을 통한 문제 확인

  • 실무에서 주로 발생하는 대표적인 예시를 통해서 애플리케이션에 문제가 발생했을 때 그라파나를 통해 어떻게 모니터링 하는지 실습

1) CPU 사용량 초과

(1) TrafficController - cpu() 추가

  • 반복문을 통해 CPU에 간단히 부하를 주는 코드를 작성
  • 각자의 컴퓨터 성능에 따라서 루프 횟수를 설정
package hello.controller;

@Slf4j
@RestController
public class TrafficController {

    @GetMapping("/cpu")
    public String cpu() {
        log.info("cpu");
        long value = 0;
        // 간단한 부하 테스트는 반복문으로 작성
        for (long i = 0; i < 1000000000000L; i++) {
            value++;
        }
        return "ok value=" + value;
    }
}

 

(2) 실행

  • localhost:8080/cpu 에 접속하여 실행 후 그라파나 대시보드를 통해 확인해보면 CPU 사용량이 증가하는 것을 확인할 수 있음
  • 요청 하나당 코어 하나를 100% 사용할 것이므로 여러 웹브라우저를 띄우거나 포스트맨으로 동시에 요청하면 더 많은 CPU가 사용되는 것을 볼 수 있음

2) JVM 메모리 사용량 초과

(1) TrafficController - jvm() 추가

  • 메모리 사용을 누적하는 코드를 추가
  • 리스트에 문자를 계속해서 추가
private List<String> list = new ArrayList<>();

@GetMapping("/jvm")
public String jvm() {
    log.info("jvm");
    // CPU 사용량을 늘리려면 Loop 를 사용하는 것이 좋음
    for (long i = 0; i < 1000000000L; i++) {
        list.add("hello jvm!" + i);
    }
    return "ok";
}

 

(2) 실행

  • localhost:8080/jvm으로 여러변 요청 후 JVM 마이크로미터 대시보드로 JVM 메모리 사용량을 확인해보면 어느 순간 JVM 메모리 사용량이 계속 증가하다가 최대치를 넘는 순간 메트릭이 잡히지 않는데 JVM 내부에서 OOM이 발생했기 때문임
  • 애플리케이션 로그를 확인해보면 java.lang.OutOfMemoryError: Java heap space 가 출력되어 있는 것을 확인할 수 있음 

3) 커넥션 풀 고갈

(1) TrafficController - jdbc() 추가

  • 데이터 소스를 주입 받고 커넥션을 얻은 후 conn.close()를 하지 않고 그냥 retrun을 하여 데드 커넥션이 되도록 설정
  • 계속 커넥션이 쌓이게 됨
@Autowired DataSource dataSource;

@GetMapping("/jdbc")
public String jdbc() throws SQLException {
    log.info("jdbc");
    Connection conn = dataSource.getConnection();
    log.info("connection info={}", conn);
    // conn.close() // 원래는 커넥션을 닫아야 하는데 커넥션을 닫지 않고 종료 -> 커넥션이 쌓임
    return "ok";
}

 

(2) 실행

  • localhost:8080/jdbc로 여러번 요청 후 스프링 부트 2.1 대시보드의 HikariCP Statistics의 Connections를 확인해보면 사용되는 커넥션 수가 증가되는 것을 확인할 수 있음
  • Active 커넥션이 커넥션 풀의 최대 숫자인 10개를 넘어가게 되면 커넥션을 획득하기 위해 대기(Pending)하게 되며 커넥션 획득 부분에서 쓰레드가 대기하게 되고 결과적으로 HTTP 요청을 응답하지 못함
  • 대시 보드에 보면 Pending부분이 활성화 되었다가 다시 사라지는데, DB 커넥션을 획득하기 위해 대기했던 톰캣 쓰레드가 30초 이상 DB 커넥션을 획득하지 못하면 java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30005ms 예외가 발생하면서 커넥션 획득을 포기하게 되고 웹페이지도 에러페이지로 뜸
  • 그리고 대시보드의 Connection Timeout Count의 수가 증가되는 것을 확인할 수 있음

** 참고

  • 요즘은 JDBC 템플릿, JPA 이런곳에서 알아서 닫아주기 때문에 커넥션을 닫지 않는 문제가 발생하지는 않고 쿼리를 날렸는데 그 쿼리가 응답하는데 DB에서 너무 오래걸려서 계속 커넥션이 늘어나는 문제가 생기는 경우가 있음
  • 그럴 때는 롱 쿼리를 확인해보거나 락이 걸린 부분을 확인해보거나 하면서 문제의 범위를 좁힐 수 있음

4) 에러 로그 급증

(1) TrafficController - errorLog() 추가

  • 애플리케이션에서 ERROR 레벨의 로그가 급증한다면 심각한 문제가 발생한 것으로 이해할 수 있음
@GetMapping("/error-log")
public String errorLog() {
    log.error("error log");
    return "error";
}

 

(2) 실행

  • localhost:8080/error-log를 여러번 실행해보면 스프링 부트 2.1 대시보드의 Logback Statistics 패널에서 ERROR logs가 급증하는 것을 확인할 수 있음

(3) 정리

  • 이런 모니터링 툴 덕분에 애플리케이션 상황을 한눈에 확인할 수 있게 되어 장애가 발생했을 때 문제를 빠르게 파악하고 대응할 수 있음

** 참고

  • 메트릭을 보는 것은 정확한 값을 보는 것이 목적이 아니라 대략적인 값과 추세를 확인하는 것이 주 목적임