摘要:眾所周知,負(fù)責(zé)收集并聚合測(cè)量值。每個(gè)都有一個(gè),該值的解釋方式依賴于。計(jì)時(shí)器的一大好處在于,你可以得到平均值總值計(jì)數(shù)值和上下限值。給傳一個(gè)數(shù)字,它會(huì)不經(jīng)處理地將該數(shù)字傳到后端。由三部分組成監(jiān)聽時(shí)間序列的數(shù)據(jù)的后臺(tái)程序。
眾所周知,StatsD 負(fù)責(zé)收集并聚合測(cè)量值。之后,它會(huì)將數(shù)據(jù)傳給 Graphite,后者以時(shí)間序列為依據(jù)存儲(chǔ)數(shù)據(jù),并繪制圖表。但是,我們不知道,基于 http 訪問的圖表在展示時(shí),是基于每秒鐘的請(qǐng)求數(shù),每次留存的平均請(qǐng)求數(shù)還是其它。讓我們就以此為目標(biāo),來一探究竟吧!本文系 OneAPM 工程師編譯整理。
StatsD
為了全面了解 StatsD 的工作原理,我閱讀了它的源碼。之前我就耳聞 StatsD 是一種簡(jiǎn)單的應(yīng)用,但讀過源碼后才發(fā)現(xiàn)它竟如此簡(jiǎn)單!在主腳本文件只有300多行代碼,而 Graphite 的后端代碼只有150行左右。
在這個(gè)文檔中,列出了一些需要理解的 StatsD 概念。
Buckets
當(dāng)一個(gè) Whisper 文件被創(chuàng)建,它會(huì)有一個(gè)不會(huì)改變的固定大小。在這個(gè)文件中可能有多個(gè) "buckets" 對(duì)應(yīng)于不同分別率的數(shù)據(jù)點(diǎn),每個(gè) bucket 也有一個(gè)保留屬性指明數(shù)據(jù)點(diǎn)應(yīng)該在 bucket 中應(yīng)該被保留的時(shí)間長(zhǎng)度,Whisper 執(zhí)行一些簡(jiǎn)單的數(shù)學(xué)計(jì)算來計(jì)算出多少數(shù)據(jù)點(diǎn)會(huì)被實(shí)際保存在每個(gè) bucket 中。
Values
每個(gè) stat 都有一個(gè) value,該值的解釋方式依賴于 modifier。通常,values 應(yīng)該是整數(shù)。
Flush Interval
在 flush interval (沖洗間隔,通常為10秒)超時(shí)之后,stats 會(huì)聚集起來,傳送到上游的后端服務(wù)。
測(cè)量值類別計(jì)數(shù)器
計(jì)數(shù)器很簡(jiǎn)單。它會(huì)給 bucket 加 value,并存儲(chǔ)在內(nèi)存中,直到 flush interval 超時(shí)。
讓我們看一下生成計(jì)數(shù)器 stats 的源碼,該 stats 會(huì)被推送到后端。
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 會(huì)迭代它收到的所有計(jì)數(shù)器,對(duì)每個(gè)計(jì)數(shù)器它都會(huì)分配兩個(gè)變量。一個(gè)變量用于存儲(chǔ)計(jì)數(shù)器的 value,另一個(gè)存儲(chǔ) per-second value。之后,它會(huì)將 values 加至 statString,同時(shí)增加 numStats 變量的值。
如果你使用默認(rèn)的 flush interval(10秒),并在每個(gè)間隔通過某個(gè)計(jì)數(shù)器給 StatsD 傳送7個(gè)增量。則計(jì)時(shí)器的 value 為 7,而 per-second value 為 0.7。
計(jì)時(shí)器
計(jì)時(shí)器用于收集數(shù)字。他們不必要包含時(shí)間值。你可以收集某個(gè)存儲(chǔ)器中的字節(jié)數(shù)、對(duì)象數(shù)或任意數(shù)字。計(jì)時(shí)器的一大好處在于,你可以得到平均值、總值、計(jì)數(shù)值和上下限值。給 StatsD 設(shè)置一個(gè)計(jì)時(shí)器,就能在數(shù)據(jù)傳送給 Graphite 之前自動(dòng)計(jì)算這些量。
計(jì)時(shí)器的源碼比計(jì)數(shù)器的源碼要稍微復(fù)雜一些。
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; } }
如果在默認(rèn)的 flush interval 內(nèi),你將下列計(jì)數(shù)器 values 傳給 StatsD:
450
120
553
994
334
844
675
496
StatsD 將會(huì)計(jì)數(shù)下面的 values:
mean_90 496
upper_90 844
sum_90 3472
upper 994
lower 120
count 8
sum 4466
mean 558.25
Gauges
一個(gè) guage 代表著時(shí)間段內(nèi)某點(diǎn)的任意 vaule,是 StatsD 中最簡(jiǎn)單的類型。你可以給它傳任意值,它會(huì)傳給后端。
Gauge stats 的源碼只有短短四行。
for (key in gauges) { statString += "stats.gauges." + key + " " + gauges[key] + " " + ts + " "; numStats += 1; }
給 StatsD 傳一個(gè)數(shù)字,它會(huì)不經(jīng)處理地將該數(shù)字傳到后端。值得注意的是,在一個(gè) flush interval 內(nèi),只有 gauge 最后的值會(huì)傳送到后端。因此,如果你在一個(gè) flush interval 內(nèi),將下面的 gauge 值傳給 StatsD:
643
754
583
會(huì)傳到后端的值只有583而已。該 gauge 的值會(huì)一直存儲(chǔ)在內(nèi)存中,直到 flush interval 結(jié)束才傳值。
Graphite現(xiàn)在,我們已經(jīng)了解數(shù)據(jù)是怎樣從 StatsD 傳出來的,讓我們看看它在 Graphite 里是如何存儲(chǔ)并處理的。
總覽在 Graphite 文檔里,我們可以找到 Graphite 概覽,此概覽總結(jié)了 Graphite 的兩個(gè)要點(diǎn):
Graphite 存儲(chǔ)數(shù)值型帶有時(shí)間序列的數(shù)據(jù)。
Graphite 按需繪制圖表。
Graphite 由三部分組成:
carbon :監(jiān)聽時(shí)間序列的數(shù)據(jù)的后臺(tái)程序。
whisper:一個(gè)簡(jiǎn)單的數(shù)據(jù)庫庫,用來存儲(chǔ)時(shí)間序列數(shù)據(jù)。
webapp: Django webapp,使用 Cairo 來根據(jù)需要呈現(xiàn)圖形。
Graphite 當(dāng)做時(shí)間序列數(shù)據(jù)的格式如下:
存儲(chǔ)方案
Graphite 采用可配置的存儲(chǔ)方案用以定義所存數(shù)據(jù)的留存率。它會(huì)給數(shù)據(jù)路徑匹配特定的模式,從而決定所存數(shù)據(jù)的頻率和來歷。
以下配置示例截取自 StatsD 文檔。
[stats] pattern = ^stats..* retentions = 10:2160,60:10080,600:262974
該示例表明,匹配上述樣式的數(shù)據(jù)都會(huì)套用這些留存。留存的格式為 frequency: history。所以,該配置允許我們將10秒鐘的數(shù)據(jù)存儲(chǔ)6個(gè)小時(shí),1分鐘的數(shù)據(jù)存儲(chǔ)1周,10分鐘的數(shù)據(jù)存儲(chǔ)5年。
在 Graphite 顯示計(jì)時(shí)器了解了這么多,我們來看看一個(gè)簡(jiǎn)單的 ruby 腳本,該腳本能收集 HTTP 請(qǐng)求的時(shí)間。
#!/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
讓我們看看該數(shù)據(jù)生成的 Graphite 圖。該數(shù)據(jù)來自 2 分鐘前,而 elapsed_time 則來自前面的腳本。
圖像生成
Render URL
下面圖片的 Render URL
/render/?width=586&height=308&from=-2minutes&target=stats.timers.http_request.elapsed_time.sum
Graphite 生成的圖片
該圖片簡(jiǎn)單地描繪了 http 請(qǐng)求在一段時(shí)間內(nèi)的 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
在下面的結(jié)果中,我們可以查看來自 Graphite 的源數(shù)據(jù)。這些數(shù)據(jù)來自12個(gè)不同的數(shù)據(jù)點(diǎn),也即 StatsD 10 秒 flush internal 的兩分鐘。Graphite 繪制數(shù)據(jù)就是如此簡(jiǎn)單。
此外,借助 JSONLint,JSON-data 的數(shù)據(jù)顯示更加美觀。
[ { "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 圖像
下面的簡(jiǎn)單腳本能將 gauge 傳送給 StatsD,模擬用戶注冊(cè)的過程。
#!/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
圖像顯示——用戶注冊(cè)數(shù)量
Render URL
下面圖片的 Render URL
/render/?width=586&height=308&from=-20minutes&target=stats.gauges.user_registrations
來自 Graphite 的圖片
另一個(gè)簡(jiǎn)單的圖片,展示總的注冊(cè)數(shù)。
圖片顯示——每分鐘的用戶注冊(cè)數(shù)
使用 Graphite 的衍生函數(shù),可以獲得每分鐘的用戶注冊(cè)數(shù)量。
Render URL
下面圖片的 Render URL
/render/?width=586&height=308&from=-20minutes&target=derivative(stats.gauges.user_registrations)
來自 Graphite 的圖片
該圖片所用的數(shù)據(jù)跟之前的圖片一致,但是使用了衍生函數(shù)從而顯示每分鐘的注冊(cè)率。
結(jié)論
深入了解 StatsD 與 Graphite 的工作原理,能讓我們更加明白 StatsD 所傳送的數(shù)據(jù)種類,如何傳送,以及怎樣更有效地根據(jù) Graphite 讀取數(shù)據(jù)。
原文地址:https://blog.pkhamre.com/understanding-statsd-and-graphite/
OneAPM 是應(yīng)用性能管理領(lǐng)域的新興領(lǐng)軍企業(yè),Cloud Insight 能幫助企業(yè)用戶和開發(fā)者輕松實(shí)現(xiàn):監(jiān)控各項(xiàng)基礎(chǔ)組件以及對(duì)數(shù)據(jù)進(jìn)行聚合、過濾和篩選的功能,致力于打造一個(gè)更為強(qiáng)大的數(shù)據(jù)管理平臺(tái)。想閱讀更多技術(shù)文章,請(qǐng)?jiān)L問 OneAPM 官方博客。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/7924.html
摘要:本文轉(zhuǎn)自劉斌博文如何選擇監(jiān)控方案,文中劉斌從技術(shù)的角度深入解釋了監(jiān)控的數(shù)據(jù)采集原理,介紹了現(xiàn)有開源的監(jiān)控方案,以及能夠?qū)M(jìn)行監(jiān)控功能的主流服務(wù)工具。下一章,劉斌將為大家介紹監(jiān)控的開原方案,主流服務(wù),及其特點(diǎn)。 過去的一年中,關(guān)于 Docker 的話題從未斷過,而如今,從嘗試 Docker 到最終決定使用 Docker 的轉(zhuǎn)化率依然在逐步升高,關(guān)于 Docker 的討論更是有增無減。另一...
摘要:的展示非常炫酷,絕對(duì)是運(yùn)維提升逼格的一大利器。另外的可視化功能比強(qiáng)得多,而且以上版本將集成報(bào)警功能。它由寫成,著力于高性能地查詢與存儲(chǔ)時(shí)序型數(shù)據(jù)。被廣泛應(yīng)用于存儲(chǔ)系統(tǒng)的監(jiān)控?cái)?shù)據(jù),行業(yè)的實(shí)時(shí)數(shù)據(jù)等場(chǎng)景。 原有監(jiān)控系統(tǒng) showImg(https://segmentfault.com/img/remote/1460000011082384); 整個(gè)系統(tǒng)以 Graphite (carbon ...
摘要:有如下模塊源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析源碼解析使用和監(jiān)控和博客從到學(xué)習(xí)介紹從到學(xué)習(xí)上搭建環(huán)境并構(gòu)建運(yùn)行簡(jiǎn)單程序入門從到學(xué)習(xí)配置文件詳解從到學(xué)習(xí)介紹從到學(xué)習(xí)如何自 Flink Metrics 有如下模塊: Flink Metrics 源碼解析 —— Flink-metrics-core Flink Metrics 源碼解析 —— Flink-metr...
摘要:可行工具圖為上監(jiān)控到的應(yīng)用程序響應(yīng)時(shí)間和吞吐量平均負(fù)載第二個(gè)廣泛使用的衡量指標(biāo)就是服務(wù)器的平均負(fù)載。率和中止時(shí)間垃圾回收器行為異常,是導(dǎo)致應(yīng)用吞吐量和響應(yīng)時(shí)間突然下降的主要原因之一。 在某個(gè)重大發(fā)布之后,都需要記錄相應(yīng)的指標(biāo),本文介紹了最重要的幾個(gè) Java 性能指標(biāo),包括響應(yīng)時(shí)間和平均負(fù)載等。為理解應(yīng)用程序在生產(chǎn)環(huán)境中如何運(yùn)行,就需要遵循一些 Java 性能指標(biāo)。 在以前,當(dāng)軟件被發(fā)...
摘要:前言在資源審計(jì)和計(jì)費(fèi)這塊,容器和虛機(jī)有很大區(qū)別。支持諸多輸出,稱為。所以本文主要講如何為增加。實(shí)際上,基于增加并且更改,也可以做到,只不過需要裝一些包指令,結(jié)果就是鏡像變大。實(shí)際運(yùn)行日志截圖由于的出色的寫入性能,運(yùn)行非常穩(wěn)定。 前言 在k8s資源審計(jì)和計(jì)費(fèi)這塊,容器和虛機(jī)有很大區(qū)別。相對(duì)虛機(jī)來講,容器不容易實(shí)現(xiàn)。資源指標(biāo)收集可以采用heapster,也可以用prometheus。之前文...
閱讀 1085·2023-04-26 02:56
閱讀 23612·2021-11-23 09:51
閱讀 1980·2021-09-26 10:14
閱讀 3074·2019-08-29 13:09
閱讀 2211·2019-08-26 13:29
閱讀 640·2019-08-26 12:02
閱讀 3627·2019-08-26 10:42
閱讀 3066·2019-08-23 18:18