ganglia自定义图表
http://blog.163.com/digoal@126/blog/static/1638770402014815105622529/



Ganglia 扩展之 Python 实现方法
--作者:Terry,Schubert
1. Ganglia 简介
Ganglia 是 UC Berkeley 发起的一个开源监视项目,设计用于测量数以千计的节点。每台计算机都运行一个收集和发送度量数据(如处理器速度、内存使用量等)的名为 gmond 的守护进程。它将从操作系统和指定主机中收集。接收所有度量数据的主机可以显示这些数据并且可以将这些数据的精简表单传递到层次结构中。正因为有这种层次结构模式,才使得 Ganglia 可以实现良好的扩展。 gmond 带来的系统负载非常少,这使得它成为在集群中各台计算机上运行的一段代码,而不会影响用户性能。
所有这些数据收集会多次影响节点性能。网络中的 “ 抖动( Jitter ) ” 发生在大量小消息同时出现时。我们发现通过将节点时钟保持一致,就可以避免这个问题。
2. Ganglia 扩展能力
基本 Ganglia 安装已经给我们提供了大量有用信息。使用 Ganglia 的插件将给我们提供两种添加更多功能的方法:
- 通过添加带内( in-band )插件。
- 通过添加一些其他来源的带外( out-of-band )欺骗。
Ganglia 安装启动部分参照文档尾部的参考资料,本文档主要讲解 Ganglia 扩展方法的带内 Python 插件实现。
3. 系统准备
实验环境:
l 机器:
n 机型: DELL OPTIPLEX 755
n 操作系统: Linux 2.6.18-164.15.1.el5.centos.plus #1 SMP Wed Mar 17 19:54:20 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux
n 内存: 2G
l Ganglia 部署环境
n Ganglia 根目录: /usr/local/ganglia/ $GANGLIA_ROOT
n Ganglia 配置文件目录: /etc/ganglia/ $GANGLIA_CONF
n Ganglia RRDTool 目录: /var/lib/ganglia/rrds/ $GANGLIA_RRDS
n Ganglia html 目录: /var/www/html/ganglia/ $GANGLIA_WEB
为了方便描述,将采用 $GANGLIA_*** 代表相关环境。
如果安装成功,可发现 $GANGLIA_ROOT/lib64/ganglia/modpython.so ,该文件是 Ganglia Python 扩展的动态库文件,若不存在,则无法支持 python 扩展。
4. Python 扩展的实现
1) 实例描述
我们以实现一个 random_module , random 模块中有两个 metric : random1 和 random2 。我们限定 random的取值为 [RandMin,RandomMax], 其中 random1+random2 互补,即
random2 = RandomMin + RandomMax - random1
2) 需要做的工作
为实现该模块需要做的工作如下:
l 修改配置文件,添加扩展的模块
l 编写扩展模块 Python 代码
l 增加扩展模块的统计表(可省略)
3) 修改配置文件
l gmond.conf 文件
修改 $GANGLIA_CONF/gmond.conf 文件,操作如下:
*********************** Start ****************************
…
modules {
…..
module {
name = "sys_module"
path = "modsys.so"
}
/* 添加 python 主模块 */
module {
name = "python_module"
/* 动态库路径, 完整路径为 $GANGLIA_ROOT/lib64/ganglia/modpython.so */
path = "modpython.so"
/* Python 扩展模块代码存放目录,不存在则创建 */
params="/etc/ganglia/python_modules/"
}
}
include ('/etc/ganglia/conf.d/*.conf')
/* /etc/ganglia/conf.d/ 为 python 扩展模块配置文件存放目录,不存在则创建, gmond 启动时,会 load 所有的配置文件和 python 模块代码
*/
include ('/etc/ganglia/conf.d/*.pyconf')
….
*********************** End ****************************
我们将用 $GANGLIA_PY_CODE 和 $GANGLIA_PY_CONF 来表示 Python 扩展模块的代码和配置文件存放的目录
l random_module.pyconf 文件
vi $GANGLIA_PY_CONF/random_module.pyconf
random_module.pyconf 内容如下:
*********************** Start ****************************
modules {
module {
/* 模块名 $PY_MODULE ,创建 Python 文件路径为 $GANGLIA_PY_CODE/$PY_MODULE.py */
name = "random_module"
language = "python"
/* 参数列表,所有的参数作为一个 dict( 即 map) 传给 python 脚本的 metric_init(params) 函数。
本例中, metric_init 调用时, params={“RandomMax”:”10”,”RandomMin”:”0”}
*/
param RandomMax{
value = 10
}
param RandomMin{
value = 0
}
}
}
/* 需要收集的 metric 列表,一个模块中可以扩展任意个 metric
本例中,我们收集的 metric 为 random1 和 random2.
Title 的内容,作为 metric 图的标题
*/
collection_group {
/* 汇报周期
可选参数:
collect_once – Specifies that the group of static metrics
collect_every – Collection interval (only valid for non-static)
time_threshold – Max data send interval
*/
collect_every = 10 /* 10 s 汇报一次 */
time_threshold = 50
metric {
name = "random1"
title = "test random1" /* Metric name (see “gmond –m”) */
value_threshold = 50 /* Metric variance threshold (send if exceeded) */
}
metric {
name="random2"
title = "test random2"
value_threshold = 50
}
}
*********************** End ****************************
4) 编写模块代码
Ganglia 模块扩展时, Python 脚本主要要实现的函数有:
l metric_init(params):
§ Called once at module initialization time
§ Must return a metric description dictionary or list of dictionaries
Metric definition data dictionary :
d = { ‘name’ : ‘<your_metric_name>’,
‘ call_back’ : <call_back function>,
‘ time_max’ : int(<your_time_max>),
‘ value_type’ : ‘<string | uint | float | double>’,
‘ units’ : ’<your_units>’,
‘ slope’ : ‘<zero | positive | negative | both>’,
‘ format’ : ‘<your_format>’,
‘ description’ : ‘<your_description>’}
Can be a single dictionary or a list of dictionaries
Must be returned from the metric_init() function
§ Any other module initialization can also take place here
l metric_handler() – may have multiple handlers
§ Metric gathering handler
§ Must return a single data value of the same type as specified in the metric_init() function
l metric_cleanup()
§ Called once at module termination time
§ Does not return a value
vi $GANGLIA_PY_CODE /random_module.py
random_module.py 的代码如下:
*********************** Start ****************************
- import random
- random_max = 100
- random_min = 0
- v = 0
- def random1_handler(name):
- global v,random_max,random_min
- v = random.randint(random_min,random_max)
- return v
- def random2_handler(name):
- global v,random_max,random_min
- return random_min+random_max-v
- def metric_init(params):
- global random_max,random_min
- if params:
- if params.has_key("RandomMin"):
- random_min = int(params["RandomMin"])
- if params.has_key("RandomMax"):
- random_max = int(params["RandomMax"])
- tmp = {'name':'random1','call_back':random1_handler,
- 'value_type':'uint','units':'usage',
- 'slope':'both','format':'%u',
- 'description':'test random plugin',
- 'groups':'random'}
- descriptors = [tmp]
- tmp1 = {'name':'random2','call_back':random2_handler,
- 'value_type':'uint','units':'usage',
- 'slope':'both','format':'%u',
- 'description':'test subs plugin',
- 'groups':'random'}
- descriptors.append(tmp1)
- return descriptors
- def metric_cleanup():
- pass
- if __name__=='__main__':
- descriptors = metric_init(None)
- for d in descriptors:
- print "value for %s is %d"%(d['name'],d['call_back'](d['name']))
*********************** End ****************************
完成以上步骤后,重启 gmond ,就可以在 web 界面的节点视图上看到新添的 random1 和 random2 的统计图表
截图如下:
5) 增加统计表
通过以上扩展,我们增加了自定义的 metric ,这些 metric 各自以图表的形式展现,为了方便查找问题,需要将若干 metric 结合起来,显示在同一个表中,这时我们就需要增加相应的统计表展现。该部分实现仅需修改 Ganglia 的web 代码。这里,我们以扩展的 random 模块作为例子,将 random1 和 random2 两个 metric 画在同一张表中。
$GANGLIA_WEB 目录文件组及相关文件说明见附录 1.
为此我们需要做的工作:
l 修改 $GANGLIA_WEB/conf.php 文件,添加要显示的统计表名称 $GRAPH_NAME ,本例中为“ random ”;
l 编写 $GANGLIA_WEB/graph.d/{$GRAPH_NAME}_report.php 文件,并实现函数:
function graph_{$GRAPH_NAME}_report ( &$rrdtool_graph )
l 重启 httpd 服务。
a) 修改 $GANGLIA_WEB/conf.php 文件
Vi $GANGLIA_WEB/conf.php
************************* Start **********************
…
#
# Colors for the load ranks.
#
$load_colors = array(
"100+" => "ff634f",
"75-100" =>"ffa15e",
"50-75" => "ffde5e",
"25-50" => "caff98",
"0-25" => "e2ecff",
"down" => "515151"
);
#
# 添加我们自定义 metric 的颜色,也可以在 random_report.php 中定义
# Colors for the random report graph
#
$random1_color = "0000FF";
$random2_color = "FF0000";
…
#
# Default metric
#
$default_metric = "load_one";
#
# Optional summary graphs
#
#$optional_graphs = array('packet');
# 需要添加的统计表名
$optional_graphs = array('random');
…
************************ End *************************
b) 编写 $GANGLIA_WEB/graph.d/random_report.php 文件
我们可以参考 $GANGLIA_WEB/graph.d/ 目录下已经实现的内容。
Vi $GANGLIA_WEB/graph.d/random_report.php
************************ Start *************************
- <?php
- function graph_random_report ( &$rrdtool_graph ) {
- global $context, //声明全局变量
- $random1_color,
- $random2_color,
- $hostname,
- $range,
- $rrd_dir, // 即$GANGLIA_RRDS
- $size;
- //
- // You *MUST* set at least the 'title', 'vertical-label', and 'series' variables.
- // Otherwise, the graph *will not work*.
- //
- $title = 'random';
- if ($context != 'host') { //判断是否为节点视图
- $rrdtool_graph['title'] = $title; // 设置图表的标题
- } else {
- $rrdtool_graph['title'] = "$hostname $title last $range";
- }
- $rrdtool_graph['vertical-label'] = 'usage'; // Y坐标标题
- $rrdtool_graph['height'] += $size == 'medium' ? 28 : 0 ; // Fudge to account for number of lines in the chart legend
- $rrdtool_graph['upper-limit'] = '10';
- $rrdtool_graph['lower-limit'] = '0';
- $rrdtool_graph['extras'] = '--rigid';
- if($context != "host" ) {
- $series = "DEF:'num_nodes'='${rrd_dir}/cpu_user.rrd':'num':AVERAGE "
- . "DEF:'random1'='${rrd_dir}/random1.rrd':'sum':AVERAGE"
- . "CDEF:'crandom1'=random1,num_nodes,/ "
- . "DEF:'random2'='${rrd_dir}/random2.rrd':'sum':AVERAGE"
- . "CDEF:'crandom2'=random2,num_nodes,/ "
- . "LINE2:'crandom1'#$random1_color:'random1' "
- . "LINE2:'crandom2'#$random2_color:'random2' ";
- }
- else
- {
- $series = "DEF:'random1'='${rrd_dir}/random1.rrd':'sum':AVERAGE "
- . "DEF:'random2'='${rrd_dir}/random2.rrd':'sum':AVERAGE"
- . "LINE2:'random1'#$random1_color:'random1' "
- . "LINE2:'random2'#$random2_color:'random2' ";
- }
- // We have everything now, so add it to the array, and go on our way.
- $rrdtool_graph['series'] = $series;
- return $rrdtool_graph;
- }
- ?>
************************ End *************************
摘录《 Custom Graphs in Ganglia 3.1.x 》,相关说明如下:
- Set values for the following hash keys:
|
$rrdtool_graph['title'] |
This will be used as the "title" of the graph. |
|
$rrdtool_graph['vertical_label'] |
This will set the label for the Y-axis on the chart (there is no corresponding X-axis key, since it is always "time.) |
|
$rrdtool_graph['series'] |
Commands to actually generate the rrdtool graph are here. This is a string variable, so care must be taken to properly format and space each command. Developers may find it useful to create a temporary array and push() commands into it, then implode() them into a single string. |
- Set other variables as desired. Setting the "upper-limit" and "lower-limit" keys can be useful to clamp a chart to a fixed range in the Y-axis. For example, if you are monitoring a percentage, and always want the low and high values to be 0 and 100, respectively. This can also be used to ignore values outside the norm that would otherwise cause rrdtool to chose an inappropriate range; basically, cheap spike removal.
- The most difficult part of generating the graph is properly setting the $rrdtool_graph['series'] value. It is suggested that you experiment first on the command line, using rrdtool directly, then convert that into a set of PHP statements. The PHP code can be as simple or complicated as required.
- There are many variables are pre-defined and available for use in custom graphs. Users are encouraged to make use of these, although changing the values inside the report PHP file is notrecommended. Variables are imported into the scope of the PHP file using the global PHP function (yes, it's ugly, we know). A list of the more commonly used variables is:
|
$context (e.g. "host", "cluster", "meta", etc) |
$cpu_*_color (see list in conf.php) |
|
$hostname (set to the current hostname, as known to gmetad) |
$load_one_color |
|
$range (time range of the graph, usually "hour", "week", "month", or "year") |
$load_colors (assoc. array that stores colors for the CPU report. Valid keys are: "down", "0-25", "25-50", "50-75", "75-100", "100+") |
|
$rrd_dir (Appropriate filesystem directory for the RRD file in question. Different contexts (host/cluster/meta) will be handled correctly. Use this instead of hardcoding paths to RRD files.) |
$mem_*_color (similar to $cpu_*color, above) |
|
$size (Current size of the graph, usually "small", "medium", "large", etc) |
$strip_domainname (should the "shortname" of the host be used, instead of the FQDN?) |
- Penultimately, any value in the $rrdtool_graph['extras'] key will be passed, verbaitim, to rrdtool after all other keys, but before various data definition, calculation, graphing and printing elements. This key is essentially a way for the developer to add any other rrdtool options that are desired, and make a last-ditch effort to override other settings.
- And lastly, the $rrdtool_graph variable should be the return value of the function; Ganglia will take care of the rest!
#rrdtool_graph_keys?
- Keys present in the $rrdtool_graph associative array.
A list of keys in $rrdtool_graph that are used:
$series (string: holds the meat of the rrdgraph definition. REQUIRED!)
//见参考文档 《RRD 数据库及RRDTool 简介》
$title (string: title of the report. REQUIRED!)
$vertical_label (label for Y-Axis. REQUIRED!)
$start (string: Start time of the graph, can usually be
left alone)
$end (string: End time of the graph, also can usually be
left alone)
$width (strings: Width and height of *graph*, the actual image
$height will be slightly larger due to text elements
and padding. These are normally set
automatically, depending on the graph size
chosen from the web UI)
$upper-limit (strings: Maximum and minimum Y-value for the graph.
$lower-limit RRDTool normally will auto-scale the Y min
and max to fit the data. You may override
this by setting these variables to specific
limits. The default value is a null string,
which will force the auto-scale behavior)
$color (array: Sets one or more chart colors. Usually used
for setting the background color of the chart.
Valid array keys are BACK, CANVAS, SHADEA,
SHADEB, FONT, FRAME and ARROW. Usually,
only BACK is set, and only rarely at that.)
$extras (Any other custom rrdtool commands can be added to this
variable. For example, setting a different --base
value or use a --logarithmic scale)
做完以上操作,重启 httpd ,操作如下:
Service httpd restart
我们可以在 cluster 视图中看到 random 统计图表,截图如下:
但在节点视图上看不到该图表,尽管 $GANGLIA_WEB/graph.d/random_report.php 中针对集群视图和节点视图都做了处理。
6) Ganglia 自定义 Web 模板
检查 web 执行流程,我们发现 $GANGLIA_WEB/host_view.php 以及 $GANGLIA_WEB/ templates/default/host_view.tpl 中均没有自定义统计表显示的代码。为了保证默认模板不变,我们建立新的模板目录 $GANGLIA_WEB/ templates/onest, 并将 default 的内容拷贝到该目录下。
a) 修改 $GANGLIA_WEB/host_view.php
在文件尾部 “ $tpl->printToScreen(); ” 语句前,添加如下代码:
// 添加自定义统计表信息
if (!isset($optional_graphs))
$optional_graphs = array();
foreach ($optional_graphs as $g) {
$tpl->newBlock('optional_graphs');
$tpl->assign('name',$g);
$tpl->assign("cluster_url", $cluster_url);
$tpl->assign("graphargs", "h=$hostname&$get_metric_string&st=$cluster[LOCALTIME]");
$tpl->gotoBlock('_ROOT');
}
该部分是通过替换 $GANGLIA_WEB/ templates/onest/host_view.tpl 的 optional_graphs 模块实现的。
b) 修改 $GANGLIA_WEB/ templates/onest/host_view.tpl
**************** Start ****************************
…….
<A HREF="./graph.php?g=network_report&z=large&c={cluster_url}&{graphargs}">
<IMG BORDER=0 ALT="{cluster_url} NETWORK"
SRC="./graph.php?g=network_report&z=medium&c={cluster_url}&{graphargs}">
</A>
<A HREF="./graph.php?g=packet_report&z=large&c={cluster_url}&{graphargs}">
<IMG BORDER=0 ALT="{cluster_url} PACKETS"
SRC="./graph.php?g=packet_report&z=medium&c={cluster_url}&{graphargs}">
</A>
<!-- START BLOCK : optional_graphs -->
<A HREF="./graph.php?g={name}_report&z=large&c={cluster_url}&{graphargs}">
<IMG BORDER=0 ALT="{cluster_url} {name}"
SRC="./graph.php?g={name}_report&z=medium&c={cluster_url}&{graphargs}">
</A>
<!-- END BLOCK : optional_graphs -->
…..
************************* End ****************************
以上修改中,在节点视图中增加了网络包统计表以及自定义统计表
c) 修改 $GANGLIA_WEB/conf.php
修改 $template_name 参数 , 让其指向我们的模板目录
**************** Start ****************************
<?php
# $Id: conf.php.in 1688 2008-08-15 12:34:40Z carenas $
#
# Gmetad-webfrontend version. Used to check for updates.
#
include_once "./version.php";
#
# The name of the directory in "./templates" which contains the
# templates that you want to use. Templates are like a skin for the
# site that can alter its look and feel.
#
$template_name = "onest";
…..
************************* End ****************************
d) 重启 httpd 服务
执行命令: service httpd restart ,这样我们就可以在节点视图,看到节点的 random 统计了。
截图如下:
e) 自定义显示
如果不喜欢 Ganglia 显示界面,我们可以修改 $GANGLIA_WEB/ templates /$template_name 目录中相应的模板文件
附录 1 :
$GANGLIA_WEB
|-- AUTHORS
|-- COPYING
|-- Makefile.am
|-- auth.php
|-- class.TemplatePower.inc.php
|-- cluster_legend.html
|-- cluster_view.php // 集群视图
|-- conf.php
|-- conf.php.in // 配置文件初始模板
|-- footer.php // 脚注
|-- functions.php
|-- ganglia.php
|-- get_context.php // 解析视图类型
|-- get_ganglia.php
|-- graph.d // 存放绘图脚本, metric 以及统计图表
| |-- cpu_report.php
| |-- load_report.php
| |-- mem_report.php
| |-- metric.php
| |-- network_report.php
| |-- packet_report.php
| |-- random_report.php
| `-- sample_report.php
|-- graph.php // 绘图脚本调用起点文件
|-- grid_tree.php
|-- header.php
|-- host_view.php // 节点视图
|-- index.php
|-- meta_view.php
|-- node_legend.html
|-- physical_view.php
|-- pie.php
|-- private_clusters
|-- show_node.php
|-- styles.css
|-- templates // 相关模板,可以修改该模板,自定义显示
| |-- default // 默认模板目录
| | |-- cluster_extra.tpl // 集群视图扩展内容模板
| | |-- cluster_view.tpl // 集群视图模板
| | |-- footer.tpl
| | |-- grid_tree.tpl
| | |-- header-nobanner.tpl
| | |-- header.tpl
| | |-- host_extra.tpl // 节点视图扩展内容模板
| | |-- host_view.tpl // 节点视图模板
| | |-- images
| | | |-- cluster_0-24.jpg
| | | |-- cluster_25-49.jpg
| | | |-- cluster_50-74.jpg
| | | |-- cluster_75-100.jpg
| | | |-- cluster_overloaded.jpg
| | | |-- cluster_private.jpg
| | | |-- grid_0-24.jpg
| | | |-- grid_25-49.jpg
| | | |-- grid_50-74.jpg
| | | |-- grid_75-100.jpg
| | | |-- grid_overloaded.jpg
| | | |-- grid_private.jpg
| | | |-- logo.jpg
| | | |-- node_0-24.jpg
| | | |-- node_25-49.jpg
| | | |-- node_50-74.jpg
| | | |-- node_75-100.jpg
| | | |-- node_dead.jpg
| | | `-- node_overloaded.jpg
| | |-- meta_view.tpl
| | |-- node_extra.tpl
| | |-- physical_view.tpl
| | `-- show_node.tpl
| `-- onest // 自定义模板目录,通过 conf.php 的 $template_name 参数指定
| |-- cluster_extra.tpl
| |-- cluster_view.tpl
| |-- footer.tpl
| |-- grid_tree.tpl
| |-- header-nobanner.tpl
| |-- header.tpl
| |-- host_extra.tpl
| |-- host_view.tpl
| |-- images
| | |-- cluster_0-24.jpg
| | |-- cluster_25-49.jpg
| | |-- cluster_50-74.jpg
| | |-- cluster_75-100.jpg
| | |-- cluster_overloaded.jpg
| | |-- cluster_private.jpg
| | |-- grid_0-24.jpg
| | |-- grid_25-49.jpg
| | |-- grid_50-74.jpg
| | |-- grid_75-100.jpg
| | |-- grid_overloaded.jpg
| | |-- grid_private.jpg
| | |-- logo.jpg
| | |-- node_0-24.jpg
| | |-- node_25-49.jpg
| | |-- node_50-74.jpg
| | |-- node_75-100.jpg
| | |-- node_dead.jpg
| | `-- node_overloaded.jpg
| |-- meta_view.tpl
| |-- node_extra.tpl
| |-- physical_view.tpl
| `-- show_node.tpl
|-- version.php
`-- version.php.in
参考资料:
1) 《 Custom Graphs in Ganglia 3.1.x 》
http://sourceforge.net/apps/trac/ganglia/wiki/Custom_graphs
2) 《 Ganglia Monitoring Tool 》
http://www.slideshare.net/sudhirpg/ganglia-monitoring-tool
3) 《针对 ganglia3.1.1 开发自定义的模块》
http://yaoweibin2008.blog.163.com/blog/static/11031392009085410345/
4) 《 Ganglia 和 Nagios ,第 1 部分 : 用 Ganglia 监视企业集群》
http://www.ibm.com/developerworks/cn/linux/l-ganglia-nagios-1/
5) PHP 语法参考
http://www.w3school.com.cn/php/php_looping.asp
http://linux.chinaunix.net/salon/200712/files/RRD_RRDTool_xa.pdf
http://www.seotcs.com/blog/1304.html
作为一个大型网站的监控,是一个涉及到各个方面的系统工作。要做好全面的web监控工作,其实不是那么容易的,作为Web的监控,笔者认为,应该包含以下几个方面:
1,服务器基础资源的监控。服务器基础资源的监控,包括服务器的内存、cpu以及磁盘等的使用监控。
这些基础资源的监控,意义是十分明显的,可以及时发现占资源的程序并尽快修复,也可以及时发现硬件资源的瓶颈,便于技术人员在第一时间将硬件进行扩充和升级。
2,web服务器的监控。web服务器的监控,主要是访问请求的监控,例如,httpd并发链接数的监控,平均响应时间等。
3,web数据库的监控。包含数据库进程资源的使用,频繁使用的sql的展示,耗资源的前几位的sql语句等。一般各大数据库服务商都带有监控的功能,例如oracle、mysql等。
4,应用服务器的监控。可以针对Web Services等的监控,监控一些重要api的调用情况,调用次数,单位时间内调用的频率等。
5,网络流量的监控。带宽的占用分析,也是相当重要的。网络流量的监控,可以及时发现异常流量的情况,例如DDOS的攻击,这样的流量攻击通过流量的监控,就可以及时发现并进行处理,避免网站因为流量攻击而瘫痪。
当然,监控虽然复杂,网络上也是有不少好用的开源工具可供下载使用的,下面来介绍一些重量级的开源监控工具。
1,Ganglia。
Ganglia是一个跨平台可扩展的,高性能计算系统下的分布式监控系统,它是UC Berkeley 发起的一个开源监视项目,设计用于测量数以千计的节点。每台计算机都运行一个收集和发送度量数据(如处理器速度、内存使用量等)的名为 gmond 的守护进程。它将从操作系统和指定主机中收集。接收所有度量数据的主机可以显示这些数据并且可以将这些数据的精简表单传递到层次结构中。正因为有这种层次结构模式,才使得 Ganglia 可以实现良好的扩展。gmond 带来的系统负载非常少,这使得它成为在集群中各台计算机上运行的一段代码,而不会影响用户性能。
2,Munin。
Munin是通过客户端-服务器架构收集数据并将其图形化的工具。Munin允许你跟踪你的主机的运行记录,就是所谓的‘节点’,然后将它们发送到中央服务器,随后你就能在这里以图像形式展示它们。
3,Cacti。
Cacti在英文中的意思是仙人掌的意思,Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具。它通过snmpget来获取数据,使用 RRDtool绘画图形,你可以不需要了解RRDtool复杂的参数。Cacti提供了非常强大的数据和用户管理功能,可以指定每一个用户能查看树状结构、host以及任何一张图,还可以与LDAP结合进行用户验证,同时也能自己增加模板,功能非常强大完善。
4,Nagios。
Nagios是一个强大的监控系统,号称IT架构监控中的行业标准。它可以让企业及时鉴别和解决IT设施中的问题,功能也是非常强大,主要表现在以下几个方面:
1)监控网络服务的方方面面(SMTP, POP3, HTTP, NNTP, ICMP, SNMP, FTP, SSH);
2)监控主机资源(cpu负载,磁盘使用情况,系统日志等);
3)服务等监视的并发处理;
4)各种预警通知功能 (通过手机短信,email或其他用户自定义方法);
5)可指定自定义的事件处理控制器;
6)可选的基于浏览器的WEB界面以方便系统管理人员查看网络状态,各种系统问题,以及日志等
7)可以通过手机查看系统监控信息
总结一下,web监控的意义如此之大,所以是需要企业花大力气去关注和重视的,幸好监控的工具也是非常多,这就需要web技术或运维人员去了解和学习这些工具,以便为web的监控工作作出更多贡献。
http://www.haodaima.net/art/1186169
Ganglia监控系统--自定义插件
当在运营的环境中使用ganglia后,你可能不在满足ganglia自身提供的插件,需要根据特定的需求描述特定服务的性能数据。接下来,我完整完成一个自定义插件的Hello World,以后翻阅。
我使用python编写插件,测试环境是ubuntu10.04+x86_64
基础环境准备
apt-get install ganglia-monitor
在/etc/ganglia/中创建conf.d目录
在conf.d目录中创建modpython.conf,其内容如下:
modules {
module {
name = "python_module"
path = "/usr/lib/ganglia/modpython.so"
params = "/usr/lib/ganglia/python_modules"
}
}
include('/etc/ganglia/conf.d/*.pyconf')
cd /usr/lib/ganglia目录,在其中创建python_modules目录,日后自行编写的python脚本都是需要放置在python_modules中。
到此,基础的环境准备已经完成。
自定义插件
其实自定义插件分为两步,第一步编写python脚本,第二步是向gmond注册此脚本
(1)第一步编写python脚本
脚本中需要包含如下三个函数:
metric_init(params):
- Called once at module initialization time
- Must return a metric description dictionary or list of dictionaries
Metric definition data dictionary :
d = {
‘name’ : ‘<your_metric_name>’,
‘ call_back’ : <call_back function>,
‘ time_max’ : int(<your_time_max>),
‘ value_type’ : ‘<string | uint | float | double>’,
‘ units’ : ’<your_units>’,
‘ slope’ : ‘<zero | positive | negative | both>’,
‘ format’ : ‘<your_format>’,
‘ description’ : ‘<your_description>’
}
Can be a single dictionary or a list of dictionaries,Must be returned from the metric_init() function
metric_handler(): – may have multiple handlers
- Metric gathering handler
- Must return a single data value of the same type as specified in the metric_init() function
metric_cleanup()
- Called once at module termination time
- Does not return a value
举个简单的例子来说明下,进入上面提到的python_modules目录中,创建如test123.py
#!/usr/bin/env python
import random
def get_foo_count(name):
return random.randrange(23, 90) + 5
def metric_init(params):
'''''metric'''
global descriptors
d1 = {
'name': 'test_count',
'call_back': get_foo_count,
'time_max': 90, #调度时间间隔
'value_type': 'uint',
'units': 'C',
'slope': 'both',
'format': '%u',
'description': 'Number of test',
'groups': 'test_group'
}
descriptors = [d1]
return descriptors
def metric_cleanup():
pass
if __name__ == '__main__':
metric_init({})
for d in descriptors:
v = d['call_back'](d['name'])
print 'value for %s is %u' % (d['name'], v)
(2)注册编写的脚本
cd /etc/ganglia/conf.d/
创建test123.pyconf,其内容如下:
modules {
module {
name = "test123"
language = "python"
}
}
collection_group {
collect_every = 10
time_threshold = 50
metric {
name = "test_count"
title = "test data" /* Metric name (see “gmond –m”) */
value_threshold = 50 /* Metric variance threshold (send if exceeded) */
}
}
说明
可能在构建的过程中遇到权限相关的问题,在调试的时候也可以使用 tail -f /var/log/syslog,帮助解决问题
【ganglia】 ganglia扩展之gmetric and Python实现方法
来自:bkeep
1 概述 Ganglia 扩展能力:使用 Ganglia 的插件将给我们提供两种添加更多功能的方法:
方法一:通过添加带内(in-band)插件。gmetric命令
方法二:通过添加一些其他来源的带外(out-of-band)欺骗。
c或者python接口来实现
说明:hadoop使用metric2插件另外研究研究。
2 gmetric命令详解 2.1 示例1:
#gmetric -n test_string -v 'hello value' -t string -d 10 -c /etc/ganglia/gmond.conf.bkeep -S '2.2.2.2:web'
解说:-n '指标名' -v 指标值 -t 数据类型 -u '单位' -d 指标的存活时间 -c 指定ganglia配置文件 -S伪装客户端信息2.2.2.2代表ip地址,web代表主机名。

2.2 示例2:
#gmetric -n bkeepUse -v 10 -t int32 -u '% test' -d 10 -S '2.2.2.2:web'

2.3 gmetric语法:
#gmetric --help
gmetric 3.1.2
Purpose:
The Ganglia Metric Client (gmetric) announces a metric
on the list of defined send channels defined in a configuration file
Usage: gmetric [OPTIONS]...
-h, --help Print help and exit
-V, --version Print version and exit
-c, --conf=STRING The configuration file to use for finding send channels
(default='/etc/ganglia/gmond.conf')
-n, --name=STRING Name of the metric
-v, --value=STRING Value of the metric
-t, --type=STRING Either
string|int8|uint8|int16|uint16|int32|uint32|float|double
-u, --units=STRING Unit of measure for the value e.g. Kilobytes, Celcius
(default='')
-s, --slope=STRING Either zero|positive|negative|both (default='both')
-x, --tmax=INT The maximum time in seconds between gmetric calls
(default='60')
-d, --dmax=INT The lifetime in seconds of this metric (default='0')
-S, --spoof=STRING IP address and name of host/device (colon separated) we
are spoofing (default='')
-H, --heartbeat spoof a heartbeat message (use with spoof option)
3 python插件扩展ganglia 3.1 首先安装gangliapython模块,即modpython.so
安装包:
#rpm -qf /usr/lib64/ganglia/modpython.so
ganglia-gmond-python-3.1.2-5.el5
安装后的文件位置:
[root@inc-dw-hadoop-3 /usr/lib64/ganglia]
#ls
modcpu.so modload.so modmulticpu.so modproc.so modsys.so
moddisk.so modmem.so modnet.so modpython.so python_modules
3.2 配置gmond.conf,添加扩展的模块
1,vi /etc/ganglia/gmond.conf
#如果没有下面这句,请添加
include ('/etc/ganglia/conf.d/*.conf')
2,创建modpython.conf文件
vi /etc/ganglia/conf.d/modpython.conf
# The modules section describes the module
# that should be loaded.
# name - module name
# path - load path of the .so
# params - path to the directory where mod_python
# should look for python metric modules
modules {
module {
name = "python_module" #python主模块
path = "modpython.so" #动态库路径
params = "/usr/lib64/ganglia/python_modules" #指定我们编写的python脚本放置位置
}
}
include ('/etc/ganglia/conf.d/*.pyconf') #该目录下只能有一个文件包含此配置,否则会造成死循环。把机器搞死。
3.3 实战之开发python模块 3.3.1 实验环境
进程 机器
------------ -----------------------------
gmond inc-dw-hadoop-3
gmetad dw-ganglia-3
httpd dw-ganglia-3
3.3.2 创建random_module.pyconf模块配置文件:注意:请区别于modpython.conf;自定义python模块配置文件只针对自己开发的模块。
[root@inc-dw-hadoop-3 /etc/ganglia/conf.d]
#cat random_module.pyconf
modules {
module {
#模块名,该文件存放于params = "/usr/lib64/ganglia/python_modules"指定的路径下
name = "random_module"
#声明使用python语言
language = "python"
#参数列表,所有的参数作为一个dict(即map)传给python脚本的metric_init(params)函数。
#本例中,metric_init调用时,params={“RandomMax”:”10”,”RandomMin”:”0”}
param RandomMax{
value = 10
}
param RandomMin{
value = 0
}
}
}
#需要收集的metric列表,一个模块中可以扩展任意个metric
collection_group {
collect_every = 10
time_threshold = 50 #最大发送间隔
metric {
name = "random1" #metric在模块中的名字
title = "test random1" #图形界面上显示的标题
value_threshold = 50
}
metric {
name="random2"
title = "test random2"
value_threshold = 50
}
}
3.3.3 编写random_module.py模块:
具体采集那些信息?有什么语法规定吗?仔细读下面的例子就能发现。
#cd /usr/lib64/ganglia/python_modules/
#vi random_module.py
import random
random_max = 100
random_min = 0
v = 0
def random1_handler(name):
global v,random_max,random_min
v = random.randint(random_min,random_max)
return v
def random2_handler(name):
global v,random_max,random_min
return random_min+random_max-v
def metric_init(params):
global random_max,random_min
if params:
if params.has_key("RandomMin"):
random_min = int(params["RandomMin"])
if params.has_key("RandomMax"):
random_max = int(params["RandomMax"])
tmp = {'name':'random1','call_back':random1_handler,
'value_type':'uint','units':'usage',
'slope':'both','format':'%u',
'description':'test random plugin',
'groups':'random'}
descriptors = [tmp]
tmp1 = {'name':'random2','call_back':random2_handler,
'value_type':'uint','units':'usage',
'slope':'both','format':'%u',
'description':'test subs plugin',
'groups':'random'}
descriptors.append(tmp1)
return descriptors
def metric_cleanup():
pass
if __name__=='__main__':
descriptors = metric_init(None)
for d in descriptors:
print "value for %s is %d"%(d['name'],d['call_back'](d['name']))
3.3.4 metric开发接口:
Ganglia模块扩展时,Python脚本主要要实现的函数有:
metric_init(params):
? Called once at module initialization time
? Must return a metric description dictionary or list of dictionaries
Metric definition data dictionary :
d = {‘name’ : ‘<your_metric_name>’,
'call_back’ : <call_back function>,
'time_max’ : int(<your_time_max>),
'value_type’ : ‘<string | uint | float | double>’,
'units’ : ’<your_units>’,
'slope’ : ‘<zero | positive | negative | both>’,
'format’ : ‘<your_format>’,
'description’ : ‘<your_description>’}
Can be a single dictionary or a list of dictionaries
Must be returned from the metric_init() function
? Any other module initialization can also take place here
? metric_handler() – may have multiple handlers
? Metric gathering handler
? Must return a single data value of the same type as specified in the metric_init() function
? metric_cleanup()
? Called once at module termination time
? Does not return a value
3.3.5 random_module.py输出效果图:
完成以上步骤后,重启gmond ,就可以在 web 界面的节点视图上看到新添的 random1 和 random2 的统计图表

3.4实战之增加统计表(将多条曲线画在一张图上) 3.4.1 思路
思路:根据url得知关键字---->ganglia web 目录底下去搜索相关文件---->模仿即可。
说明:memory和network模版不一样,需要分别模仿。

[root@dw-ganglia-3 /usr/share/ganglia]
# grep "network_report" * -r
get_context.php: "network_report" => 1,
graph.php:$graph = isset($_GET["g"]) && in_array( $_GET['g'], array( 'cpu_report', 'mem_report', 'load_report', 'network_report', 'packet_report' ) ) ?
graph.php: else if ($graph == "network_report")
templates/default/host_view.tpl:<A HREF="./graph.php?g=network_report&z=large&c={cluster_url}&{graphargs}">
templates/default/host_view.tpl: SRC="./graph.php?g=network_report&z=medium&c={cluster_url}&{graphargs}">
templates/default/cluster_view.tpl:<A HREF="./graph.php?g=network_report&z=large&{graph_args}">
templates/default/cluster_view.tpl: SRC="./graph.php?g=network_report&z=medium&{graph_args}">
3.4.2编辑get_context.php[root@dw-ganglia-3 /usr/share/ganglia]
#vi get_context.php
#add by bkeep
$reports = array(
"load_report" => "load_one",
"cpu_report" => 1,
"mem_report" => 1,
"network_report" => 1,
"random_report" => 1,
"packet_report" => 1
3.4.3编辑graph.php
这里演示了增加random曲线,后面会演示增加多条曲线的方法
[root@dw-ganglia-3 /usr/share/ganglia]
#vi graph.php
#$graph = isset($_GET["g"]) && in_array( $_GET['g'], array( 'cpu_report', 'mem_report', 'load_report', 'network_re
port', 'packet_report' ) ) ?
#modify by bkeep
$graph = isset($_GET["g"]) && in_array( $_GET['g'], array( 'cpu_report', 'mem_report', 'load_report', 'network_rep
ort', 'packet_report' ,'random_report') ) ?
# add by bkeep
#else if ($graph == "network_report")
else if ($graph == "random_report")
{
$fudge = $fudge_2;
#$style = "Network";
$style = "Random";
$lower_limit = "--lower-limit 0 --rigid";
$extras = "--base 1024";
$vertical_label = "--vertical-label 'Bytes/sec'";
#$series = "DEF:'bytes_in'='${rrd_dir}/bytes_in.rrd':'sum':AVERAGE "
$series = "DEF:'random1'='${rrd_dir}/random1.rrd':'sum':AVERAGE "
#."DEF:'bytes_out'='${rrd_dir}/bytes_out.rrd':'sum':AVERAGE "
."DEF:'random2'='${rrd_dir}/random2.rrd':'sum':AVERAGE "
#."LINE2:'bytes_in'#$mem_cached_color:'In' "
."LINE2:'random1'#$mem_cached_color:'In' "
#."LINE2:'bytes_out'#$mem_used_color:'Out' ";
."LINE2:'random2'#$mem_used_color:'Out' ";
}
3.4.4编辑templates/default/host_view.tpl
[root@dw-ganglia-3 /usr/share/ganglia]
#vi templates/default/host_view.tpl
<A HREF="./graph.php?g=network_report&z=large&c={cluster_url}&{graphargs}">
<IMG BORDER=0 ALT="{cluster_url} NETWORK"
SRC="./graph.php?g=network_report&z=medium&c={cluster_url}&{graphargs}">
</A>
<!--add by bkeep -->
<A HREF="./graph.php?g=random_report&z=large&c={cluster_url}&{graphargs}">
<IMG BORDER=0 ALT="{cluster_url} NETWORK"
SRC="./graph.php?g=random_report&z=medium&c={cluster_url}&{graphargs}">
</A>
3.4.5编辑templates/default/cluster_view.tpl
[root@dw-ganglia-3 /usr/share/ganglia]
#vi templates/default/cluster_view.tpl
<A HREF="./graph.php?g=network_report&z=large&{graph_args}">
<IMG BORDER=0 ALT="{cluster} NETWORK"
SRC="./graph.php?g=network_report&z=medium&{graph_args}">
</A>
<!-- add by bkeep -->
<A HREF="./graph.php?g=random_report&z=large&{graph_args}">
<IMG BORDER=0 ALT="{cluster} NETWORK"
SRC="./graph.php?g=random_report&z=medium&{graph_args}">
</A>
3.4.6添加多条曲线
vi /usr/share/ganglia/graph.php
# add by bkeep
#else if ($graph == "network_report")
else if ($graph == "random_report")
{
$fudge = $fudge_2;
#$style = "Network";
$style = "Random";
$lower_limit = "--lower-limit 0 --rigid";
$extras = "--base 1024";
$vertical_label = "--vertical-label 'Bytes/sec'";
#$series = "DEF:'bytes_in'='${rrd_dir}/bytes_in.rrd':'sum':AVERAGE "
$series = "DEF:'random1'='${rrd_dir}/random1.rrd':'sum':AVERAGE "
#."DEF:'bytes_out'='${rrd_dir}/bytes_out.rrd':'sum':AVERAGE "
."DEF:'random2'='${rrd_dir}/random2.rrd':'sum':AVERAGE "
."DEF:'bytes_out'='${rrd_dir}/bytes_out.rrd':'sum':AVERAGE "
."DEF:'bytes_in'='${rrd_dir}/bytes_in.rrd':'sum':AVERAGE " #定义一个样式
#."LINE2:'bytes_in'#$mem_cached_color:'In' "
."LINE2:'random1'#$mem_cached_color:'randmon1' "
#."LINE2:'bytes_out'#$mem_used_color:'Out' ";
."LINE2:'random2'#$mem_used_color:'random2' "
."LINE2:'bytes_out'#$mem_used_color:'bytes_out' "
."LINE2:'bytes_in'#$cpu_nice_color:'bytes_in' "; #定义颜色
}
看看效果图,四条曲线。

系统的服务器多了,独立运行的服务进程多了,服务进程间的通讯多了,该做那些监控,该怎么监控?有没有什么成熟的思想想法?
监控是不是可以分为2个方面:1)系统级别的监控(cpu,memory,io,disk,net),服务是否存活
2)应用级别(各子系统业务相关异常监控)
具体的,怎么来实现这个监控,做到一个可灵活配置、扩展的插件式监控平台?感觉还是比较棘手
综合了大家的回答,打算先这么做:
1:Nagios作为CPU、内存、硬盘等各个基本非业务的监控
2:各个业务模块做自己相关的监控:服务异常监控、服务统计信息等
1)服务异常信息通过mq异步的发送给监控主服务器,由监控主服务器统一处理
2)服务统计信息先在本地模块内存汇总,然后定时间隔的发送给监控主服务器进行持久化等相关处理


















浙公网安备 33010602011771号