指標是用來衡量性能、消耗、效率和許多其他軟件屬性隨時間的變化趨勢。它們允許工程師通過警報和儀表盤來監控一系列測量值的演變(如CPU或內存使用量、請求持續時間、延遲等)。指標在IT監控領域有著悠久的歷史,并被工程師廣泛使用,與日志和鏈路追蹤一起被用來檢測系統是否有不符合預期的表現。 在其最基本的形式中,一個指標數據點是由以下三個部分構成:
一個指標名稱
收集該數據點的時間戳
一個由數字表示的測量值
在過去的十年里,隨著系統變得越來越復雜,出現了維度度量的概念,也就是說,度量還包括一組標簽或標識(即維度),以提供額外的上下文。支持維度指標的監控系統允許工程師通過查詢特定的指標名稱,并通過標簽進行過濾和分組,從而輕易地在多個組件和維度上匯總和分析一個指標。 Prometheus定義了一個度量說明格式和一個遠程寫入協議,社區和許多供應商都采用這個協議來說明和收集度量成為事實上的標準。OpenMetrics是另一個CNCF項目,它建立在Prometheus導出格式的基礎上,為收集度量標準提供了一個與廠商無關的標準化模型,旨在成為互聯網工程任務組(IEFT)的一部分。 最近,另一個CNCF項目OpenTelemetry出現了,它的目標是提供一個新的標準,能夠統一指標、鏈路跟蹤和日志的收集,使跨領域的遙測信號收集和關聯更容易。 我們希望你在讀完這些文章后,你能理解每個標準之間的差異,這樣你就能決定哪一個能更好地滿足你當前(和未來)的需求。
1、Prometheus指標
首先要做的事。Prometheus收集的指標有四種,作為其暴露格式的一部分。
Counters
Gauges
Histograms
Summaries
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函數。
# 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{hostname="host1.domain.com"} 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{hostname="host1.domain.com"}[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 指標對于表示測量的分布很有用。它們經常被用來測量請求持續時間或響應大小。 直方圖將整個測量范圍劃分為一組區間,稱為桶,并計算每個桶中有多少測量值。 一個直方圖指標包括幾個項目:
一個包含測量次數的Counter。指標名稱使用_count后綴。
一個包含所有測量值之和的Counter。指標名稱使用_sum后綴。
直方圖桶被暴露為一系列的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有三個主要的缺點:首先,桶必須是預定義的,這需要一些前期的設計。如果你的桶沒有被很好地定義,你可能無法計算出你需要的百分比,或者會消耗不必要的資源。例如,如果你有一個總是需要超過一秒鐘的API,那么擁有上限(le label)小于一秒鐘的桶將是無用的,只會消耗監控后端服務器的計算和存儲資源。另一方面,如果99.9%的API請求耗時少于50毫秒,那么擁有一個上限為100毫秒的初始桶將無法讓你準確測量API的性能。
第二,他們提供的是近似的百分位數,而不是精確的百分位數。這通常沒什么問題,只要你的桶被設計為提供具有合理準確性的結果。
第三,由于百分位數需要在服務器端計算,當有大量數據需要處理時,它們的計算成本會非常高。在Prometheus中減輕這種情況的一個方法是使用錄制規則來預先計算所需的百分位數。
下面的例子顯示了如何使用 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指標包括這些指標:
一個包含總測量次數的Counter。指標名稱使用_count后綴。
一個包含所有測量值之和的Counter。指標名稱使用_sum后綴。可以選擇使用帶有分位數標簽的指標名稱,來暴露一些測量值的分位數指標。由于你不希望這些量值是從應用程序運行的整個時間內測得的,Prometheus客戶端庫通常會使用流式的分位值,這些分位值是在一個滑動的(通常是可配置的)時間窗口上計算得到的。
例如,測量在 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 SDK中的實現限制了內存中保留和排序的數據點的數量,這降低了準確性以換取效率的提高。注意,并非所有的Prometheus客戶端庫都支持匯總指標中的量值。例如,Python SDK就不支持。
第二,你要查詢的量值必須由客戶端預先定義。只有那些已經提供了指標的量值才能通過查詢返回。沒有辦法在查詢時計算其他百分位。增加一個新的百分位指標需要修改代碼,該指標才可以被使用。
第三,也是最重要的一點,不可能把多個Summary指標進行聚合計算。這使得它們對動態現代系統中的大多數用例毫無用處,在這些用例中,通常我們對一個特定的組件感興趣,這個視角是全局的,它不與特定的實例關聯。
因此,想象一下,在我們的例子中,add_product 的 API 端點運行在10個主機上,在這些服務之前有一個負載均衡器。我們沒有任何聚合函數可以用來計算add_product API 接口在所有請求中響應時間的第99百分位數,無論這些請求被發送到哪個后端實例上。我們只能看到每個主機的第99個百分點。 同樣地,我們也只能知道某個接口,比如 add_productAPI 端點的(在某個實例上的)第99百分位數,而不能對不同的接口進行聚合。
下面的代碼使用 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? 在大多數情況下,直方圖是首選,因為它更靈活,并允許匯總百分位數。 在不需要百分位數而只需要平均數的情況下,或者在需要非常精確的百分位數的情況下,匯總是有用的。例如,在履行關鍵系統的合約責任的情況下。 下表總結了直方圖和匯總表的優點和缺點。
編輯:黃飛
?
評論
查看更多