摘要:眾所周知,負責收集并聚合測量值。每個都有一個,該值的解釋方式依賴于。計時器的一大好處在于,你可以得到平均值總值計數值和上下限值。給傳一個數字,它會不經處理地將該數字傳到后端。由三部分組成監聽時間序列的數據的后臺程序。
眾所周知,StatsD 負責收集并聚合測量值。之后,它會將數據傳給 Graphite,后者以時間序列為依據存儲數據,并繪制圖表。但是,我們不知道,基于 http 訪問的圖表在展示時,是基于每秒鐘的請求數,每次留存的平均請求數還是其它。讓我們就以此為目標,來一探究竟吧!本文系 OneAPM 工程師編譯整理。
StatsD
為了全面了解 StatsD 的工作原理,我閱讀了它的源碼。之前我就耳聞 StatsD 是一種簡單的應用,但讀過源碼后才發現它竟如此簡單!在主腳本文件只有300多行代碼,而 Graphite 的后端代碼只有150行左右。
在這個文檔中,列出了一些需要理解的 StatsD 概念。
Buckets
當一個 Whisper 文件被創建,它會有一個不會改變的固定大小。在這個文件中可能有多個 "buckets" 對應于不同分別率的數據點,每個 bucket 也有一個保留屬性指明數據點應該在 bucket 中應該被保留的時間長度,Whisper 執行一些簡單的數學計算來計算出多少數據點會被實際保存在每個 bucket 中。
Values
每個 stat 都有一個 value,該值的解釋方式依賴于 modifier。通常,values 應該是整數。
Flush Interval
在 flush interval (沖洗間隔,通常為10秒)超時之后,stats 會聚集起來,傳送到上游的后端服務。
測量值類別計數器
計數器很簡單。它會給 bucket 加 value,并存儲在內存中,直到 flush interval 超時。
讓我們看一下生成計數器 stats 的源碼,該 stats 會被推送到后端。
for (key in counters) { var value = counters[key]; var valuePerSecond = value / (flushInterval / 1000); // calculate "per second" rate statString += "stats."+ key + " " + valuePerSecond + " " + ts + " "; statString += "stats_counts." + key + " " + value + " " + ts + " "; numStats += 1; }
首先,StatsD 會迭代它收到的所有計數器,對每個計數器它都會分配兩個變量。一個變量用于存儲計數器的 value,另一個存儲 per-second value。之后,它會將 values 加至 statString,同時增加 numStats 變量的值。
如果你使用默認的 flush interval(10秒),并在每個間隔通過某個計數器給 StatsD 傳送7個增量。則計時器的 value 為 7,而 per-second value 為 0.7。
計時器
計時器用于收集數字。他們不必要包含時間值。你可以收集某個存儲器中的字節數、對象數或任意數字。計時器的一大好處在于,你可以得到平均值、總值、計數值和上下限值。給 StatsD 設置一個計時器,就能在數據傳送給 Graphite 之前自動計算這些量。
計時器的源碼比計數器的源碼要稍微復雜一些。
for (key in timers) { if (timers[key].length > 0) { var values = timers[key].sort(function (a,b) { return a-b; }); var count = values.length; var min = values[0]; var max = values[count - 1]; var cumulativeValues = [min]; for (var i = 1; i < count; i++) { cumulativeValues.push(values[i] + cumulativeValues[i-1]); } var sum = min; var mean = min; var maxAtThreshold = max; var message = ""; var key2; for (key2 in pctThreshold) { var pct = pctThreshold[key2]; if (count > 1) { var thresholdIndex = Math.round(((100 - pct) / 100) * count); var numInThreshold = count - thresholdIndex; maxAtThreshold = values[numInThreshold - 1]; sum = cumulativeValues[numInThreshold - 1]; mean = sum / numInThreshold; } var clean_pct = "" + pct; clean_pct.replace(".", "_"); message += "stats.timers." + key + ".mean_" + clean_pct + " " + mean + " " + ts + " "; message += "stats.timers." + key + ".upper_" + clean_pct + " " + maxAtThreshold + " " + ts + " "; message += "stats.timers." + key + ".sum_" + clean_pct + " " + sum + " " + ts + " "; } sum = cumulativeValues[count-1]; mean = sum / count; message += "stats.timers." + key + ".upper " + max + " " + ts + " "; message += "stats.timers." + key + ".lower " + min + " " + ts + " "; message += "stats.timers." + key + ".count " + count + " " + ts + " "; message += "stats.timers." + key + ".sum " + sum + " " + ts + " "; message += "stats.timers." + key + ".mean " + mean + " " + ts + " "; statString += message; numStats += 1; } }
如果在默認的 flush interval 內,你將下列計數器 values 傳給 StatsD:
450
120
553
994
334
844
675
496
StatsD 將會計數下面的 values:
mean_90 496
upper_90 844
sum_90 3472
upper 994
lower 120
count 8
sum 4466
mean 558.25
Gauges
一個 guage 代表著時間段內某點的任意 vaule,是 StatsD 中最簡單的類型。你可以給它傳任意值,它會傳給后端。
Gauge stats 的源碼只有短短四行。
for (key in gauges) { statString += "stats.gauges." + key + " " + gauges[key] + " " + ts + " "; numStats += 1; }
給 StatsD 傳一個數字,它會不經處理地將該數字傳到后端。值得注意的是,在一個 flush interval 內,只有 gauge 最后的值會傳送到后端。因此,如果你在一個 flush interval 內,將下面的 gauge 值傳給 StatsD:
643
754
583
會傳到后端的值只有583而已。該 gauge 的值會一直存儲在內存中,直到 flush interval 結束才傳值。
Graphite現在,我們已經了解數據是怎樣從 StatsD 傳出來的,讓我們看看它在 Graphite 里是如何存儲并處理的。
總覽在 Graphite 文檔里,我們可以找到 Graphite 概覽,此概覽總結了 Graphite 的兩個要點:
Graphite 存儲數值型帶有時間序列的數據。
Graphite 按需繪制圖表。
Graphite 由三部分組成:
carbon :監聽時間序列的數據的后臺程序。
whisper:一個簡單的數據庫庫,用來存儲時間序列數據。
webapp: Django webapp,使用 Cairo 來根據需要呈現圖形。
Graphite 當做時間序列數據的格式如下:
存儲方案
Graphite 采用可配置的存儲方案用以定義所存數據的留存率。它會給數據路徑匹配特定的模式,從而決定所存數據的頻率和來歷。
以下配置示例截取自 StatsD 文檔。
[stats] pattern = ^stats..* retentions = 10:2160,60:10080,600:262974
該示例表明,匹配上述樣式的數據都會套用這些留存。留存的格式為 frequency: history。所以,該配置允許我們將10秒鐘的數據存儲6個小時,1分鐘的數據存儲1周,10分鐘的數據存儲5年。
在 Graphite 顯示計時器了解了這么多,我們來看看一個簡單的 ruby 腳本,該腳本能收集 HTTP 請求的時間。
#!/usr/bin/env ruby require "rubygems" if RUBY_VERSION < "1.9.0" require "./statsdclient.rb" require "typhoeus" Statsd.host = "localhost" Statsd.port = 8125 def to_ms time (1000 * time).to_i end while true start_time = Time.now.to_f resp = Typhoeus::Request.get "http://www.example.org/system/information" end_time = Time.now.to_f elapsed_time = (1000 * end_time) - (to_ms start_time) response_time = to_ms resp.time start_transfer_time = to_ms resp.start_transfer_time app_connect_time = to_ms resp.app_connect_time pretransfer_time = to_ms resp.pretransfer_time connect_time = to_ms resp.connect_time name_lookup_time = to_ms resp.name_lookup_time Statsd.timing("http_request.elapsed_time", elapsed_time) Statsd.timing("http_request.response_time", response_time) Statsd.timing("http_request.start_transfer_time", start_transfer_time) Statsd.timing("http_request.app_connect_time", app_connect_time) Statsd.timing("http_request.pretransfer_time", pretransfer_time) Statsd.timing("http_request.connect_time", connect_time) Statsd.timing("http_request.name_lookup_time", name_lookup_time) sleep 10 end
讓我們看看該數據生成的 Graphite 圖。該數據來自 2 分鐘前,而 elapsed_time 則來自前面的腳本。
圖像生成
Render URL
下面圖片的 Render URL
/render/?width=586&height=308&from=-2minutes&target=stats.timers.http_request.elapsed_time.sum
Graphite 生成的圖片
該圖片簡單地描繪了 http 請求在一段時間內的 elapsed_time 值。
JSON-data
Render URL
下面 JSON-data 的 Render URL
/render/?width=586&height=308&from=-2minutes&target=stats.timers.http_request.elapsed_time.sum&format=json
來自 Graphite 的 JSON-output
在下面的結果中,我們可以查看來自 Graphite 的源數據。這些數據來自12個不同的數據點,也即 StatsD 10 秒 flush internal 的兩分鐘。Graphite 繪制數據就是如此簡單。
此外,借助 JSONLint,JSON-data 的數據顯示更加美觀。
[ { "target": "stats.timers.http_request.elapsed_time.sum", "datapoints": [ [ 53.449951171875, 1343038130 ], [ 50.3916015625, 1343038140 ], [ 50.1357421875, 1343038150 ], [ 39.601806640625, 1343038160 ], [ 41.5263671875, 1343038170 ], [ 34.3974609375, 1343038180 ], [ 36.3818359375, 1343038190 ], [ 35.009033203125, 1343038200 ], [ 37.0087890625, 1343038210 ], [ 38.486572265625, 1343038220 ], [ 45.66064453125, 1343038230 ], [ null, 1343038240 ] ] } ]在 Graphite 繪制 gauge 圖像
下面的簡單腳本能將 gauge 傳送給 StatsD,模擬用戶注冊的過程。
#!/usr/bin/env ruby require "./statsdclient.rb" Statsd.host = "localhost" Statsd.port = 8125 user_registrations = 1 while true user_registrations += Random.rand 128 Statsd.gauge("user_registrations", user_registrations) sleep 10 end
圖像顯示——用戶注冊數量
Render URL
下面圖片的 Render URL
/render/?width=586&height=308&from=-20minutes&target=stats.gauges.user_registrations
來自 Graphite 的圖片
另一個簡單的圖片,展示總的注冊數。
圖片顯示——每分鐘的用戶注冊數
使用 Graphite 的衍生函數,可以獲得每分鐘的用戶注冊數量。
Render URL
下面圖片的 Render URL
/render/?width=586&height=308&from=-20minutes&target=derivative(stats.gauges.user_registrations)
來自 Graphite 的圖片
該圖片所用的數據跟之前的圖片一致,但是使用了衍生函數從而顯示每分鐘的注冊率。
結論
深入了解 StatsD 與 Graphite 的工作原理,能讓我們更加明白 StatsD 所傳送的數據種類,如何傳送,以及怎樣更有效地根據 Graphite 讀取數據。
原文地址:https://blog.pkhamre.com/understanding-statsd-and-graphite/
OneAPM 是應用性能管理領域的新興領軍企業,Cloud Insight 能幫助企業用戶和開發者輕松實現:監控各項基礎組件以及對數據進行聚合、過濾和篩選的功能,致力于打造一個更為強大的數據管理平臺。想閱讀更多技術文章,請訪問 OneAPM 官方博客。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7924.html
摘要:本文轉自劉斌博文如何選擇監控方案,文中劉斌從技術的角度深入解釋了監控的數據采集原理,介紹了現有開源的監控方案,以及能夠對進行監控功能的主流服務工具。下一章,劉斌將為大家介紹監控的開原方案,主流服務,及其特點。 過去的一年中,關于 Docker 的話題從未斷過,而如今,從嘗試 Docker 到最終決定使用 Docker 的轉化率依然在逐步升高,關于 Docker 的討論更是有增無減。另一...
摘要:的展示非常炫酷,絕對是運維提升逼格的一大利器。另外的可視化功能比強得多,而且以上版本將集成報警功能。它由寫成,著力于高性能地查詢與存儲時序型數據。被廣泛應用于存儲系統的監控數據,行業的實時數據等場景。 原有監控系統 showImg(https://segmentfault.com/img/remote/1460000011082384); 整個系統以 Graphite (carbon ...
摘要:有如下模塊源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析使用和監控和博客從到學習介紹從到學習上搭建環境并構建運行簡單程序入門從到學習配置文件詳解從到學習介紹從到學習如何自 Flink Metrics 有如下模塊: Flink Metrics 源碼解析 —— Flink-metrics-core Flink Metrics 源碼解析 —— Flink-metr...
摘要:可行工具圖為上監控到的應用程序響應時間和吞吐量平均負載第二個廣泛使用的衡量指標就是服務器的平均負載。率和中止時間垃圾回收器行為異常,是導致應用吞吐量和響應時間突然下降的主要原因之一。 在某個重大發布之后,都需要記錄相應的指標,本文介紹了最重要的幾個 Java 性能指標,包括響應時間和平均負載等。為理解應用程序在生產環境中如何運行,就需要遵循一些 Java 性能指標。 在以前,當軟件被發...
摘要:前言在資源審計和計費這塊,容器和虛機有很大區別。支持諸多輸出,稱為。所以本文主要講如何為增加。實際上,基于增加并且更改,也可以做到,只不過需要裝一些包指令,結果就是鏡像變大。實際運行日志截圖由于的出色的寫入性能,運行非常穩定。 前言 在k8s資源審計和計費這塊,容器和虛機有很大區別。相對虛機來講,容器不容易實現。資源指標收集可以采用heapster,也可以用prometheus。之前文...
閱讀 975·2023-04-26 02:56
閱讀 9511·2021-11-23 09:51
閱讀 1875·2021-09-26 10:14
閱讀 2986·2019-08-29 13:09
閱讀 2158·2019-08-26 13:29
閱讀 575·2019-08-26 12:02
閱讀 3566·2019-08-26 10:42
閱讀 3007·2019-08-23 18:18