直方圖與摘要是更複雜的指標類型。單一直方圖或摘要不僅會建立大量的時間序列,而且更難以正確使用這些指標類型。本節將幫助您為您的用例選擇和配置適當的指標類型。
某些函式庫僅支援兩種類型中的其中一種,或者它們僅以有限的方式支援摘要(缺乏 分位數計算)。
直方圖和摘要都會取樣觀察值,通常是請求持續時間或回應大小。它們會追蹤觀察次數和觀察值的總和,讓您能夠計算觀察值的平均值。請注意,觀察次數(在 Prometheus 中顯示為具有 _count
後綴的時間序列)本質上是一個計數器(如上所述,它只會增加)。只要沒有負數的觀察值,觀察值的總和(顯示為具有 _sum
後綴的時間序列)也像計數器一樣運作。顯然,請求持續時間或回應大小永遠不會是負數。然而,原則上,您可以使用摘要和直方圖來觀察負值(例如,攝氏溫度)。在這種情況下,觀察值的總和可能會下降,因此您無法再對其應用 rate()
。在需要應用 rate()
且無法避免負數觀察值的罕見情況下,您可以使用兩個單獨的摘要,一個用於正數觀察值,另一個用於負數觀察值(後者具有反向符號),然後稍後使用適當的 PromQL 表達式來合併結果。
若要從名為 http_request_duration_seconds
的直方圖或摘要計算過去 5 分鐘內的平均請求持續時間,請使用以下表達式
rate(http_request_duration_seconds_sum[5m])
/
rate(http_request_duration_seconds_count[5m])
直方圖(而非摘要)的直接用法是計算落在特定觀察值儲存桶中的觀察值。
您可能有在 300 毫秒內服務 95% 請求的 SLO。在這種情況下,請配置一個直方圖,使其儲存桶的上限為 0.3 秒。然後,您可以直接表達在 300 毫秒內服務的請求的相對數量,並且如果該值降至 0.95 以下,則可以輕鬆發出警示。以下表達式會計算過去 5 分鐘內每個任務的服務請求數量。請求持續時間是使用名為 http_request_duration_seconds
的直方圖收集的。
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m])) by (job)
/
sum(rate(http_request_duration_seconds_count[5m])) by (job)
您可以使用類似的方式來近似著名的 Apdex 分數。將具有目標請求持續時間的儲存桶配置為上限,並將具有可容忍請求持續時間(通常是目標請求持續時間的 4 倍)的另一個儲存桶配置為上限。範例:目標請求持續時間為 300 毫秒。可容忍的請求持續時間為 1.2 秒。以下表達式會產生過去 5 分鐘內每個任務的 Apdex 分數
(
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m])) by (job)
+
sum(rate(http_request_duration_seconds_bucket{le="1.2"}[5m])) by (job)
) / 2 / sum(rate(http_request_duration_seconds_count[5m])) by (job)
請注意,我們會將兩個儲存桶的總和相除。原因是直方圖儲存桶是累積的。le="0.3"
儲存桶也包含在 le="1.2"
儲存桶中;將其除以 2 可對此進行修正。
計算結果與傳統 Apdex 分數並不完全相符,因為它在計算的滿意和可容忍部分中包含錯誤。
您可以使用摘要和直方圖來計算所謂的 φ-分位數,其中 0 ≤ φ ≤ 1。φ-分位數是在 N 個觀察值中排名為 φ*N 的觀察值。φ-分位數的範例:0.5-分位數稱為中位數。0.95-分位數是第 95 個百分位數。
摘要和直方圖之間的基本差異在於,摘要會在客戶端計算串流 φ-分位數並直接公開它們,而直方圖則會公開已分組的觀察次數,而從直方圖儲存桶計算分位數則會在伺服器端使用 histogram_quantile()
函式 來完成。
這兩種方法有許多不同的含義
直方圖 | 摘要 | |
---|---|---|
所需的組態 | 選擇適合預期觀察值範圍的儲存桶。 | 選擇所需 φ-分位數和滑動視窗。其他 φ-分位數和滑動視窗無法稍後計算。 |
客戶端效能 | 觀察非常便宜,因為它們只需要增加計數器。 | 由於串流分位數計算,觀察很昂貴。 |
伺服器效能 | 伺服器必須計算分位數。如果臨時計算耗時過長(例如在大型儀表板中),您可以使用 記錄規則。 | 伺服器端成本低。 |
時間序列數量(除了 _sum 和 _count 序列之外) |
每個已設定儲存桶一個時間序列。 | 每個已設定分位數一個時間序列。 |
分位數誤差(請參閱下文了解詳細資訊) | 誤差在觀察值維度中受到相關儲存桶寬度的限制。 | 誤差在 φ 維度中受到可設定值的限制。 |
φ-分位數和滑動時間視窗的規格 | 使用 Prometheus 表達式 臨時指定。 | 由客戶端預先設定。 |
彙總 | 使用 Prometheus 表達式 臨時指定。 | 一般而言 不可彙總。 |
請注意表格中最後一項的重要性。讓我們回到在 300 毫秒內服務 95% 請求的 SLO。這次,您不想顯示在 300 毫秒內服務的請求百分比,而是顯示第 95 個百分位數,即您已服務 95% 請求的請求持續時間。為此,您可以配置具有 0.95 分位數和(例如)5 分鐘衰減時間的摘要,或配置具有 300 毫秒附近幾個儲存桶的直方圖,例如 {le="0.1"}
、{le="0.2"}
、{le="0.3"}
和 {le="0.45"}
。如果您的服務在多個實例中複寫執行,您將從每個實例收集請求持續時間,然後您希望將所有內容彙總為一個總體第 95 個百分位數。但是,彙總來自摘要的預先計算分位數很少有意義。在這種特殊情況下,平均分位數會產生統計上無意義的值。
avg(http_request_duration_seconds{quantile="0.95"}) // BAD!
使用直方圖,可以使用 histogram_quantile()
函式 完全實現彙總。
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) // GOOD.
此外,如果您的 SLO 發生變化,而您現在想要繪製第 90 個百分位數,或者您想要考慮過去 10 分鐘而不是過去 5 分鐘,您只需調整以上表達式,而無需重新設定客戶端。
無論是在客戶端還是伺服器端計算,分位數都是估計值。了解該估計的誤差非常重要。
繼續以上面的直方圖範例,假設您的常見請求持續時間幾乎都非常接近 220 毫秒,或者換句話說,如果您可以繪製「真實」直方圖,您將會在 220 毫秒處看到一個非常明顯的峰值。在如上設定的 Prometheus 直方圖指標中,幾乎所有觀察值,因此第 95 個百分位數,都將落在標記為 {le="0.3"}
的儲存桶中,即從 200 毫秒到 300 毫秒的儲存桶。直方圖實作保證真實的第 95 個百分位數介於 200 毫秒和 300 毫秒之間。為了傳回單一值(而不是間隔),它會應用線性內插,在這種情況下會產生 295 毫秒。計算出的分位數給您的印象是您即將違反 SLO,但實際上,第 95 個百分位數略高於 220 毫秒,這與您的 SLO 有一段相當舒適的距離。
在我們的思想實驗中的下一步:後端路由中的變更會將 100 毫秒的固定量新增到所有請求持續時間。現在,請求持續時間的峰值位於 320 毫秒,幾乎所有觀察值都將落在從 300 毫秒到 450 毫秒的儲存桶中。第 95 個百分位數計算為 442.5 毫秒,儘管正確值接近 320 毫秒。雖然您僅稍微超出您的 SLO,但計算出的第 95 個分位數看起來要差得多。
在兩種情況下,摘要都能毫無問題地計算出正確的百分位數值,至少如果它在客戶端使用適當的演算法(例如,Go 客戶端使用的演算法)。不幸的是,如果您需要彙總來自多個實例的觀察值,則無法使用摘要。
幸運的是,由於您適當選擇了儲存桶的邊界,即使在這個觀察值分佈出現非常尖銳峰值的刻意範例中,直方圖也能夠正確地識別您是否在 SLO 內或之外。此外,分位數的實際值越接近我們的 SLO(或者換句話說,我們實際上最感興趣的值),計算出的值就越準確。
現在讓我們再次修改實驗。在新的設置中,請求持續時間的分佈在 150 毫秒處有一個峰值,但它不像之前那麼尖銳,僅佔觀察值的 90%。10% 的觀察值均勻分佈在 150 毫秒到 450 毫秒之間的長尾中。在這種分佈下,第 95 百分位數恰好在我們的 SLO 300 毫秒處。使用直方圖,計算出的值是準確的,因為第 95 百分位數的值恰好與其中一個儲存桶邊界重合。即使是稍微不同的值仍然是準確的,因為相關儲存桶內的(刻意設計的)均勻分佈正是儲存桶內線性插值所假設的。
現在,摘要報告的分位數誤差變得更有趣了。摘要中分位數的誤差是在 φ 的維度中配置的。在我們的例子中,我們可能配置了 0.95±0.01,也就是說,計算出的值將在第 94 和第 96 百分位數之間。在上述分佈下,第 94 分位數為 270 毫秒,第 96 分位數為 330 毫秒。摘要報告的第 95 百分位數的計算值可能在 270 毫秒到 330 毫秒之間的任何位置,不幸的是,這正是明確在 SLO 內與明確在 SLO 外之間的所有差異。
重點是:如果您使用摘要,您可以在 φ 的維度中控制誤差。如果您使用直方圖,您可以透過選擇適當的儲存桶佈局來控制觀察值的維度中的誤差。對於廣泛的分佈,φ 的微小變化會導致觀察值的巨大偏差。對於尖銳的分佈,觀察值的小範圍涵蓋了 φ 的大範圍。
兩條經驗法則
如果您需要聚合,請選擇直方圖。
否則,如果您對將要觀察到的值的範圍和分佈有概念,請選擇直方圖。如果您需要準確的分位數,無論值的範圍和分佈如何,請選擇摘要。
實作它!歡迎程式碼貢獻。一般來說,我們預期直方圖的需求比摘要更迫切。直方圖在客戶端函式庫中也更容易實作,因此如果猶豫不決,我們建議先實作直方圖。
此文件是開放原始碼。請透過提交問題或提取請求來幫助改進它。