티스토리 뷰

애플리케이션 메트릭

분산 시스템은 서로 상호작용하는 수많은 마이크로 서비스로 구성됩니다. 시스템 복잡도가 높아질 수록 시스템을 관찰하는 역량의 중요성이 더욱 커집니다. 애플리케이션 메트릭 관련 포스팅에서는 분산 시스템의 성능을 측정하고 사전에 위험을 알리는 방법에 대해 다룹니다.

모든 조직은 반드시 모니터링 솔루션을 하나 이 상 선정해야 하는데 규모나 복잡도에 구애받지 않고 조직에 맞는 솔루션을 찾을 수 있을 정도로 시장은 충분히 성숙해졌습니다.

블랙박스 vs 화이트박스 모니터링

메트릭 수집 방식은 관찰 가능한 요소가 무엇인지에 따라 두 가지로 분류합니다.

블랙박스

  • 수집기가 입출력을 관찰할 수 있으나 내부 메커니즘은 알 수 없음
    • ex) HTTP 요청/응답
  • 프로세스를 가로채거나 감싸는 방식으로 대상을 측정

화이트 박스

  • 수집기가 입출력 관찰 뿐만 아니라 내부 작동 메커니즘 관찰 가능
  • 애플리케이션 코드 내부에서 작동

많은 솔루션이 에이전트 형태로 블랙박스 모니터링 시스템을 제공합니다. 에이전트는 애플리케이션 프로세스와 같이 동작하며 상태를 관찰하는데, 스프링 부트처럼 많이 사용되는 프레임워크의 프로세스는 상당히 깊은 수준까지 관찰할 수 있어서 화이트박스 수집기처럼 보이기도 합니다.
블랙박스 모니터링은 에이전트가 일반화시킨 정보만 얻을 수 있는데 이는 전적으로 에이전트에 종속적입니다. 예를 들어, 스프링부트의 데이터베이스 트랜잭션 메커니즘을 가로채 작동 시간을 측정할 수 있으나 특정 클래스 내부에서 Map이 수행하는 캐싱 기능을 측정할 순 없습니다.

서비스 메시를 이용한 측정은 내부 로직을 알지 못하고 외부에서 네트워크 요청만 들여다보는 블랙박스 방식입니다.
이런 방식은 애플리케이션 내부까지 들어가서 함수 호출 하나하나를 추적할 수 있는 에이전트 방식보다 정밀도나 활용성이 떨어질 수 있습니다.
서비스 메시로 볼 수 있는 최대 수준은 "A 서비스가 B 서비스에게 요청을 보냈다"는 RPC 수준의 정보 정도입니다.

화이트박스 방식은 뭔가 복잡하고 손이 많이 갈 것처럼 느껴지지만, 사실 HTTP 요청 시간, CPU 사용률 같은 기본적인 지표들은 블랙박스로도 충분히 잘 수집됩니다.
게다가 요즘의 화이트박스 측정 도구들은 내부 설정을 자동화해주기 때문에, 오히려 블랙박스처럼 간편하게 사용할 수 있고, 개발자가 직접 들여야 하는 노력의 차이도 거의 없습니다.

화이트박스 방식은 블랙박스보다 더 많은 정보, 특히 내부의 세부 정보까지 수집할 수 있어 정밀한 모니터링이 가능합니다.
작업량 측면에서는 큰 차이가 없는데, 블랙박스는 에이전트 설정이나 전달 방식 수정 같은 작업이 필요하고, 화이트박스는 자동 설정 기능을 쓰면 비슷한 수준으로 수집을 자동화할 수 있습니다.
다만 화이트박스 방식은 수집 기능을 애플리케이션에 미리 넣어야 해서, 빌드 시점에 코드에 포함시키는 작업이 필요합니다.

일부 화이트박스 측정 방식은 블랙박스처럼 동작하지만, 특정 모니터링 시스템에 맞춘 전용 라이브러리는 이런 방식을 잘 사용하지 않습니다.
왜냐하면 특정 프레임워크나 클라이언트에 종속되지 않도록 설계되기 때문입니다.
또한, 같은 코드를 여러 측정 라이브러리가 중복해서 측정하는 것도 피하고 싶어합니다.
그래서 마이크로미터처럼 하나의 측정 포인트를 작성하면 여러 곳에 쓸 수 있는 방식이 프레임워크나 라이브러리를 만드는 개발자 입장에서 훨씬 실용적입니다.

두 방식은 서로 기능이 겹치는 경우에도 보완적 관계를 형성할 수 있어 어느 한 가지만 사용을 제한할 필요는 없습니다.

차원형 메트릭

최신 모니터링 시스템은 대부분 하나의 메트릭명에 여러 키-값 태그로 구성된 차원형 명명 스키마를 채택합니다.

모니터링 시스템마다 저장 방식은 다르지만, 일반적으로 메트릭 이름과 태그(tag)의 조합 별로 데이터를 별도로 저장합니다.
따라서 저장 비용은 모든 태그 조합의 개수에 비례하게 됩니다.
예를 들어, http.server.requests 메트릭이 다음과 같은 태그를 가진다고 가정해보겠습니다.

  • method: GET, POST (2종류)
  • status: 200, 400, 500 (3종류)
  • uri: /a, /b (2종류)

이 경우, 이 메트릭의 최대 고유 시계열 개수는

2 × 3 × 2 = 12

가 됩니다. 즉, 12개의 서로 다른 태그 조합에 대해 각각 데이터가 저장되고 전송됩니다.

하지만, 만약 /a는 GET 방식만, /b는 POST 방식만 사용하는 경우라면, 가능한 조합 수는

1 × 3 × 2 = 6

로 줄어듭니다.

각 고유한 메트릭명 + 태그 조합 하나하나가 독립된 시계열(series)로 관리됩니다.
각 시계열은 일정 기간 동안 데이터를 원형 버퍼(circular buffer) 형태로 저장합니다.
따라서, 메트릭이 소모하는 총 저장 비용은 다음과 같이 표현할 수 있습니다.

총 비용 = 고유 메트릭명 / 태그 조합 수 × 원형 버퍼 크기

계층형 메트릭

차원형 메트릭이 대중화되기 전에 주로 사용되었던 계층형 메트릭은 키-값 태그 없이 이름으로만 메트릭을 정의하는 구조입니다. 메트릭명과 태그를 결합하면 간단하게 계층형 이름으로 변환할 수 있습니다.
HTTP method가 GET인 차원형 메트릭 httpServerRequests는 계층형 메트릭으로는 httpServerRequests.method.GET이 됩니다. 와일드 카드를 이용해 httpServerRequests.method.*로 모든 메트릭을 조회할 수 있습니다.
하지만 계층형 모니터링 시스템에서는 태그를 동적으로 해석하거나 변환하는 기능이 부족합니다.
특히 와일드카드(*)를 포함한 쿼리는 매우 제한적으로 동작하며, 예측 불가능한 결과를 낳을 수 있습니다.

메트릭 쿼리
httpServerRequests.method.GET 10
httpServerRequests.method.POST 20
httpServerRequests.status.200.method.GET 10
httpServerRequests.method.* 30 (!!)

위 예시는 httpServerRequests.method.* 와일드카드로 모든 method 값을 집계하려 하지만, status 태그가 추가된 시계열은 제외되어 총합이 실제보다 낮게 나올 수 있음을 보여줍니다.
따라서 계층형 메트릭 시스템은 독립적인 키-값 태그들을 메트릭명 안에서 인위적으로 정렬해야한다는 번거로움이 있습니다.

그러므로 초기부터 차원형 시스템을 선택하고, 태그 기반 메트릭 기록 방식을 최대한 활용하는 것이 best practice라고 할 수 있습니다.

앞으로 포스팅 되는 내용은 차원형 메트릭 측정을 중심적으로 다룰 예정입니다.

댓글