iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
DevOps

時間序列資料庫探討 - Prometheus系列 第 25

Prometheus - 時間序列資料寫入時的不同行為

  • 分享至 

  • xImage
  •  

大前篇提問

  • 常見的監控指標和 PromQL
  • Prometheus Server 的讀寫流程

本篇要來繼續講述不同 prometheus client 寫入流程細節上的不同處。

CAdvisor 和 Kafka Exporter

總的來說這兩個函式庫分別是把用既有的 http 和 sarama Client,定時抓取目標資料後。將資料轉換成 Prometheus Client 的資料型態。等待 Prometheus Server 的抓取。
需要特別注意的是 Prometheus Server 上的樣本時間是 Prometheus Server 的時間。而不是 Exporter 向 docker 或 kafka 請求資料的時間。雖然一般來說這兩個函式庫預設的抓取週期都比較短,但還是有為了省資源而調整的可能。

業務指標 Histogram

Histogram 可以提供數值分布的統計資料。使用上需先切分區間。在 Prometheus Client 中,Histogram 的每個區間各有一個計數器。每次有新數值時,由 atomic.Add 操作確保數值的正確性。
當 Prometheus Server 發送 http request 到 /metrics 時,Histogram 才會將各區間的計數器值累加,產生符合 OpenMetrics 格式-由 le 標籤區分的指標值。這個累加的過程是會對 histogram 上鎖的。確保在計算過程中,不會有新的數值被加入。
與 CounterVec 相同的是,HistogramVec 也會用 mutex 確保同一時間只能產生一個 Histogram。且不同 Histogram 之間的計數器值可以同時被增加。
更甚者,同 HistogramVec 內的兩個標籤不同的 Histogram 甲和乙。有可能甲先增加後乙才增加,http response 的數值卻只反應乙的增加。時間順序:

  1. Prometheus Client 收到 http request
  2. Registry 讀取甲的數值
  3. 甲增加
  4. 乙增加
  5. Registry 讀取乙的數值
  6. Registry 用讀到的數值產生 http response

Http API 錯誤率

上述誤差在 Counter 和 Gauge 上也有可能發生。比方說我們的 http client 中間件,除了增加計數器外,還記錄 elapsed_time:

//  作一個 http client 的中間件,每次向下游發送請求後增加對應的計數器
type prometheusMiddleware struct{}
func (m *prometheusMiddleware) RoundTrip (next http.RoundTripper)
    return func(req *http.Request) (*http.Response, error) {
        start := time.Now()
        // 發送請求到下游
        resp, err := next.RoundTrip(req)
        elapsed := time.Since(start)
        requestDuration.WithLabelValues(req.URL.Path, resp.StatusCode()).Add(elapsed)
        requestCount.WithLabelValues(req.URL.Path, resp.StatusCode()).Inc()
        return resp, err
    }
}

這時有極微小的機率,registry 讀取 requestDurationrequestCount 給 promethues server 時,只有其中一個增加。

反觀以下 PromQL 查詢:

http_responses_total{code!="2xx"} / http_responses_total

http_responses_total 是很多個不同時間序列的總和。總和的計算是在 Prometheus Server 上進行的。對於一個 code!="2xx" 的樣本。它在 PromQL 計算的時候,如果有被計入分子,那麼也一定會被計入分母。

相信從這個例子中,讀者可以看出為什麼 OpenMetrics 規範中,為什麼需要 StateSet 這個資料型態了。

P99 延遲

在舉例常見的監控指標時,我們提到了用 Histogram 來記錄 http 延遲。再由 PromQL 計算 P99 延遲。然而既然要算 P99,為什麼不用 Summary 卻要用 Histogram 呢?照理來說 Histogram 經過了區間切分,對資訊進行了壓縮,算出 P99 需要內插,並不準確。在已知要算 P99,的情況下,使用 Summary 會更準確。然而這只限於單一標的的情況。萬一我們有十臺同樣的服務,每臺服務都有一個 Summary,各自回報該機器上的 P99 延遲。當我們想要知道的是所有服務的 P99 延遲時,依舊毫無頭緒-既不能取平均,也不能加權平均。這時 Histogram 至少可以給我們一個合理的數值。
於是正確的使用 Summary 的方式,就是不要做任何的加總或平均。一開始就確認所需的標籤,查詢時也要指定所有的標籤。


上一篇
Prometheus - Storage 寫入流程
下一篇
Prometheus - /query_range 如何觸發 PromQL 執行
系列文
時間序列資料庫探討 - Prometheus30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言