Prometheus로 Armeria 메트릭 모니터링하기

macOS Catalina 환경에서 실습하였습니다.

Spring Boot, Armeria 설정

Armeria 로 띄운 서버의 메트릭을 Spring Actuator 로 노출하여 Prometheus 서버에서 수집을 할 수 있게 하기 위해, 아래의 dependency들이 build.gradle에 정의되어야 한다.

dependencies {

    // Armeria
    implementation "com.linecorp.armeria:armeria:1.2.0" // Core
    implementation "com.linecorp.armeria:armeria-spring-boot2-autoconfigure:1.2.0" // For Spring Boot 2 integration

    // Micrometer
    implementation "io.micrometer:micrometer-core" // Core
    implementation "io.micrometer:micrometer-registry-prometheus" // For Prometheus

    // Spring Boot
    implementation 'org.springframework.boot:spring-boot-starter-actuator' // Actuator
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // ...
}

application.yml에 Acuator과 Armeria 관련 설정들을 추가하였다. Actuator는 8082 포트, Armeria 서버는 8083 포트를 사용하도록 설정하였다.
Prometheus 메트릭들을 Actuator로 노출시키기 위해, management.endpoints.web.exposureprometheus가 포함되어 있는 점을 주목하자.

management:  
  server:
    port: 8082
  endpoints:
    web:
      exposure:
        include: health, info, prometheus

armeria:  
  ports:
    - port: 8083
      protocol: HTTP

간단한 모니터링 테스트를 위해 /hello로 GET 요청을 하면 임의의 확률로 성공 또는 실패를 응답하는 REST API를 하나 준비하였다.

@Named
@NoArgsConstructor
public class MyAnnotatedService {

    private static Random RAND = new Random();

    @Get("/hello")
    public HttpResponse hello() {
        int rand = RAND.nextInt(2);
        if (rand % 2 == 0) {
            return HttpResponse.of("world");
        }
        return HttpResponse.ofFailure(new RuntimeException("error"));
    }
}
@Configuration
public class ArmeriaServerConfiguration {

    @Bean
    public ArmeriaServerConfigurator serverConfigurator(MyAnnotatedService myService) {
        return server -> server.annotatedService("/", myService);
    }
}

Application을 실행한 후에, 브라우저를 띄워보자.
http://localhost:8082/actuator/prometheus 에 접속했을때,

위의 그림에서처럼 Prometheus 메트릭들이 잘 보이는지 확인해보자.

다음으로 http://localhost:8083/hello 에 접속했을때, 응답이 성공 또는 실패로 잘 오는지 확인해보자.

모두 잘 동작한다면, 의도한대로 잘 설정된 것이다.


Prometheus 설정

Homebrew 패키지 매니저로 Prometheus를 설치한다.

$ brew install prometheus

Homebrew로 설치하면 기본적으로 prometheus.yml 파일은 /usr/local/etc/ 아래에 위치하게 된다.
이 YAML파일을 이용해 Prometheus의 설정들을 변경할 수 있다. 설정한 후에는 다시 Prometheus 서비스를 재시작해야한다.

global:  
  scrape_interval: 10s

scrape_configs:  
  - job_name: "armeria-prometheus"
    metrics_path: '/actuator/prometheus'
    static_configs:
    - targets: ["localhost:8082"]

여기서 위에서 확인했던, Spring Boot Actuator로 Prometheus 메트릭들을 수집할 수 있었던 path(/actuator/prometheus)와 port(8082)를 정확하게 설정하여야 한다.

$ brew services start prometheus

Prometheus가 사용하는 default 포트는 9090이므로, 브라우저에서 http://localhost:9090 으로 접속하면 아래 화면을 볼 수 있다.

Select box를 눌렀을 때, Armeria 관련 메트릭들이 잘 보인다면, 잘 설정된 것이다.

http://localhost:8083/hello 를 몇번 요청하여, armeria_server_requests_total 메트릭이 잘 올라가는지 그래프에서 확인해보자.


Grafana 설정

마찬가지로 Grafana 도 Homebrew로 설치한 후 서비스를 시작한다.

$ brew install grafana
$ brew services start grafana

Grafana의 기본 포트는 3000이므로, 브라우저에서 http://localhost:3000으로 접속하면 아래 로그인 페이지를 만나게된다.

계정을 만든 적이 없는데..? 라고 당황하지 말고 침착하게 admin을 username, password에 입력하면 로그인된다. 이는 단순 기본 계정이므로 실제 서비스에서 사용할 때는 보안을 위해 반드시 새로운 계정을 하나 만들도록 하자.

Grafana에서 Prometheus 메트릭들을 그래프로 그릴 수 있도록, 앞에서 설정한 Prometheus 경로를 Data Source로 등록해야 한다.

자 이제 Dashboard를 하나 생성한 후, /hello API의 성공/실패 횟수를 모니터링할 수 있는 Panel를 하나 생성해보자.

  • success
increase(armeria_server_requests_total{hostname_pattern="*", method="hello", http_status="200", result="success", service="com.example.armeria_prometheus.MyAnnotatedService"}[1m])  
  • failure
increase(armeria_server_requests_total{hostname_pattern="*", method="hello", http_status="500", result="failure", service="com.example.armeria_prometheus.MyAnnotatedService"}[1m])  

여기서 armeria_server_requests_total metric은 Counter 라는 metric type으로 단순히 누적되서 계속 증가하는 값이다. 실제 API 모니터링에서는 이 API가 현재까지 얼마나 많은 성공/실패가 있었나보다는, 시간별 성공/실패의 횟수가 더 의미있을 것이다. 이를 위해 increase() 함수를 사용해서 매 1분동안의 성공/실패 횟수를 그래프로 나타내었다.

하지만 실제 그래프에 찍힌 수치를 보면 소수점 값이다. 1씩 증가하는 횟수인데, 어떻게 소수점이 나올 수 있을까?
이 이유는 이 글 에 자세히 정리되어 있다.

(위의 블로그에는 아래와 같은 문구도 있다.)

Don't expect exact values from Prometheus. It's not designed to give you the exact number of anything, but rather an overview of what's happening.


모니터링

이제 loadtest 라이브러리를 이용하여 임의로 많은 요청을 보내보자.

$ loadtest http://127.0.0.1:8083/hello --rps 1

/hello API의 성공/실패 횟수가 Grafana에 그래프로 이쁘게 나옴을 볼 수 있다.


참고