Armeria & Spring Boot에서 Prometheus 지표 수집하기

Spring 연동하고 Prometheus 지표 수집까지

이전 글인 Armeria와 Spring Boot 연동하기를 통해 기존 Spring Boot에 Armeria를 쉽게 도입하는 방법에 대해 알아보았습니다. Armeria와 Spring Boot를 연동할 때 적용할 수 있는 것들이 꽤 많은데요. 그 중 하나가 지표 수집입니다. Armeria는 간단한 코드를 추가하여 Prometheus 지표를 수집할 수 있는데 Spring Boot와 함께 사용하는 경우 Armeria를 단독으로 사용할 때와 다른 설정을 사용해야 합니다. 이 글에서는 직접 Spring Boot와 연동한 Armeria에서 지표를 수집하는 코드를 작성했던 과정과 주의해야 할 점들에 대해 이야기해보겠습니다.

Armeria만 쓸 때는 어떻게 하는가

먼저 라인 기술 블로그를 보면 Armeria에서 Prometheus 지표를 사용하는 방법을 자세히 소개합니다. 그 과정을 코드 한 블록으로 간단하게 요약했습니다.

먼저 기본 설정값으로 PrometheusMeterRegistry 인스턴스를 만듭니다. 그 다음 ServerBuilder#meterRegistry() 메소드를 통해 서버 빌더에 MeterRegistry 인스턴스를 주입합니다. 그리고 MetricCollectingService를 데코레이터로 추가합니다. 이 때 MeterIdPrefixFunction을 사용하는데 위 코드에서는 Armeria에서 수집하는 지표의 prefix에 my.metric을 붙입니다. (실제로는 my_metric_이 붙습니다.) 마지막으로 Armeria가 제공하는 PrometheusExpositionService를 사용해 메트릭 정보를 조회할 수 있는 엔드포인트를 생성합니다. 이 간단한 설정을 통해 Armeria에서 Prometheus 지표를 수집할 수 있습니다.

Spring에서 사용하기

그럼 Spring과 Armeria를 함께 사용할 때는 어떻게 Prometheus와 연결할까요? 우선 이전 글인 Armeria와 Spring 연동하기가 완료되었다고 해봅시다. 연동을 위해 ArmeriaServerConfigurator 빈을 만들었던 것과 마찬가지로 빈 설정을 통해 MeterRegistry, MetricCollectingServiceConfigurator, MeterIdPrefixFunction을 주입할 수 있습니다. 참고로 추가적인 빈 설정은 AbstractArmeriaAutoConfiguration#armeriaServer()에서 보실 수 있습니다.

그럼 하나씩 빈을 만들어보겠습니다. 먼저 MeterRegistry 인스턴스로 사용할 PrometheusMeterRegistry 빈을 만들어줍니다.

다음으로 MetricCollectingServiceConfigurator 빈을 만들어줍니다. 그런데 위 Armeria-Prometheus 예시를 보면 MetricCollectingService를 사용하였지만 MetricCollectingServiceConfigurator는 처음 보실 텐데요. 해당 코드를 열어보면 그 역할을 쉽게 알 수 있습니다.

코드를 보면 @FunctionalInterface 어노테이션을 통해 단순한 함수임을 알 수 있습니다. 이는 MetricServiceCollectingServiceBuilder를 받아 void 리턴하므로 빌더에 추가적인 설정을 주입해주는 함수임을 쉽게 알 수 있습니다. 또한 getOrder() 메소드를 오버라이드하여 Configurator간의 우선순위도 설정할 수 있음을 알 수 있네요.

그럼 그 정체를 알았으니 실제 빈을 만들겠습니다. 우선 위 Armeria-Prometheus 예시에서는 MetricCollectingService에 추가적인 설정없이 기본값으로 사용하였습니다. 따라서 우리가 빈을 만들지 않고 기본 설정으로 사용할 수 있지만 여기서는 어떻게 사용하는지 보기 위해 404 status code도 응답 성공 기준에 포함시키도록 successFunction()을 사용합니다.

MeterIdPrefixFunction 빈 역시 쉽게 만들 수 있습니다.

모든 빈 설정이 끝났으니 마지막으로 해당 지표를 조회할 수 있는 엔드포인트를 만들어야 합니다. 이 부분도 Armeria에서 쉽게 사용할 수 있도록 application.yml (또는 application.properties) 설정을 통해 엔드포인트를 사용할 수 있습니다. 추가적인 설정은 ArmeriaSettings에서 보실 수 있습니다.

Armeria는 Spring과 함께 사용할 수 있는 docs, metrics, health, actuator 네 가지 내부 서비스들을 제공합니다. 따라서 armeria.internal-services.includemetrics 서비스를 추가합니다. 이 때 armeria.internal-services.port 값을 설정해주지 않으면 사용 가능한 랜덤 포트를 할당합니다. 다음으로 armeria.enable-metrics, armeria.metric-path 설정을 변경할 수 있습니다. 기본값이 모두 설정되어 있기 때문에 따로 변경하지 않아도 무방합니다.

이제 모든 준비가 끝났습니다. 애플리케이션을 재시작한 뒤 /internal/metrics에 접속하면 Prometheus 지표를 조회할 수 있습니다. 다음으로 /internal/metrics 엔드포인트를 Prometheus 서비스와 연결하여 사용하시면 됩니다. (이후 연결 내용은 라인 기술 블로그에 자세히 나와있습니다.)

주의할 점

추가적인 팁으로 Spring Boot Actuator를 함께 사용하는 경우 주의할 점이 있습니다. Actuator 역시 설정을 통해 Prometheus 지표를 /actuator/prometheus 엔드포인트로 조회할 수 있습니다. 만약 레거시 Spring Boot가 이미 해당 기능을 사용하고 있다면 위의 코드에서 PrometheusMeterRegistry 빈을 만들면 안됩니다. Actuator가 자동으로 해당 빈을 생성하기 때문에 명시적으로 생성한 빈을 지우지 않으면 지표 수집이 되지 않습니다.

또한 Actuator를 함께 사용하는 경우 /actuator/prometheus, /internal/metrics 두 개의 엔드포인트에서 모두 지표를 수집할 수 있는데요. 만약 둘 중의 하나만 사용하고 싶다면 application.yml 설정에서 armeria.metric-path=""로 설정하면 됩니다. 반대로 Actuator의 엔드포인트를 닫는 것도 괜찮습니다.

다음 주의할 점은 지표 설정 관련 빈을 만들지 않고 ArmeriaServerConfigurator 빈으로 모든 것을 설정하면 안됩니다. 예를 들어 지표 설정에 대해 잘 모른다면 다음과 같은 코드를 만들 수 있습니다.

Armeria를 단독으로 사용할 때 코드와 유사하게 ArmeriaServerConfigurator 빈의 서버 빌더 설정이 괜찮아보이지만 실제 Armeria 내부 연동 과정 코드를 살펴보면 몇 가지 설정들이 기본값으로 덮어써질 수 있습니다. 다음은 우리가 주입하는 Armeria 설정 빈을 주입받는 빈의 코드입니다.

코드 주석에 표시했듯이 MeterRegistry, MeterIdPrefixFunction 빈 같은 경우 빈 주입으로 사용하지 않으면 기본값으로 덮어써질 위험이 있습니다. 따라서 반드시 직접 ServerBuilder를 사용하는 대신 빈을 사용하여야 합니다. 참고로 해당 주의사항은 시간이 지나면 Armeria의 코드가 변경될 수 있기 때문에 직접 사용하기 전에 확인해보시기 바랍니다.

Armeria를 연동하고 공유하자

지구에서 자바로 서버 개발을 하고 있다면 십중팔구 Spring 프레임워크를 사용하고 있을 겁니다. Spring은 편리하고 강력하지만 Armeria를 함께 사용하면 더 쉽게 해결할 수 있는 요구사항들이 있습니다. 예를 들어 gRPC, Thrift 서비스를 같은 port를 사용하는 엔드포인트에 추가할 수 있고 이벤트 루프를 사용하는 멀티플렉싱 서버이기 때문에 트래픽 부하를 줄일 수 있습니다. (이전 글인 Armeria Spring 연동하기에서 보실 수 있습니다.)

그리고 Armeria는 단순한 연동 외에 추가적인 내부 서비스로 지표 수집, 문서화, 헬스체크, Actuator 연동(metrics, docs, health, actuator)을 제공합니다. 지표 수집의 경우 Dropwizard를 사용하는 것도 가능합니다. 이 글에서는 Prometheus 지표 수집 서비스를 빈 설정을 통해 사용하는 방법에 대해 알아보았습니다.

아직 Armeria에는 해당 과정이 문서화 되어있지 않아 직접 코드를 읽고 테스트하면서 시스템을 구축했습니다.(현재 제가 문서화 진행 중입니다.) 그 과정에서 더 자세한 내부 동작을 탐구하게 되어 얻은 지식도 많았습니다. 저는 Armeria를 알게 된 시간이 길지 않지만 장점이 많고 계속해서 발전할 수 있다고 생각합니다. 만약 이 글을 읽고 Armeria에 관심이 생겼다면 직접 시도해보고 그 지식을 공유해주세요. Armeria와 개발자들에게 많은 도움이 되리라 생각합니다!

comments powered by Disqus

Related