如何深入理解 StatsD 与 Graphite ?(如何深入理解把握教材)

网友投稿 678 2022-09-12

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

如何深入理解 StatsD 与 Graphite ?(如何深入理解把握教材)

StatsD

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 + "\n"; statString += 'stats_counts.' + key + ' ' + value + ' ' + ts + "\n"; 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 + "\n"; message += 'stats.timers.' + key + '.upper_' + clean_pct + ' ' + maxAtThreshold + ' ' + ts + "\n"; message += 'stats.timers.' + key + '.sum_' + clean_pct + ' ' + sum + ' ' + ts + "\n";}sum = cumulativeValues[count-1];mean = sum / count;message += 'stats.timers.' + key + '.upper ' + max + ' ' + ts + "\n";message += 'stats.timers.' + key + '.lower ' + min + ' ' + ts + "\n";message += 'stats.timers.' + key + '.count ' + count + ' ' + ts + "\n";message += 'stats.timers.' + key + '.sum ' + sum + ' ' + ts + "\n";message += 'stats.timers.' + key + '.mean ' + mean + ' ' + ts + "\n";statString += message;numStats += 1;} }

如果在默认的 flush interval 内,你将下列计数器 values 传给 StatsD:

450120553994334844675496

StatsD 将会计数下面的 values:

mean_90 496upper_90 844sum_90 3472upper 994lower 120count 8sum 4466mean 558.25

Gauges

一个 guage 代表着时间段内某点的任意 vaule,是 StatsD 中最简单的类型。你可以给它传任意值,它会传给后端。Gauge stats 的源码只有短短四行。

for (key in gauges) { statString += 'stats.gauges.' + key + ' ' + gauges[key] + ' ' + ts + "\n"; numStats += 1;}

给 StatsD 传一个数字,它会不经处理地将该数字传到后端。值得注意的是,在一个 flush interval 内,只有 gauge 最后的值会传送到后端。因此,如果你在一个 flush interval 内,将下面的 gauge 值传给 StatsD:

643754583

会传到后端的值只有583而已。该 gauge 的值会一直存储在内存中,直到 flush interval 结束才传值。

Graphite

现在,我们已经了解数据是怎样从 StatsD 传出来的,让我们看看它在 Graphite 里是如何存储并处理的。

总览

Graphite 存储数值型带有时间序列的数据。Graphite 按需绘制图表。

Graphite 由三部分组成:

Graphite 当做时间序列数据的格式如下:

存储方案

Graphite 采用可配置的存储方案用以定义所存数据的留存率。它会给数据路径匹配特定的模式,从而决定所存数据的频率和来历。

以下配置示例截取自 StatsD 文档。

[stats]pattern = ^stats\..*retentions = 10:2160,60:10080,600:262974

该示例表明,匹配上述样式的数据都会套用这些留存。留存的格式为 frequency: history。所以,该配置允许我们将10秒钟的数据存储6个小时,1分钟的数据存储1周,10分钟的数据存储5年。

在 Graphite 显示计时器

了解了这么多,我们来看看一个简单的 ruby 脚本,该脚本能收集 HTTP 请求的时间。

让我们看看该数据生成的 Graphite 图。该数据来自 2 分钟前,而 elapsed_time 则来自前面的脚本。

图像生成

Render URL

下面图片的 Render URL

Graphite 生成的图片

JSON-data

Render URL

下面 JSON-data 的 Render URL

来自 Graphite 的 JSON-output

在下面的结果中,我们可以查看来自 Graphite 的源数据。这些数据来自12个不同的数据点,也即 StatsD 10 秒 flush internal 的两分钟。Graphite 绘制数据就是如此简单。

在 Graphite 绘制 gauge 图像

下面的简单脚本能将 gauge 传送给 StatsD,模拟用户注册的过程。

#!/usr/bin/env rubyrequire './statsdclient.rb'Statsd.host = 'localhost' Statsd.port = 8125user_registrations = 1while true user_registrations += Random.rand 128 Statsd.gauge('user_registrations', user_registrations) sleep 10end

图像显示——用户注册数量

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 读取数据。

上一篇:强者先行 | 同时签约 9 家互联网公司(与强者同行)
下一篇:DIY Ruby CPU 分析——Part I
相关文章

 发表评论

暂时没有评论,来抢沙发吧~