Prometheus 的四種指標類型,我終於搞懂了

指標是用來衡量性能、消耗、效率和許多其他軟件屬性隨時間的變化趨勢。它們允許工程師通過警報和儀表盤來監控一系列測量值的演變(如 CPU 或內存使用量、請求持續時間、延遲等)。指標在 IT 監控領域有着悠久的歷史,並被工程師廣泛使用,與日誌和鏈路追蹤一起被用來檢測系統是否有不符合預期的表現。

在其最基本的形式中,一個指標數據點是由以下三個部分構成:

在過去的十年裏,隨着系統變得越來越複雜,出現了維度度量的概念,也就是說,度量還包括一組標籤或標識(即維度),以提供額外的上下文。支持維度指標的監控系統允許工程師通過查詢特定的指標名稱,並通過標籤進行過濾和分組,從而輕易地在多個組件和維度上彙總和分析一個指標。

對於由許多組件組成的現代動態系統,雲原生基金會(CNCF)中的項目 Prometheus 已經成爲最受歡迎的開源監控軟件,並有效地成爲指標監控的行業標準。Prometheus 定義了一個度量說明格式和一個遠程寫入協議,社區和許多供應商都採用這個協議來說明和收集度量成爲事實上的標準。OpenMetrics 是另一個 CNCF 項目,它建立在 Prometheus 導出格式的基礎上,爲收集度量標準提供了一個與廠商無關的標準化模型,旨在成爲互聯網工程任務組(IEFT)的一部分。

最近,另一個 CNCF 項目 OpenTelemetry 出現了,它的目標是提供一個新的標準,能夠統一指標、鏈路跟蹤和日誌的收集,使跨領域的遙測信號收集和關聯更容易。

由於有幾個不同的選擇,你可能想知道哪個標準最適合你。爲了幫助你回答這個問題,我們準備了一個由三部分組成的 Blog 系列,其中我們將深入研究由 CNCF 主持的指標標準。

在第一篇博文中,我們將介紹 Prometheus 指標標準;在下一篇博文中,我們將回顧 OpenTelemetry 指標標準;在最後一篇博文中,我們將直接比較這兩種格式,爲更好的互操作性提供一些建議。

我們希望你在讀完這些文章後,你能理解每個標準之間的差異,這樣你就能決定哪一個能更好地滿足你當前(和未來)的需求。

Prometheus 指標

首先要做的事。Prometheus 收集的指標有四種,作爲其暴露格式的一部分。

Prometheus 使用拉取模型來收集這些指標;也就是說,Prometheus 主動抓取暴露指標的 HTTP 端點。這些端點可以是由被監控的組件自然暴露,也可以通過社區建立的數百個 Prometheus 導出器之一暴露出來。Prometheus 提供了不同編程語言的客戶端庫,你可以用它來監控你的代碼。

由於服務發現機制和集羣內的共享網絡訪問,拉取模型在監控 Kubernetes 集羣時效果很好,但用 Prometheus 監控動態的虛擬機集羣、AWS Fargate 容器或 Lambda 函數就比較困難了。

爲什麼呢?主要原因是交易確定要抓取的指標端點,而且對這些端點的訪問可能受到網絡安全策略的限制。爲了解決其中的一些問題,社區在 2021 年底發佈了 Prometheus Agent Mode,它只收集指標並使用遠程寫入協議將其發送到監控後端。

Prometheus 可以抓取 Prometheus 暴露格式和 OpenMetrics 格式的指標。在這兩種情況下,指標通過 HTTP 接口暴露,使用簡單的基於文本的格式(更常用和廣泛支持)或更有效和強大的 Protobuf 格式。文本格式的一大優勢是它的可讀性,這意味着你可以在瀏覽器中打開它或使用像 curl 這樣的工具來檢索當前暴露的指標集。

Prometheus 使用一個非常簡單的指標模型,有四種指標類型,只在客戶端 SDK 中支持。所有的指標類型都是用一種數據類型或由多個單一數據類型的組合在暴露格式中表示。這個數據類型包括一個指標名稱、一組標籤和一個浮點數。時間戳是由監控後端(例如 Prometheus)或代理在抓取指標時添加的。

指標名稱和標籤集的每個唯一組合定義了一條時間序列,而每個時間戳和浮點數定義了一個系列中的樣本(即一個數據點)。

一些慣例被用來表示不同的度量類型。

Prometheus 暴露格式的一個非常有用的特點是能夠將元數據與度量相關聯,以定義其類型並提供描述。例如,Prometheus 提供了這些信息,Grafana 利用這些信息向用戶顯示額外的上下文信息,幫助他們選擇正確的度量並應用正確的 PromQL 函數。

Grafana 中的指標瀏覽器顯示 Prometheus 指標的列表,並顯示有關這些指標的額外背景。

以下是一個通過 Prometheus 暴露格式暴露的指標的案例。

# HELP http_requests_total Total number of http api requests
# TYPE http_requests_total counter
http_requests_total{api="add_product"} 4633433

HELP 用來爲指標提供描述,# TYPE 爲指標提供類型。

現在,讓我們來更詳細地介紹一下每個 Prometheus 指標類型。

計數器(Counter)

Counter 類型指標被用於單調增加的測量結果。因此它們總是累積的數值,值只能上升。唯一的例外是 Counter 重啓,在這種情況下,它的值會被重置爲零。

Counter 的實際值通常本身並不十分有用。一個計數器的值經常被用來計算兩個時間戳之間的 delta 或者隨時間變化的速率。

例如,Counter 的一個典型用例是記錄 API 調用次數,這是一個總是會增加的測量值。

# HELP http_requests_total Total number of http api requests
# TYPE http_requests_total counter
http_requests_total{api="add_product"} 4633433

指標名稱是 http_requests_total,它有一個名爲 api 的標籤,值爲 add_product,Counter 的值爲 4633433。這意味着自從上次服務啓動或 Counter 重置以來,add_product 的 API 已經被調用了 4633433 次。按照慣例,Counter 類型的指標通常以_total 爲後綴。

這個絕對數字並沒有給我們提供多少信息,但當與 PromQL 的 rate 函數(或其他監控後端的類似函數)一起使用時,它可以幫助我們瞭解該 API 每秒收到的請求數。下面的 PromQL 查詢計算了過去 5 分鐘內每秒的平均請求數。

rate(http_requests_total{api="add_product"}[5m])

爲了計算一段時期內的絕對變化,我們將使用 delta 函數,在 PromQL 中稱爲 increate():

increase(http_requests_total{api="add_product"}[5m])

這將返回過去 5 分鐘內的總請求數,這相當於用每秒的速率乘以間隔時間的秒數(在我們的例子中是 5 分鐘):

rate(http_requests_total{api="add_product"}[5m]) * 5 * 60

其他你可能會使用 Counter 類型指標的例子:測量電子商務網站的訂單數量,在網絡接口上發送和接收的字節數,或者應用程序中的錯誤數量。如果它是一個會一直上升的指標,那麼就使用一個 Counter。

下面是一個例子,說明如何使用 Prometheus 客戶端庫在 Python 中創建和增加一個計數器指標:

from prometheus_client import Counter
api_requests_counter = Counter(
                        'http_requests_total',
                        'Total number of http api requests',
                        ['api']
                       )
api_requests_counter.labels(api='add_product').inc()

需要注意的是,由於 Counter 可以被重置爲零,你要確保你用來存儲和查詢指標的後端能夠支持這種情況,並且在 Counter 重啓的情況下仍然提供準確的結果。Prometheus 和兼容 PromQL 的 Prometheus 遠程存儲系統,如 Promscale,可以正確處理 Counter 重啓。

儀表(Gauge)

Gauge 指標用於可以任意增加或減少的測量。這是你可能更熟悉的指標類型,因爲即使沒有經過額外處理的實際值也是有意義的,它們經常被使用到。例如,測量溫度、CPU 和內存使用的指標,或者隊列的大小都是 Gauge。

例如,爲了測量一臺主機的內存使用情況,我們可以使用一個 Gauge 指標,比如:

# HELP node_memory_used_bytes Total memory used in the node in bytes
# TYPE node_memory_used_bytes gauge
node_memory_used_bytes{host} 943348382

上面的指標表明,在測量時,節點 host1.domain.com 使用的內存約爲 900 MB。該指標的值是有意義的,不需要任何額外的計算,因爲它告訴我們該節點上消耗了多少內存。

與使用 Counter 指標時不同,rate 和 delta 函數對 Gauge 沒有意義。然而,計算特定時間序列的平均數、最大值、最小值或百分比的函數經常與 Gauge 一起使用。在 Prometheus 中,這些函數的名稱是 avg_over_time、max_over_time、min_over_time 和 quantile_over_time。要計算過去 10 分鐘內在 host1.domain.com 上使用的平均內存,你可以這樣做:

avg_over_time(node_memory_used_bytes{host}[10m])

要使用 Prometheus 客戶端庫在 Python 中創建一個 Gauge 指標,你可以這樣做:

from prometheus_client import Gauge
memory_used = Gauge(
                'node_memory_used_bytes',
                'Total memory used in the node in bytes',
                ['hostname']
              )
memory_used.labels(hostname='host1.domain.com').set(943348382)

直方圖(Histogram)

Histogram 指標對於表示測量的分佈很有用。它們經常被用來測量請求持續時間或響應大小。

直方圖將整個測量範圍劃分爲一組區間,稱爲桶,並計算每個桶中有多少測量值。

一個直方圖指標包括幾個項目:

  1. 一個包含測量次數的 Counter。指標名稱使用_count 後綴。

  2. 一個包含所有測量值之和的 Counter。指標名稱使用_sum 後綴。

  3. 直方圖桶被暴露爲一系列的 Counter,使用指標名稱的後綴_bucket 和表示桶的上限的 le label。Prometheus 中的桶是包含桶的邊界的,即一個上限爲 N 的桶(即 le label)包括所有數值小於或等於 N 的數據點。

例如,測量運行在 host1.domain.com 實例上的 add_productAPI 端點實例的響應時間的 Histogram 指標可以表示爲:

# HELP http_request_duration_seconds Api requests response time in seconds
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_sum{api="add_product" instance="host1.domain.com"} 8953.332
http_request_duration_seconds_count{api="add_product" instance="host1.domain.com"} 27892
http_request_duration_seconds_bucket{api="add_product" instance="host1.domain.com" le="0"}
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="0.01"} 0
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="0.025"} 8
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="0.05"} 1672
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="0.1"} 8954
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="0.25"} 14251
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="0.5"} 24101
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="1"} 26351
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="2.5"} 27534
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="5"} 27814
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="10"} 27881
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="25"} 27890
http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"le="+Inf"} 27892

上面的例子包括 sum、counter 和 12 個桶。sum 和 counter 可以用來計算一個測量值隨時間變化的平均值。在 PromQL 中,過去 5 分鐘的平均請求響應時間可以通過如下方式計算得到。

rate(http_request_duration_seconds_sum{api="add_product"instance="host1.domain.com"}[5m]) / rate(http_request_duration_seconds_count{api="add_product"instance="host1.domain.com"}[5m])

它也可以被用來計算各時間序列的平均數。下面的 PromQL 查詢將計算出所有 API 和實例在過去 5 分鐘內的平均請求響應時間。

sum(rate(http_request_duration_seconds_sum[5m])) / sum(rate(http_request_duration_seconds_count[5m]))

利用 Histogram,你可以在查詢時計算單個時間序列以及多個時間序列的百分位。在 PromQL 中,我們將使用 histogram_quantile 函數。Prometheus 使用分位數而不是百分位數。它們本質上是一樣的,但是以 0 到 1 的比例表示的,而百分位數是以 0 到 100 的比例表示的。要計算在 host1.domain.com 上運行的 add_product API 響應時間的第 99 百分位數(0.99 四分位數),你可以使用以下查詢。

histogram_quantile(0.99, rate(http_request_duration_seconds_bucket{api="add_product"instance="host1.domain.com"}[5m]))

Histograms 的一大優勢是可以進行彙總。下面的查詢返回所有 API 和實例的響應時間的第 99 個百分點‍:

histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

在雲原生環境中,通常有許多相同組件的多個實例在運行,能否跨實例彙總數據是關鍵。

Histograms 有三個主要的缺點:

下面的例子顯示瞭如何使用 Prometheus 的 Python 客戶端庫創建一個帶有自定義桶的直方圖指標。

from prometheus_client import Histogram
api_request_duration = Histogram(
                        name='http_request_duration_seconds',
                        documentation='Api requests response time in seconds',
                        labelnames=['api''instance'],
                        buckets=(0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 25 )
                       )
api_request_duration.labels(
    api='add_product',
    instance='host1.domain.com'
).observe(0.3672)

彙總(Summary)

像直方圖一樣,Summary 指標對於測量請求持續時間和響應體大小很有用。

像直方圖一樣,彙總度量對於測量請求持續時間和響應大小很有用。

一個 Summary 指標包括這些指標:

例如,測量在 host1.domain.com 上運行的 add_productAPI 端點實例的響應時間的 Summary 指標可以表示爲:

# HELP http_request_duration_seconds Api requests response time in seconds
# TYPE http_request_duration_seconds summary
http_request_duration_seconds_sum{api="add_product" instance="host1.domain.com"} 8953.332
http_request_duration_seconds_count{api="add_product" instance="host1.domain.com"} 27892
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0"}
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0.5"} 0.232227334
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0.90"} 0.821139321
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0.95"} 1.528948804
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="0.99"} 2.829188272
http_request_duration_seconds{api="add_product" instance="host1.domain.com" quantile="1"} 34.283829292

上面這個例子包括總和和計數以及五個分位數。分位數 0 相當於最小值,分位數 1 相當於最大值。分位數 0.5 是中位數,分位數 0.90、0.95 和 0.99 相當於在 host1.domain.com 上運行的 add_product API 端點響應時間的第 90、95 和 99 個百分位。

像直方圖一樣,Summary 指標包括總和和計數,可用於計算隨時間的平均值以及不同時間序列的平均值。

Summary 提供了比 Histogram 更精確的百分位計算結果,但這些百分位有三個主要缺點:

下面的代碼使用 Prometheus 的 Python 客戶端庫創建了一個 Summary 指標。

from prometheus_client import Summary
api_request_duration = Summary(
                        'http_request_duration_seconds',
                        'Api requests response time in seconds',
                        ['api''instance']
                       )
api_request_duration.labels(api='add_product'instance='host1.domain.com').observe(0.3672)

上面的代碼沒有定義任何量化指標,只會產生總和和計數指標。Prometheus 的 Python SDK 不支持 Summary 指標中的分位數計算。

Histogram 還是 Summary?

在大多數情況下,直方圖是首選,因爲它更靈活,並允許彙總百分位數。

在不需要百分位數而只需要平均數的情況下,或者在需要非常精確的百分位數的情況下,彙總是有用的。例如,在履行關鍵系統的合約責任的情況下。

下表總結了直方圖和彙總表的優點和缺點。

kl8oDA

Prometheus 中直方圖與彙總的不同特性的比較

總結

在這個關於指標的系列博文的第一部分,我們已經回顧了 Prometheus 指標的四種類型:計數器、儀表、直方圖和彙總。在這個系列的下一部分,我們將剖析 OpenTelemetry 指標。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/OqkGioTuDJdep5doCJb5ww