原文地址: http://www.micmiu.com/enterprise-app/snmp/snmp-jrobin-core-demo/
最近接触一个流量统计和网管的系统,对相关信息和技术做了一些了解和学习,在此记录,以供自己日后回顾,同时也方便给刚接触的TX们一些参考。
MRTG(Multi Router Traffic Grapher,MRTG),相信接触过网络管理的人,应该不会对它陌生的。MRTG是比较早的技术了,后来在此基础上发展了RRD技术,相比MRTG而言更加灵活方便。
JRobin(基于LGPL授权的开源技术)就是RRD的一个Java实现的版本。JRobin支持在RRD(Round Robin Database)上的所有标准操作:CREATE, UPDATE, FETCH, LAST, DUMP, XPORT和GRAPH。JRobin的API适合于那些熟悉RRDTool的概念与逻辑,但更喜欢使用纯Java实现的人。如果你提供相同的数据给RRDTool与JRobin,你将会得到相同的结果与图形。
ps:JRobin的官网:
http://oldwww.jrobin.org/
http://www.jrobin.org/index.php/Main_Page
先从Core API 开始了解学习如何定义RRD模板、如何创建RRD文件、如何获取RrdDb、如何将RRD文件和XML之间转换以及如何从RRD文件里读取数据等基础内容,下面是学习时写的一些测试代码:TestCoreRrd.java
1 |
package com.snmp.jrobin; |
2 |
3 |
import org.jrobin.core.DsDef; |
4 |
import org.jrobin.core.DsTypes; |
5 |
import org.jrobin.core.FetchData; |
6 |
import org.jrobin.core.FetchRequest; |
7 |
import org.jrobin.core.RrdDb; |
8 |
import org.jrobin.core.RrdDef; |
9 |
import org.jrobin.core.Sample; |
10 |
import org.jrobin.core.Util; |
11 |
12 |
/** |
13 |
* JRobin Core学习 |
14 |
* @author Michael sun |
15 |
*/ |
16 |
public class TestCoreRrd { |
17 |
/** |
18 |
* @param args |
19 |
*/ |
20 |
public static void main(String[] args) { |
21 |
// 2010-10-01:1285862400L 2010-11-01:1288540800L |
22 |
long startTime = Util.getTimestamp( 2010 , 10 - 1 , 1 ); |
23 |
long endTime = Util.getTimestamp( 2010 , 11 - 1 , 1 ); |
24 |
25 |
TestCoreRrd test = new TestCoreRrd(); |
26 |
String rootPath = "d:/test/jrobin/" ; |
27 |
String rrdName = "demo_flow.rrd" ; |
28 |
// 测试创建RrdDef |
29 |
RrdDef rrdDef = test.createRrdDef(rootPath, rrdName, startTime); |
30 |
// 测试创建RRD文件 初始数据 |
31 |
test.createRRDInitData(startTime, endTime, rootPath, rrdName, rrdDef); |
32 |
// 测试获取RrdDb的方法 |
33 |
test.getRrdDbMethod(rootPath); |
34 |
// 测试FetchData获取RRD |
35 |
test.fetchRrdData(rootPath, rrdName); |
36 |
} |
37 |
38 |
/** |
39 |
* 创建RRDDef |
40 |
*/ |
41 |
private RrdDef createRrdDef(String rootPath, String rrdName, long startTime) { |
42 |
try { |
43 |
44 |
String rrdPath = rootPath + rrdName; |
45 |
RrdDef rrdDef = new RrdDef(rrdPath, startTime - 1 , 300 ); |
46 |
// DsTypes: GAUGE COUNTER DERIVE ABSOLUTE |
47 |
DsDef dsDef = new DsDef( "input" , DsTypes.DT_COUNTER, 600 , 0 , |
48 |
Double.NaN); |
49 |
rrdDef.addDatasource(dsDef); |
50 |
51 |
rrdDef.addDatasource( "output" , DsTypes.DT_COUNTER, 600 , 0 , |
52 |
Double.NaN); |
53 |
54 |
rrdDef.addArchive( "AVERAGE" , 0.5 , 1 , 600 ); |
55 |
rrdDef.addArchive( "AVERAGE" , 0.5 , 6 , 700 ); |
56 |
rrdDef.addArchive( "AVERAGE" , 0.5 , 24 , 797 ); |
57 |
rrdDef.addArchive( "AVERAGE" , 0.5 , 288 , 775 ); |
58 |
rrdDef.addArchive( "MAX" , 0.5 , 1 , 600 ); |
59 |
rrdDef.addArchive( "MAX" , 0.5 , 6 , 700 ); |
60 |
rrdDef.addArchive( "MAX" , 0.5 , 24 , 797 ); |
61 |
rrdDef.addArchive( "MAX" , 0.5 , 288 , 775 ); |
62 |
63 |
// RRD file definition is completed |
64 |
65 |
rrdDef.exportXmlTemplate(rootPath + rrdName + "_template.xml" ); |
66 |
System.out.println( "[RrdDef Template export xml success]" ); |
67 |
68 |
return rrdDef; |
69 |
} catch (Exception e) { |
70 |
e.printStackTrace(); |
71 |
return null ; |
72 |
} |
73 |
} |
74 |
75 |
/** |
76 |
* 通过RrdDef创建RRD文件并初始化数据 |
77 |
*/ |
78 |
private void createRRDInitData( long startTime, long endTime, |
79 |
String rootPath, String rrdName, RrdDef rrdDef) { |
80 |
try { |
81 |
82 |
RrdDb rrdDb = new RrdDb(rrdDef); |
83 |
// / by this point, rrd file can be found on your disk |
84 |
85 |
// 模拟一些测试数据 |
86 |
//Math.sin(2 * Math.PI * (t / 86400.0)) * baseval; |
87 |
int baseval = 50 ; |
88 |
for ( long t = startTime; t < endTime; t += 300 ) { |
89 |
Sample sample = rrdDb.createSample(t); |
90 |
double tmpval = Math.random() * baseval; |
91 |
double tmpval2 = Math.random() * baseval; |
92 |
sample.setValue( "input" , tmpval + 50 ); |
93 |
sample.setValue( "output" , tmpval2 + 50 ); |
94 |
sample.update(); |
95 |
} |
96 |
System.out.println( "[RrdDb init data success]" ); |
97 |
System.out.println( "[Rrd path]:" + rrdDef.getPath()); |
98 |
99 |
// rrdDb.dumpXml(rootPath + rrdName + "_rrd.xml") |
100 |
rrdDb.exportXml(rootPath + rrdName + ".xml" ); |
101 |
102 |
// If your RRD files are updated rarely, open them only when |
103 |
// necessary and close them as soon as possible. |
104 |
rrdDb.close(); |
105 |
106 |
System.out.println( "[RrdDb export xml success]" ); |
107 |
} catch (Exception e) { |
108 |
e.printStackTrace(); |
109 |
110 |
} |
111 |
} |
112 |
113 |
/** |
114 |
* 除根据RrdDef以外获取RrdDb的其他方法 |
115 |
*/ |
116 |
private void getRrdDbMethod(String rootPath) { |
117 |
try { |
118 |
119 |
// 根据RRD文件获取RrdDb |
120 |
String rrdFullPath = rootPath + "demo_flow.rrd" ; |
121 |
RrdDb rrdDb = new RrdDb(rrdFullPath); |
122 |
System.out.println( "[info:]" + rrdDb.getInfo() + "[path:]" |
123 |
+ rrdDb.getPath()); |
124 |
rrdDb.close(); |
125 |
126 |
// 根据XML文件获取RrdDb |
127 |
rrdDb = new RrdDb(rootPath + "copy.rrd" , rootPath |
128 |
+ "demo_flow_rrd.xml" ); |
129 |
System.out.println( "[info:]" + rrdDb.getInfo() + "[path:]" |
130 |
+ rrdDb.getPath()); |
131 |
rrdDb.close(); |
132 |
} catch (Exception e) { |
133 |
e.printStackTrace(); |
134 |
} |
135 |
} |
136 |
137 |
/** |
138 |
* |
139 |
*/ |
140 |
private void fetchRrdData(String rootPath, String rrdName) { |
141 |
try { |
142 |
// open the file |
143 |
RrdDb rrd = new RrdDb(rootPath + rrdName); |
144 |
145 |
// create fetch request using the database reference |
146 |
FetchRequest request = rrd.createFetchRequest( "AVERAGE" , Util |
147 |
.getTimestamp( 2010 , 10 - 1 , 1 ), Util.getTimestamp( 2010 , |
148 |
10 - 1 , 2 )); |
149 |
150 |
System.out.println( "[requet dump:]" + request.dump()); |
151 |
152 |
// filter the datasources you really need |
153 |
// String[] filterDataSource = { "input", "output" }; |
154 |
// request.setFilter(filterDataSource); |
155 |
156 |
// if you want only the "input" datasource use: |
157 |
// request.setFilter("input"); |
158 |
159 |
// execute the request |
160 |
FetchData fetchData = request.fetchData(); |
161 |
int columnCount = fetchData.getColumnCount(); |
162 |
int rowCount = fetchData.getRowCount(); |
163 |
long [] timestamps = fetchData.getTimestamps(); |
164 |
System.out.println( "[data column count:]" + columnCount); |
165 |
System.out.println( "[data row count:]" + rowCount); |
166 |
167 |
// System.out.println("[fetch data dump:]" + fetchData.dump()); |
168 |
// 循环获取数据 |
169 |
double [][] values = fetchData.getValues(); |
170 |
StringBuffer buffer = new StringBuffer( "" ); |
171 |
for ( int row = 0 ; row < rowCount; row++) { |
172 |
buffer.append(timestamps[row]); |
173 |
buffer.append( ": " ); |
174 |
for ( int dsIndex = 0 ; dsIndex < columnCount; dsIndex++) { |
175 |
buffer.append(Util.formatDouble(values[dsIndex][row])); |
176 |
buffer.append( " " ); |
177 |
} |
178 |
buffer.append( "\n" ); |
179 |
} |
180 |
System.out.println( "[fetch data display :]\n" + buffer); |
181 |
} catch (Exception e) { |
182 |
e.printStackTrace(); |
183 |
} |
184 |
185 |
} |
186 |
} |
RRD定义的模板导出XML:
1 |
< rrd_def > |
2 |
< path >d:/test/jrobin/demo_flow.rrd</ path > |
3 |
< step >300</ step > |
4 |
< start >1285862399</ start > |
5 |
< datasource > |
6 |
< name >input</ name > |
7 |
< type >COUNTER</ type > |
8 |
< heartbeat >600</ heartbeat > |
9 |
< min >+0.0000000000E00</ min > |
10 |
< max >U</ max > |
11 |
</ datasource > |
12 |
< datasource > |
13 |
< name >output</ name > |
14 |
< type >COUNTER</ type > |
15 |
< heartbeat >600</ heartbeat > |
16 |
< min >+0.0000000000E00</ min > |
17 |
< max >U</ max > |
18 |
</ datasource > |
19 |
< archive > |
20 |
< cf >AVERAGE</ cf > |
21 |
< xff >+5.0000000000E-01</ xff > |
22 |
< steps >1</ steps > |
23 |
< rows >600</ rows > |
24 |
</ archive > |
25 |
< archive > |
26 |
< cf >AVERAGE</ cf > |
27 |
< xff >+5.0000000000E-01</ xff > |
28 |
< steps >6</ steps > |
29 |
< rows >700</ rows > |
30 |
</ archive > |
31 |
< archive > |
32 |
< cf >AVERAGE</ cf > |
33 |
< xff >+5.0000000000E-01</ xff > |
34 |
< steps >24</ steps > |
35 |
< rows >797</ rows > |
36 |
</ archive > |
37 |
< archive > |
38 |
< cf >AVERAGE</ cf > |
39 |
< xff >+5.0000000000E-01</ xff > |
40 |
< steps >288</ steps > |
41 |
< rows >775</ rows > |
42 |
</ archive > |
43 |
< archive > |
44 |
< cf >MAX</ cf > |
45 |
< xff >+5.0000000000E-01</ xff > |
46 |
< steps >1</ steps > |
47 |
< rows >600</ rows > |
48 |
</ archive > |
49 |
< archive > |
50 |
< cf >MAX</ cf > |
51 |
< xff >+5.0000000000E-01</ xff > |
52 |
< steps >6</ steps > |
53 |
< rows >700</ rows > |
54 |
</ archive > |
55 |
< archive > |
56 |
< cf >MAX</ cf > |
57 |
< xff >+5.0000000000E-01</ xff > |
58 |
< steps >24</ steps > |
59 |
< rows >797</ rows > |
60 |
</ archive > |
61 |
< archive > |
62 |
< cf >MAX</ cf > |
63 |
< xff >+5.0000000000E-01</ xff > |
64 |
< steps >288</ steps > |
65 |
< rows >775</ rows > |
66 |
</ archive > |
67 |
</ rrd_def > |
RRD文件转换成XML文件的片段:
1 |
< rrd > |
2 |
<!-- JRobin, version 0.1 --> |
3 |
< version >0001</ version > |
4 |
<!-- Seconds --> |
5 |
< step >300</ step > |
6 |
<!-- Sun Oct 31 23:55:00 CST 2010 --> |
7 |
< lastupdate >1288540500</ lastupdate > |
8 |
< ds > |
9 |
< name >input</ name > |
10 |
< type >COUNTER</ type > |
11 |
< minimal_heartbeat >600</ minimal_heartbeat > |
12 |
< min >+0.0000000000E00</ min > |
13 |
< max >NaN</ max > |
14 |
<!-- PDP Status --> |
15 |
< last_ds >+6.9973544356E01</ last_ds > |
16 |
< value >+0.0000000000E00</ value > |
17 |
< unknown_sec >0</ unknown_sec > |
18 |
</ ds > |
19 |
< ds > |
20 |
< name >output</ name > |
21 |
< type >COUNTER</ type > |
22 |
< minimal_heartbeat >600</ minimal_heartbeat > |
23 |
< min >+0.0000000000E00</ min > |
24 |
< max >NaN</ max > |
25 |
<!-- PDP Status --> |
26 |
< last_ds >+9.4423065918E01</ last_ds > |
27 |
< value >+0.0000000000E00</ value > |
28 |
< unknown_sec >0</ unknown_sec > |
29 |
</ ds > |
30 |
< rra > |
31 |
< cf >AVERAGE</ cf > |
32 |
<!-- 300 seconds --> |
33 |
< pdp_per_row >1</ pdp_per_row > |
34 |
< xff >+5.0000000000E-01</ xff > |
35 |
< cdp_prep > |
36 |
< ds > |
37 |
< value >NaN</ value > |
38 |
< unknown_datapoints >0</ unknown_datapoints > |
39 |
</ ds > |
40 |
< ds > |
41 |
< value >NaN</ value > |
42 |
< unknown_datapoints >0</ unknown_datapoints > |
43 |
</ ds > |
44 |
</ cdp_prep > |
45 |
< database > |
46 |
<!-- Fri Oct 29 22:00:00 CST 2010 / 1288360800 --> |
47 |
< row > |
48 |
< v >+1.4316557626E07</ v > |
49 |
< v >+1.2619069495E-01</ v > |
50 |
</ row > |
51 |
<!-- Fri Oct 29 22:05:00 CST 2010 / 1288361100 --> |
52 |
< row > |
53 |
< v >+1.4063324411E-02</ v > |
54 |
< v >+1.4316557534E07</ v > |
55 |
</ row > |
56 |
<!-- 省略部分信息--> |
57 |
........................... |
58 |
</ database > |
59 |
</ rra > |
60 |
<!-- 省略部分信息--> |
61 |
............................... |
62 |
</ rrd > |