一、RRD及RRDTool简介
Round Robin Database 环状数据库,是一种处理定量数据、以及当前元素指针的技术。没有起点,没有终点,过来一段时间,所有可用的位置都会被用过,该循环过程会自动重用原来的位置。这样,数据集不会增大,并且不需要维护。
基于这种特点,RRD数据库用于许多记录时间序列的数据系统,如气象、速度、电压、输出量、网络流量、机场附近的噪音等级。
RRDTool就是操作这个数据库的工具,它向RRD数据库存储数据、从RRD数据库中提取数据。计算平均值、峰值,创建用于在Web浏览器中显示的PNG格式的图像。
RRD优点:
1、基于文件系统,与LDAP结合。
2、自定义数据统计周期大小,创建数据库时即固定文件大小,不需要维护。
3、一个数据库可自定义多个数据源和多种统计方式,一个数据库可生成多种统计图表,多个数据库可合并一个图表。
4、可生成xml数据库定义模板和图表定义模板,可将数据导入导出xml文件,扩展性强,应用广,兼容性强。
5、轻量级文件型数据库,需要什么保存什么,减轻已有数据库服务器压力。
6、基于java开源工具,有pool、Backends、Plottable等机制可以使用和扩展。
二、Cacti监控系统原理
步骤详解:
1、定时采集数据:使用agent客户端代理或网络协议采集被监控服务器数据。
2、存储数据:在监控服务器安装net_snmp工具将采集的数据保存至rrd数据库。
3、用户配置设备:用户使用cacti、opennms、nagios等监控工具配置服务器集群、生成图表的监控项等。
4、保存配置数据至开源数据库。
5、监控工具绘制图表:在用户查看时生成,使用rrdtool工具绘制性能统计图表。
6、展现图表。
三、基于RRD监控系统UI模块设计
步骤详解:
1、数据采集:使用已有的基于日志和ftp数据采集。
2、查看数据库模板并分配数据:每获取一次采集数据,对数据存储消息服务发送一次消息,由该服务查看数据库中该数据相关RRD模板。如采集一条sso登录用户数据,对应用户登录统计(年/月/日)、金牌会员登录统计(年/月)、用户停留时长统计(月)3个RRD模板,即这条数据将更新至这3个RRD数据库中。
3、存储数据:将对应的采集数据更新至RRD库。
4、与Nagios集成:大多数网络监控系统如Nagios,都采用RRD保存监控数据,JRobin可以直接读取这些RRD文件,并生成图表。
5、用户配置统计项:UI提供用户自定义配置统计项功能,列出系统监控点和支持统计算法,供用户选择并生成RRD模板和对应的RRDGraph模板。
6、将用户自定义的RRD模板和RRDGraph模板以一对多的形式与关联的监控数据点对应保存至数据库。如用户配置sso登录用户监控点,自定义了3个RRD模板,和6个RRDGraph模板。
7、根据对应RRDGraph模板生成图表。
8、展现给用户。
四、JRobin语法
(一)创建数据库
1、建立一个名为target.rrd的资料库
RrdDef rrdDef = new RrdDef(rrdPath);
2、开始时间(1'023'654'125)是由01-01-1970起算的秒数
rrdDef.setStartTime()
3、Step 300 说明每300秒是一个周期.完整程序稿(wrapper script)在每一周期都应执行一次,才能在每一周期内更新资料库.若要更新资料库,更新时间(秒)亦须定义;且更新时间必须比开始时间大.
rrdDef.setStep()
4、DS (Data Source)是对应到被监视设备参数的真实变数,其语法如下:
DS:variable_name:DST:heartbeat:min:max
rrdDef.addDatasource("cpu123", "GAUGE", 2 * step, 0, Double.NaN);
(1)DS:关键字,表示这是一个资料的定义
(2)variable_name(变数名):资料库中存放资料的名称;可依需要定义多个 DS.在每一个 step 周期内会产生一组新的DS值,用以更新资料库.这个值也称为Primary Data Point (PDP).在上例,每 300 秒产生一个新的 PDP 值.
注:如果无法刚好在每 300 秒产生一个值,RRDtool 会自动补偿修正.
(3)DST (Data Source Type):定义 DS 的型态(Type);说明如下:
COUNTER :贮存在一个周期内,值之改变率(假设值是一直增加的).路由器的Traffic counters是个使用counter型态的好例子.
DERIVE :同 COUNTER,但容许有负值.如果你想观察在你伺服器上的硬碟*空间的变化率,可以使用本型态.
ABSOLUTE:同前,但假设前一周期的值为 0,换句话说,是和前一周期的值的差.
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
(4)heartbeat:在我们的例子中 heartbeat 是 600 秒;如果在300秒内,资料库没有接收到一个新的 PDP 值,它将会再等300秒(共600秒);若还是无法收到任何 PDP 值,将会以 UNKNOWN 存到资料库中.
注:UNKNOWN 在RRDtool具有特殊意义(以 UNKNOWN 表示一个错失掉的值比用 0 或其他的值好).
(5) minimum :上限值.
(6)maximum :下限值.
如果设定了上下限,任何更新值落在范围之外,将以UNKNOWN贮存之.
5、round robin archive (RRA)的宣告,语法如下:
RRA:CF:xff:step:rows
rrdDef.addArchive("AVERAGE", 0.5, 1, 24);
RRA:关键字;.
CF :整合(consolidated)函数;可以是AVERAGE, MINIMUM,MAXIMUM, and LAST等.
xff :未说明;看到的值都是0.5(猜测是offset值).
step :要多少个周期来整合(DS)资料(算是一列).
rows:要收集多少列(开始循环).
consolidated data point(CDP)的概念由此处导入图形(picture)
一个 CDP 是在一个周期内已经经由整合函数处理后的一组PDP.这个 RRA 将保持数个 CDPs 的列.
6、让我们再来看看上面所用的例子:
RRA:AVERAGE:0.5:12:24 /
RRA:AVERAGE:0.5:288:31
第一列的 RRA:
以12个周期(steps)的PDP值,使用整合函数AVERAGEed处理(算是一列);取到24列(rows);从第25列开始循环(覆盖掉第1列).
每一个PDP要300秒,12个PDP要12 * 300 = 3600秒,即1小时.这表示要取得1个CDP (等於12个PDP)的资料需要1小时,24 个CDP需要一天.因此这个RRA需要一天的时间建构.经过24个CDPs,第25个CDP会取代第1个CDP;依次类推.
第二列的 RRA:
贮存31个CDP;每个CDP要一个一天的平均值(288个PDPs,每个300*288 = 24小时);所以这个RRA是一个月的建构周期.
一个单一的资料库可以有很多RRA.如果定义了多个DS,每个个别的RRA将贮存所有DS的值到资料库.例如有一个资料库,有3个DS定义,及有每日,每周及每月的RRA宣告,则每个RRA将分别为3个data sources保存资料.
注意:一个rrd可以有多个DS,定义多个RRA.一个RRA可以记录所有的DS数值
覆盖周期 = (#CDPs stored) * (#PDPs per CDP) * step
概念:
RRD:Round Robin Database 循环数据库
DS:Data Source 数据源
RRA:round robin archive档案库
PDP:Primary Data Point 单元数据点
CDP:consolidated data point整合数据点
(二)生成图表
1、建立数据库图表
RrdGraphDef def = new RrdGraphDef();
2、数据定义
DEF:<vname>=<rrdfile>:<dsname>:<CF>[:step=<step>][:start=<time>][:end=<time>][:reduce=<CF>]
def.datasource(name, file, dsName, consolFunc)
def.setTimePeriod(start, start + 86400);
Name:图表数据源名
File:RRD库路径
dsName:指定RRD数据源名
consolFunc:指定RRD数据源某个CF函数类型
3、变量定义
VDEF:vname=RPN expression
VDEF支持输出最大值、最小值、平均值、当前值等逻辑成像。
def.datasource(name, “MAX:%13.2lf”)
4、数据计算
CDEF:vname=RPN expression
CDEF 支持很多数学运算,甚至还支持简单的逻辑运算 if-then-else ,可以只绘制你所关心的数据。
def.datasource(name, rpn)
Name:将通过CDEF计算过的数据当做图表数据源,重新命名。
Rpn:CDEF数据计算RPN语法语句。
5、图表元素
[-t|--title string] [-v|--vertical-label string]
def.setVerticalLabel("link speed [bits/sec]");
def.setTitle("Leased Line Daily Traffic");
Title:标题
Vertical-label:左侧说明文字
6、打印元素
(1)LINE 的方式来绘图
def.line("b", Color.decode("0x22e9"), "min",1);
(2)STACK 方式绘图
def.area("out8", Color.GREEN, "output traffic");
(3)基准线
graphDef.rule(100, Color.BLUE, "Maximum allowed");
graphDef.vrule(100, Color.BLUE, "Maximum allowed");
Rule:横向基线
Vrule:纵向基线
(4)数字报表
def.comment(" ")
def.comment("Maximum ")
def.comment("Average ")
def.comment("Minimum ")
def.comment("95th percentile ")
def.gprint("ds0max", "MAXIMUM", "avgIn=@2 @sbits/sec");
def.gprint("ds0avg", "AVERAGE", "avgIn=@2 @sbits/sec");
def.gprint("ds0min", "MINIMUM", "avgIn=@2 @sbits/sec");
def.gprint("ds0pct", "PERCENT", "avgIn=@2 @sbits/sec");
Comment:报表列
Gprint:报表单元数据
7、生成图片
RrdGraph g = new RrdGraph(def);
g.saveAsPNG(PNG, 400, 200);
(三)RRD文件大小
算法:
TOTAL SIZE = 64 + 128 * N + 56 * M + 20 * N * M + 8 * N * R
N = number of datasources
M = number of archives
R = total number of rows in all archives
如:定义了2个数据源,8个档案库的RRD文件
DS:in:GAUGE:600:U:U
DS:out:GAUGE:600:U:U
RRA:AVERAGE:0.5:1:600
RRA:AVERAGE:0.5:6:700
RRA:AVERAGE:0.5:24:775
RRA:AVERAGE:0.5:288:797
RRA:MAX:0.5:1:600
RRA:MAX:0.5:1:700
RRA:MAX:0.5:1:775
RRA:MAX:0.5:1:797
(5分钟一次记录,分别统计了2天、半月、2月、2年)
需占用的空间是:
N = 2
M = 8
R = (600 + 700 + 775 + 797) * 2 = 5744
TOTAL SIZE = 64 + 128 * 2 + 56 * 8 + 20 * 2 * 8 + 8 * 2 * 5744
= 92992 bytes.
五、实现自定义配置
(一)导出RRD定义模板
RrdDef rrdDef = new RrdDef("test.rrd");
rrdDef.exportXmlTemplate()
(二)使用模板创建RRD库
RrdDefTemplate t = new RrdDefTemplate(new File("template.xml"));
t.setVariable("path", "demo/test.rrd");
RrdDef def = t.getRrdDef();
RrdDb rrd = new RrdDb(def);
rrd.close();
(三)导出制图模板
RrdGraphDef gDef = new RrdGraphDef();
gDef.exportXmlTemplate();
(四)使用模板制图
RrdGraphDefTemplate t = new RrdGraphDefTemplate(new File("template.xml"));
t.setVariable("start", new GregorianCalendar(2004, 2, 25));
t.setVariable("end", new GregorianCalendar(2004, 2, 26));
t.setVariable("title", "My first template based graph");
RrdGraphDef gdef = t.getRrdGraphDef();
RrdGraph g = new RrdGraph(gdef);
g.saveAsPNG("graph.png");
六、与nagios集成
(一)导出RRD数据
RrdDef rrdDef = new RrdDef("test.rrd");
RrdDb rrdDb = new RrdDb(rrdDef);
rrdDb.exportXml();
(二)导出RRDGraph数据
RrdGraphDef gDef = new RrdGraphDef();
RrdGraph graph = new RrdGraph(gDef);
ExportData data = graph.getExportData();
data.exportXml();
七、特殊功能
(一)PPN:
RPN 是 Reverse Polish Notation 的缩写,是用于表示算术运算和逻辑运算的一种语法格式。可对数据进行算术操作、比较、条件操作、排序、替换等运算。
def.datasource(“traffic_out”, “ >10Mb”)
(二)Pool
JRobin并不加载所有RRD文件内容到内存,而只保存RRD文件的数据源、归档定义、内部状态和变量定义。当多个线程访问同一个RRD文件时,将会只创建一个RRD对象保存在公共池中。
RrdDbPool pool = RrdDbPool.getInstance();
RrdDb rrdDb = pool.requestRrdDb(path);
pool.release(rrdDb);
(三)Lock
提供锁机制,防止不同JRobin对象同时访问一个RRD文件读写脏数据。
RrdDb.setLockMode(RrdDb.WAIT_IF_LOCKED);
RrdDb.setLockMode(RrdDb.EXCEPTION_IF_LOCKED);
RrdDb.setLockMode(RrdDb.NO_LOCKS);
(四)Plottable
使用测绘版可以绘制自定义数据,这样数据可以不从RRD文件中获取。
GregorianCalendar[] timestamps = {
new GregorianCalendar(2004, 2, 1, 0, 0, 0),
new GregorianCalendar(2004, 2, 1, 2, 0, 0),
new GregorianCalendar(2004, 2, 1, 7, 0, 0),
new GregorianCalendar(2004, 2, 1, 14, 0, 0),
new GregorianCalendar(2004, 2, 1, 17, 0, 0),
new GregorianCalendar(2004, 2, 1, 19, 0, 0),
new GregorianCalendar(2004, 2, 1, 23, 0, 0),
new GregorianCalendar(2004, 2, 1, 24, 0, 0)
};
double[] values = { 100, 250, 230, 370, 350, 300, 340, 350 };
LinearInterpolator linear = new LinearInterpolator(timestamps, values);
CubicSplineInterpolator spline = new CubicSplineInterpolator(timestamps, values);
(五)Backends
使用该组件选择数据存储方式,可保存为文件、内存、RAM、数据库。