Graphite 是一个企业级的监控工具,用 Python 编写,采用 django 框架,sqlite 数据库存储,自有简单文本协议通讯,绘图功能强大。Graphite由多个后端和前端组件组成。后端组件用于存储数值型的时间序列数据。前端组件则用于获取指标项数据并根据情况渲染图表。
一、graphite组成:
1、carbon:
Carbon 实际上是一系列守护进程,组成一个Graphite安装的存储后端。这些守护进程用一个名为 Twisted 的事件驱动网络引擎监听时间序列数据。Twisted框架让 Carbon 守护进程能够以很低的开销处理大量的客户端和流量。/opt/graphite/bin下有三种不同类型的 Carbon 守护进程:
- Cache :接受通过各种协议传输来的指标项数据并以尽可能高的效率将它们写入磁盘;在接收到指标项时,将指标项值缓存在RAM中,并用底层的Whisper库按照指定的时间间隔将这些值写入磁盘。
- Relay :有两个不同的用途:将输入的指标项复制并分区。
- Aggregator : 运行于cache前方,在Whisper中记录指标项之前,缓存这些指标项一段时间。
2、whisper:
一个简单的数据库库,用来存储时间序列数据,在设计上类似于RRD。之后应用程序可以用 create ,update 和fetch 操作获取并操作这些数据。Whisper脚本在/usr/local/bin下存放
3、graphite webapp:
一个Django webapp,使用 Cairo来根据需要呈现图形。
二、carbon和whisper
1、指标项和数据点:
指标项(metric ) 是一种随着时间不断变化的可度量的数量(例如:每秒请求数、CPU使用情况等),数据点(datapoint) 是包含如下信息的三元组:
- 指标项名称
- 度量值
- 时间序列上某个特定的点(通常是一个时间戳)
应用程序在Carbon进程所监听的端口上建立TCP连接,然后以简单平文本格式发送数据点信息到Carbon。客户端应用程序发布指标项的方式可以有多种:
- 通过像 netcat (nc)命令这样的工具,使用 平文本协议 发布
- 使用 pickle协议
- 使用 高级消息队列协议(AMQP)
- 用 函数库 ,如 Dropwizard Metrics库
2、Carbon与Whisper交互,将这些时间序列数据存储到文件系统中:
可以用 whisper-info脚本获取为这些指标项创建的Whisper文件的元数据信息。例如:1
2
3
4
5
6
7
8
9
10
11
12# whisper-info.py /opt/graphite/storage/whisper/PRODUCTION/host/graphite-tutorial/responseTime/p95.wsp
maxRetention: 86400
xFilesFactor: 0.5
aggregationMethod: average
fileSize: 17308
Archive 0
retention: 86400
secondsPerPoint: 60
points: 1440
size: 17280
offset: 28
三、Whisper存储模式和聚合
1、Whisper是如何存储数据的?
首先我们需要理解数据是如何在Whisper文件中存储的。当Whisper文件被创建时,将拥有一个固定的文件尺寸,这个尺寸永远不会再改变。在Whisper文件中可能会包含多个用于不同分辨率的数据点的“ 存储区( bucket ) ”,这些存储区是在配置文件中定义的。
例如:
- 存储器A:拥有10秒分辨率的数据点
- 存储区B:拥有60秒分辨率的数据点
- 存储区C:拥有10分钟分辨率的数据点
每个存储区还拥有一个保留期(retention)属性用于标识该存储区中的数据点应该保留的时间长度。例如:
- 存储区A:分辨率为10秒,保留时间6小时的数据点
- 存储区B:分辨率为60秒,保留时间1天的数据点
- 存储区C:分辨率为10分钟,保留时间7天的数据点
根据上述两种信息,Whisper可以进行一些简单的数学计算,计算出在每个存储区中实际需要保存多少数据点。
- 存储区A:6小时 x 60分钟/小时 x 6数据点/分钟 = 2160点
- 存储区B:1天 x 24小时/天 x 60分钟/小时 x 1数据点/分钟 = 1440点
- 存储区C:7天 x 24小时/天 x 6数据点/小时 = 1008点
如果根据这个存储模式配置创建Whisper文件,该文件大小是56KB。如果在这个文件上执行 whisper-dump.py 脚本,会有如下输出。需要注意的是,一个 archive 对应一个 存储区 , 每点秒数( seconds per point ) 和 点数( points ) 属性则与我们之前的计算相匹配。
2、关于聚合
当数据从一个较高精度的存储区移动到一个较低精度的存储区时,聚合开始发挥作用。让我们以前一个示例中的存储区A和存储区B为例:
存储区A:分辨率为10秒,保留时间6小时的数据点(较高精度)
存储区B:分辨率为60秒,保留时间1天的数据点(较低精度)
我们可能有一个每10秒钟发布一个数据点的应用程序。在存储区A中可以找到6小时之内发布的任何数据点。不过,如果我开始查询6小时之前发布的数据点,就可以在存储区B中找到它们。
3、数据点如何移动到存储区B?
用高精度值除以低精度值,以确定需要聚合的数据点的数量。
l 60秒(存储区B)/10秒(存储区A)= 6个数据点需要聚合
注: Whisper需要较高精度的值能够整除较低精度的值(也就是说,相除的结果必须是整数)。否则聚合的结果可能会不准确。
聚合数据时,Whisper从存储区A中读取6个10秒数据点,然后将函数应用于这些数据点上,得出一个将被存储在存储区B中的60秒数据点。有5个聚合函数选项: average ,sum ,max ,min 和last 。 聚合函数的选择取决于需要处理的数据点。例如,第95百分位的值可能应该用 max 函数聚合。另一方面,对于计数器来说, sum 函数可能更合适。
在聚合数据点时,Whisper还处理了xFilesFactor的概念。xFilesFactor表示为了保证聚合准确,一个存储区必须包含的数据点比率。在我们之前的示例中,Whisper确定了它需要聚合6个10秒数据点。由于网络问题,应用重启等原因,可能只有4个数据点有数据而其他2个数据点是空值。
如果我们的Whisper文件的xFilesFactor是0.5,这意味着只有存在至少50%的数据点时,Whisper才会聚合数据。如果超过50%的数据点为空时,Whisper会创建一个空值聚合。在我们的例子中,即6个数据点中的4个——也就是66%。聚合函数会被应用在非空数据点上,创建聚合值。
你可以将xFilesFactor设置为0到1之间的任意值。值0表示即使只有一个有效数据点,就会执行聚合。值1则表示只有全部的数据点都有效,才会执行聚合。
在前一章节中,我们将所有的样例配置文件拷贝到了 /opt/graphite/conf 文件夹中。控制Whisper文件如何创建的配置文件如下:
/opt/graphite/conf/storage-schemas.conf
/opt/graphite/conf/storage-aggregation.conf
4、默认存储模式(storage-schemas.conf)
存储模式(storage-schemas ) 配置文件由多个条目组成,每个条目中包含一个模式,用于匹配指标项名称和保留期定义。默认情况下,包含两个条目:Carbon和 全部其他 。
carbon 条目匹配以“carbon”字符串开头的指标项名称。默认情况下,Carbon守护进程每60秒发布一次它们自己内部的指标项(这一间隔是可以更改的)。例如,carbon-cache进程会发布指标项,用于标识该进程每分钟创建的指标项文件的数量。保留期的定义则表示数据点每60秒记录一次,并保存90天。1
2
3[carbon]
pattern = ^carbon\.
retentions = 60s:90d
全部其他 条目通过指定带星号的模式捕捉全部其他与 Carbon 无关的指标项。这个保留期的定义表示数据点每60秒记录一次,并保存1天。1
2
3[default_1min_for_1day]
pattern = .*
retentions = 60s:1d
5、默认存储聚合(storage-aggregation.conf)
storage-aggregation 配置文件也是由多个条目组成,其中包括:
- 匹配指标项名称的模式
- 一个xFilesFactor值
- 一个聚合函数
默认情况下,包含4个条目:
以.min结尾的指标项
- 使用min聚合函数
- 至少有10%数据点才可以聚合
以.max结尾的指标项
- 使用max聚合函数
- 至少有10%数据点才可以聚合
以.sum结尾的指标项
- 使用sum聚合函数
- 聚合的前提是至少要有一个数据点
其他指标项
- 使用average聚合函数
- 至少有10%数据点才可以聚合
1 | [min] |
在测试环境下,默认的存储模式和存储聚合函数可以很好的完成任务,不过真正应用到生产指标项时,可能还要修改配置文件。
6)存储模式修改
首先,我会修改Carbon条目。我希望Carbon每60秒记录一次指标项,并将这些指标项保存180天(6个月)。180天之后,我希望能够以10分钟的精度将这些指标项归档,再保存180天。1
2
3[carbon]
pattern = ^carbon\.
retentions = 1min:180d,10min:180d
在Squarespace,我们用 Dropwizard 框架构建RESTful的Web Service。在准生产环境和生产环境中,我们运行了许多这样的服务,所有这些服务都使用 Dropwizard Metrics 库以每10秒一次的速度发布应用和业务指标项。这种10秒一次的数据我会保存3天。3天后,这些数据将被聚合为1分钟数据并保存180天(6个月)。最后,6个月之后,这些数据将被聚合为10分钟数据并再保存180天。
注: 如果我的指标项库以不同的速度发布数据点,我就需要修改保留的定义以匹配新的速度。1
2
3[production_staging]
pattern = ^(PRODUCTION|STAGING).*
retentions = 10s:3d,1min:180d,10min:180d
而Carbon,生产环境或准生产环境之外的指标项,可能只是用于测试。我会将这些数据保存1天并且假设他们会每1分钟发布一次。1
2
3[default_1min_for_1day]
pattern = .*
retentions = 60s:1d
7)修改存储聚合
我会保留默认的存储聚合条目,不过会增加几条新的条目用于以ratio,m1_rate和p95结尾的指标项。
注: 新增的条目需要添加到 default 条目之前。1
2
3
4
5
6
7
8
9
10
11
12
13
14[ratio]
pattern = \.ratio$
xFilesFactor = 0.1
aggregationMethod = average
[m1_rate]
pattern = \.m1_rate$
xFilesFactor = 0.1
aggregationMethod = sum
[p95]
pattern = \.p95$
xFilesFactor = 0.1
aggregationMethod = max
目前为止,你已经完成了Graphite后端的配置以匹配应用程序发布数据点的速率并且已经完全理解数据点是如何在文件系统中存储的。接下来的一章,我们将尝试用graphite-webapp将这些数据可视化。