做過網路管理的人,對於mrtg應該不算陌生。MRTG可以不斷收集來自SNMP的數據,保存這些數據,並且按照日、周、月、年的方式生成4幅圖像及相關說明,很直觀的顯示出要檢測數據的趨勢信息。
MRTG是比較早的技術了,後來又出現了RRD技術,是在MRTG技術的基礎上發展起來的,更加靈活、更加方便。其套用也不在局限在主要監測網路數據上了。你可以通過RRD提供的強大功能收集各種各樣的信息,並且生成更加複雜的圖像。你也可以在自己的應用程式中使用它,因為它提供了豐富接口,方便應用程式調用。
JRobin是RRD的java版本,其原理是一致的。假如你打算監測計算機的CPU使用率,除了查看當前時刻的數據外,你可能也關心計算機在過去的一天、一周,甚至一個月、一年的CPU使用率,也就是以前一段時間的數據。對於這個要求,需要考慮以下一些問題:
1、數據的採集
獲取數據是監測的第一步,根據監測對象的不同,採集數據的方法也不一樣,可以通過SNMP獲取數據、可以通過外部程式獲取數據、可以通過腳本得到數據、也可以採用Java編寫代碼來取得數據。這些提供數據的方式,或者說是程式,可以看成是JRobin的數據源。我們不是時時刻刻的採集數據,出於性能和成本的考慮,通常在每次採集數據之間都會有一個間隔,也就是說在採集一次數據後,等待幾秒或幾分鐘,然後再次採集數據,將這些多次採集的離散數據用圖像方式展示出來,就成了好看直觀的曲線。MRTG的採集間隔是300秒,RRD較為靈活,可以以秒為單位自由設定。
2、數據的保存
在每次採集數據後,我們可以將這些數據和採集數據的時刻保存下來,這樣方便以後繪製圖像。假如每300秒採集一次數據,那么一天需要採集288次數據。如果打算保存一年的數據,那么數據的個數就是 365 * 288。這樣的數據不算多,但是沒有大多必要,因為我們對數據關心的程度與採集數據的時間遠近成比例,越近的數據越關心。另外,當把這些數據顯示在固定大小的圖像上時,並不是數據越多就越清晰。
JRobin採用了所謂的RRD的存儲方式。比如,我們打算用四個圖像顯示一日、一周、一月和一年內的數據,那么我們可以這么保存數據:
(1)保存最近的288個數據,也就是最近一天的數據;
(2)每7個數據保存一個,保存288個,也就是最近一周時間內的的一些數據;
(3)每30個數據保存一個,保存288個,也就是最近一月時間內的的一些數據;
(4)每365個數據保存一個,保存288個,也就是最近一年時間內的的一些數據。
實際處理時,可能並不是簡單隔幾個保存一個,而是套用一些簡單或複雜的算法。比如或許會對多個數據作一個平均,然後保存為一個。
以這種方式保存數據在JRobin中稱之為歸檔(Archive)。數據源於歸檔的關係可以用下圖來簡要說明:
3、數據格式
為了達到以上目的,JRobin採用自己的格式來保存數據,這種格式是平台無關的,與RRD的格式不兼容。
JRobin還提供強大的繪製圖像的功能,利用其提供的接口,可以很方便的根據數據生成各種樣式圖像。
舉例:
1、定義保存的數據格式,創建數據檔案
long end = Util.getTime(), start = end - 7 * 86400; //截至時間為當前時間,起始時間為一周前
String rrdFile = "demo.rrd";
// 創建數據檔案定義,保存日數據與周數據
RrdDef rrdDef = new RrdDef(rrdFile, start - 1, 300); //數據間隔為300秒
rrdDef.addDatasource("value1", "GAUGE", 600, Double.NaN, Double.NaN); //定義數據源,可以定義多個
//以下定義歸檔數據,即如何保存數據
rrdDef.addArchive("AVERAGE", 0.5, 1, 288); //輸入給數據源的數據每一個都保存下來,保存288筆數據,即保存最近一天的數據
rrdDef.addArchive("AVERAGE", 0.5, 7, 288); //每7筆數據,取平均值,然後保存,保存288筆數據,即保存最近一周的數據
RrdDb rrdDb = new RrdDb(rrdDef); //根據數據定義創建數據檔案
對於月和年的數據,可以用相同的方式處理。
2、更新數據
採用三角函式生成數據。
for (long t = start; t < end; t += 300) {
Sample sample = rrdDb.createSample(t);
sample.setValue("value1", Math.sin(2 * Math.PI * (t / 86400.0)) * 50 + 50);
sample.update();
}
3、生成圖形
String pngFile = "";
RrdGraphDef gDef = null;
//生成最近一天的圖形
pngFile = "demoday.png";
gDef = new RrdGraphDef();
gDef.setFilename(pngFile);
gDef.setWidth(450);
gDef.setHeight(250);
gDef.setImageFormat("png");
gDef.setTimeSpan(end - 86400, end);
gDef.setTitle("JRobin Demo");
gDef.datasource("demo", rrdFile, "value1", "AVERAGE");
gDef.line("demo", Color.GREEN, "real");
gDef.gprint("demo", "MIN", "%5.1lf Min");
gDef.gprint("demo", "AVERAGE", "%5.1lf Avg");
gDef.gprint("demo", "MAX", "%5.1lf Max");
gDef.setSmallFont(new Font("Monospaced", Font.PLAIN, 11));
gDef.setLargeFont(new Font("SansSerif", Font.BOLD, 14));
new RrdGraph(gDef);
//生成最近一周的圖形
pngFile = "demoweek.png";
gDef = new RrdGraphDef();
gDef.setFilename(pngFile);
gDef.setWidth(450);
gDef.setHeight(250);
gDef.setImageFormat("png");
gDef.setTimeSpan(end - 7 * 86400, end);
gDef.setTitle("JRobin Demo");
gDef.datasource("demo", rrdFile, "value1", "AVERAGE");
gDef.line("demo", Color.GREEN, "real");
gDef.gprint("demo", "MIN", "%5.1lf Min");
gDef.gprint("demo", "AVERAGE", "%5.1lf Avg");
gDef.gprint("demo", "MAX", "%5.1lf Max");
//如果需要顯示中文,以下兩條語句比較重要
gDef.setSmallFont(new Font("Monospaced", Font.PLAIN, 11));
gDef.setLargeFont(new Font("SansSerif", Font.BOLD, 14));
new RrdGraph(gDef);
4、生成的圖形如下所示:
(1)按日生成的圖形
(2)按周生成的圖形