Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3012043
  • 博文数量: 535
  • 博客积分: 15788
  • 博客等级: 上将
  • 技术积分: 6507
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-07 09:11
文章分类

全部博文(535)

文章存档

2016年(1)

2015年(1)

2014年(10)

2013年(26)

2012年(43)

2011年(86)

2010年(76)

2009年(136)

2008年(97)

2007年(59)

RRD

分类:

2008-06-12 17:38:30

RRD起步1——通过例子理解RRD

RRD数据库的结构与其他的线性结构数据库不同,其他数据库都是以栏或其他参数来定义表格的,这种定义有时候会非常复杂,尤其数据库比较大时。RRDtool数据库主要用于监测,因此结构非常简单,需要被定义的参数是那些拥有值的变量以及这些值的档案。由于与时间关系密切,这里还定义了一些与时间相关的参数。鉴于这种结构,RRDtool数据库的定义还提供了在缺乏更新数据的情况下应采取的特定动作。与RRDtool 数据库相关的一些术语包括:Data Source (DS), heartbeat, Date Source Type (DST), Round Robin Archive (RRA), 以及Consolidation Function (CF)等。

可以用一个例子还很好的解释RRDtool数据库的结构及其相关的术语:
rrdtool create target.rrd \
--start 1023654125 \
--step 300 \
DS:mem:GAUGE:600:0:671744 \
RRA:AVERAGE:0.5:12:24 \
RRA:AVERAGE:0.5:288:31

例子创建了名为target.rrd的数据库,开始时间(1'023'654'125)是距01-01-1970的秒数,在更新数据库时,更新时间必须比开始时间大,而且必须用距01-01-1970的秒数表示。

间隔300秒表示数据库每300秒需要新的数据,用于产生数据的脚本应该每隔这个间隔时间运行以保证及时更新。

DS (Data Source)是与被监测设备的参数相关的实际变量,其语法如下:
DS:variable_name:DST:heartbeat:min:max

DS是关键字,variable_name是参数在数据库中的名字,需要的话,一个数据库中可以有很多DS。每个时间间隔之后,DS的一个新值将提供给数据库用于更新,这个值也被称为Primary Data Point (PDP)。在我们上边的例子中,新的PDP每300秒产生一次。

DST数据源类型定义了DS的类型,供选的参数包括COUNTER, DERIVE, ABSOLUTE, GAUGE。声明为COUNTER的DS将会每隔间隔时间保存数值的变化率,只有变量的数值一直增加才能使用,流经路由器的流量很适合使用COUNTER类型;DERIVE与COUNTER一样,但它允许负值,如果你想查看你的服务器可用空间的变化率,你可能会用到DERIVE;ABSOLUTE也是保存变化率,但它假设前边的数据被置为0,当前数据与前一数据的差异与当前的值是一样的,这样它仅仅存储了当前值与时间间隔的商;GAUGE并不是保存变化率,它存储了数值本身,并没有任何分割计算,服务器的内存消耗是gauge的一个典型例子。各种DST的不同可以用下边的例子来解释:
Values = 300, 600, 900, 1200
Step = 300 seconds
COUNTER DS = 1, 1, 1, 1
DERIVE DS = 1, 1, 1, 1
ABSOLUTE DS = 1, 2, 3, 4
GAUGE DS = 300, 600, 900, 1200

下一个参数是heartbeat.我们的例子中,heartbeat设为600,如果数据库在300秒内没有得到新的PDP,它将把UNKNOWN保存到数据库中,UNKNOWN是RRDtool的一个特殊值,它比假设丢失的值是0或是其他的可能数值要好的多,例如,路由器的流计数器一直在增长,如果一个值丢失了,0而不是UNKNOWN被存储了,这样当下一个值到来的时候,它将会计算当前值与前一值(0)的差值来生成数据,这显然不合适,可见插入UNKNOWN是很重要的。

下边的两个值分别是最小值minimum和最大值maximum,区间内的值将被存储到变量,其他的值将会在变量中存入UNKNOWN。

下一行是声明round robin archive (RRA),语法如下:
RRA:CF:xff:step:rows

RRA是关键字,CF(consolidation function)可以是AVERAGE, MINIMUM, MAXIMUM, 和LAST中的一种。引入一个名词consolidated data point (CDP),它是若干个PDP经过CF(averaged, maximum/minimum value or last value)作用的结果,RRA将会保存多行的CDP。

最后再看看上边的例子,对于第一个RRA,12(间隔)个PDP(DS变量)的平均值(AVERAGEed(CF))构造了一个CDP,24(行)这种CDP被存档。每个PDP300秒产生,12个PDP代表300秒×12=1小时,24个这样的CDP代表1天,这意味着:这个RRA每1天得到一次,第25个CDP将代替第1个CDP;第二个RRA保存了31个CDP,每个CDP代表了一天的平均值(288个PDP),因此这个RRA是一个月的档案,一个数据库可以有多个档案,如果有多个DS,每个单独的RRA将会保存所有DS的数据,例如一个数据库声明了3个DS,以及天、星期、月、年4个RRA,那么每个RRA都将从3个变量中获取数据。

PS:个人理解,DS仅仅是变量,提供给DS的(数据)——PDP不会保存在数据库中,存档的是CDP——CF处理过的PDP,当然如果某个RRA的step设为1,PDP对于这个RRA的动作就是直接存档,例如:

RRA:AVERAGE:0:1:600。每个PDP作为一个CDP存档,保存600行。所以你能够从数据库中取回的数据是CDP(环形的会覆盖的哦),PDP如果对所有的RRA(的CDP)都没贡献了,估计就自动释放了。

RRD起步2——神奇绘图

RRDtool的一个重要特性就是其绘图功能,graph命令内在的调用fetch命令从数据库中提取数据,根据命令行定义的参数进行绘图。一幅图片可以绘制来自同一或不同数据库的多个DS(变量),在绘图之前,通常要对取得的数据进行一些数学处理。举个例子,在SNMP应用中,内存的消耗通常定义为KBytes ,端口流量的定义通常为Bytes,按传统的将其分别改为MBytes和mbps将会更有意义。RRDtool的绘图命令允许进行这样的转换,除了数学计算,RRDtool还能够进行诸如判断大小等逻辑运算,及if/then/else控制结构。如果一个数据库中包含着多个RRA档案,有这样一个问题————RRDtool如何决定从那个档案中选取数据。RRDtool解决这个问题时分几步来做:首先要保证RRA要尽可能的覆盖绘图的时间段;然后去对比RRA的时间粒度以及绘图的时间粒度(比较分辨率resolution ),它会选取分辨率一样或者更高的RRA。利用-r选项你能强制RRDtool使用不同的分辨率,而不是用从图的象素中计算的分辨率。
不同的变量可以用五种不同的类型来绘图,他们是AREA, LINE1, LINE2, LINE3和STACK。AREA 绘制一个实心区域,区域的边界由数据确定;STACK 也是区域绘图,不同的是在区域或是线的上边“叠”起来。另外要注意的是,变量是按照作图命令中定义的顺序作图的,所以STACK一定要在定义AREA/LINE之后,作图中指定的其他参数见作图命令手册



RRD起步3——用脚本包装RRDtool

理解了RRDtool之后该开始用脚本来使用RRDtool 了,网络管理相关的任务是:数据收集、数据存储和数据提取,下边的例子中,使用了“RRD起步1——通过例子理解RRD”中的target.rrd,为了方便,重新show一下:

rrdtool create target.rrd \
--start 1023654125 \
--step 300 \
DS:mem:GAUGE:600:0:671744 \
RRA:AVERAGE:0.5:12:24 \
RRA:AVERAGE:0.5:288:31

数据收集和数据存储通过shell脚本完成,数据的提取和报告的生成通过perl脚本完成。脚本如下:

shell脚本(数据采集,更新数据库)
#!/bin/sh
a=0
while [ "$a" == 0 ]; do
snmpwalk -c public 192.168.1.250 hrSWRunPerfMem > snmp_reply
total_mem=`awk 'BEGIN {tot_mem=0}
{ if ($NF == "KBytes")
{tot_mem=tot_mem+$(NF-1)}
}
END {print tot_mem}' snmp_reply`
# I can use N as a replacement for the current time
rrdtool update target.rrd N:$total_mem
# sleep until the next 300 seconds are full
perl -e 'sleep 300 - time % 300'
done # end of while loop

perl脚本(从数据库提取数据,生成图片和统计信息)
#!/usr/bin/perl -w
# This script fetches data from target.rrd, creates a graph of memory
# consumption on the target (Dual P3 Processor 1 GHz, 656 MB RAM)

# call the RRD perl module
use lib qw( /usr/local/rrdtool-1.0.41/lib/perl ../lib/perl );
use RRDs;
my $cur_time = time(); # set current time
my $end_time = $cur_time - 86400; # set end time to 24 hours ago
my $start_time = $end_time - 2592000; # set start 30 days in the past

# fetch average values from the RRD database between start and end time
my ($start,$step,$ds_names,$data) =
RRDs::fetch("target.rrd", "AVERAGE",
"-r", "600", "-s", "$start_time", "-e", "$end_time");
# save fetched values in a 2-dimensional array
my $rows = 0;
my $columns = 0;
my $time_variable = $start;
foreach $line (@$data) {
$vals[$rows][$columns] = $time_variable;
$time_variable = $time_variable + $step;
foreach $val (@$line) {
$vals[$rows][++$columns] = $val;}
$rows++;
$columns = 0;
}
my $tot_time = 0;
my $count = 0;
# save the values from the 2-dimensional into a 1-dimensional array
for $i ( 0 .. $#vals ) {
$tot_mem[$count] = $vals[$i][1];
$count++;
}
my $tot_mem_sum = 0;
# calculate the total of all values
for $i ( 0 .. ($count-1) ) {
$tot_mem_sum = $tot_mem_sum + $tot_mem[$i];
}
# calculate the average of the array
my $tot_mem_ave = $tot_mem_sum/($count);
# create the graph
RRDs::graph ("/images/mem_$count.png", \
"--title= Memory Usage", \
"--vertical-label=Memory Consumption (MB)", \
"--start=$start_time", \
"--end=$end_time", \
"--color=BACK#CCCCCC", \
"--color=CANVAS#CCFFFF", \
"--color=SHADEB#9999CC", \
"--height=125", \
"--upper-limit=656", \
"--lower-limit=0", \
"--rigid", \
"--base=1024", \
"DEF:tot_mem=target.rrd:mem:AVERAGE", \
"CDEF:tot_mem_cor=tot_mem,0,671744,LIMIT,UN,0,tot_mem,IF,1024,/",\
"CDEF:machine_mem=tot_mem,656,+,tot_mem,-",\
"COMMENT:Memory Consumption between $start_time",\
"COMMENT: and $end_time ",\
"HRULE:656#000000:Maximum Available Memory - 656 MB",\
"AREA:machine_mem#CCFFFF:Memory Unused", \
"AREA:tot_mem_cor#6699CC:Total memory consumed in MB");
my $err=RRDs::error;
if ($err) {print "problem generating the graph: $err\n";}
# print the output
print "Average memory consumption is ";
printf "%5.2f",$tot_mem_ave/1024;
print " MB. Graphical representation can be found at /images/mem_$count.png.";

ps:代码小长了一点r,不懂脚本是无法使用RRDtool的,入门的例子相对都经典一点,希望耐心品味。






阅读(2031) | 评论(0) | 转发(0) |
0

上一篇:有关nfs穿透IPTABLES

下一篇:linux性能优化

给主人留下些什么吧!~~