首页 > 代码库 > ganglia工作原理
ganglia工作原理
Ganglia 项目是由加州大学发起的,现在已经成为一个应用非常广泛集群监控软件。可以监视和显示集群中的节点的各种状态信息,比如如:cpu 、mem、硬盘利用率, I/O负载、网络流量情况等,同时可以将历史数据以曲线方式通过php页面呈现。同时具有很好的扩展性,允许用户加入自己所要监控的状态信息。
Ganglia整体结构图
Ganglia 包括如下几个程序,他们之间通过XDL(xml的压缩格式)或者XML格式传递监控数据,达到监控效果。集群内的节点,通过运行gmond收集发布节点状 态信息,然后gmetad周期性的轮询gmond收集到的信息,然后存入rrd数据库,通过web服务器可以对其进行查询展示。
Gmetad 这个程序负责周期性的到各个datasource收集各个cluster的数据,并更新到rrd数据库中。 可以把它理解为服务端。
Gmond 收集本机的监控数据,发送到其他机器上,收集其他机器的监控数据,gmond之间通过udp通信,传递文件格式为xdl。收集的数据供Gmetad读取,默认监听端口8649 ,监听到gmetad请求后发送xml格式的文件。可以把它理解为客户端。
web front-end 一个基于web的监控界面,通常和Gmetad安装在同一个节点上(还需确认是否可以不在一个节点上,因为php的配置文件中ms可配置gmetad的地址及端口),它从Gmetad取数据,并且读取rrd数据库,生成图片,显示出来。
如上图所示,gmetad周期性的去gmond节点或者gmetad节点poll数据。一个gmetad可以设置多个datasource,每个datasource可以有多个备份,一个失败还可以去其他host取数据。
如 果是muticast模式的话,gmond之间还会通过多播来相互传递数据。Gmond本身具有udp send和recv通道,还有一个tcp recv通道。其中udp通道用于向其他gmond节点发送或接受数据,tcp则用来export xml文件,主要接受来自gmetad的请求。Gmetad只有tcp通道,一方面他向datasource发送请求,另一方面会使用一个tcp端口,发 布自身收集的xml文件,默认使用8651端口。所以gmetad即可以从gmond也可以从其他的gmetad得到xml数据。
Gmond节点内部模块图如下所示:
图 2 Gmond节点模块结构图
如 上图所示,主要由三个模块组成,collect and publish模块,该模块周期性的调用一些内部指令获得metric data,然后将这些数据通过udp通道发布给其他gmond节点。Listen Threads,监听其他gmond节点的发送的udp数据,然后将数据存放到内存中。XML export thread负责将数据以xml格式发布出去,比如交给gmetad。
下面重点介绍下unicast模式下ganglia系统内的数据流。
图 3单播状况下集群节点间的数据流
如 上图所示,多个gmond节点通过udp向单播的目标host的gmond发送数据,gmetad然后向该目标host的gmond请求xml文件,然后 存入rrdtool数据库。 在unicast模式中,图中方框内的组件通常是位于集群内的同一个节点。该节点负责收集存储 显示被监控的各节点的状态信息。
2.2 自定义metrics
向ganglia加入自定义metric有两种方法,一种是通过命令行的方式运行gmetric,另一种是通过ganglia提供的面向c和python的扩展模块,加入自定义的模块支持。
2.3 优点及可能存在的问题2.3.1 优点
n 自动收集数据
集 群内各个节点的信息收集可以通过ganglia系统自动的收集起来,这个收集是独立进行地。其通信性能都是经过良好设计和优化的。具体的机制是:周期性的 将这些信息发送给gmond,这样信息就加入了ganglia监控系统。通过ganglia的监控机制完成监控数据的收集显示的功能。Ganglia系统 的机制可以参考2.1ganglia工作原理。
n 图形界面
数据可以通过图形显示出来。通过登录web服务器即可查看。目前可以通过该视图查看集群及单独节点的状态曲线。同时具有基本的排序机制,可以根据值降序或者升序排序。可以查看过去1小时 1天 1周 1年等时间段的状态曲线。
n 数据库rrdtool存储了历史数据
由 于采用了rrd存储数据,这样我们不单可以查看当前的状态,还可以查看之前的状态历史,同时可以将metrics随时间的变化以曲线的方式变现表现出来。 而单独的向文件写日志很难保存和方便地查看之前的历史记录。而且有可能使得日志文件很大。RRDtool具有如下优点:
1)除了存储数据之外,它具有可以创建图形的工具;
2)它的数据库文件大小是固定的,新的数据添加到已有数据的后面,当到了文件末尾的时候就开始从文件开始写数据,Round Robin就是指这个意思;
3)一般的数据库只能存储数据本身,而rrd可以存储相对与以前的数据的变动
4)一般的数据库是在提供数据的时候才更新,而RRD是在每一个预先设好的时间间隔都会更新,每次更新的时候,time stamp也会存储进去
2.3.2 可能存在的问题及瓶颈
n 开销估计:网络 IO CPU
只 运行gmond进程的节点开销很小,通常需要1m左右内存,cpu大概1%不到,同时gmond只把数据保存在内存中,因此io开销可以忽略。同时向其他 节点单播本身的信息本身的网络压力也不会很大。因此对于只运行gmond的节点来说,开销很小。 如果采用了unicast模式,主要的开销就会在各节点 的gmond进程向中央节点发送的udp数据带来的网络开销,此外gmond和gmetad的通信,web服务也在该中央节点上进行。这样主要的瓶颈就在 中央节点上,其网络 IO CPU的压力都会很大。
对于网络来说,中央节点将收到来自其他所有节点发送的udp包,如果一个节点每秒发10个包,500个节点将会发出5000个,每个包有200字节,就有1m字节,5000个包的处理所需要的cpu使用也会上升。
对于内存来说每个状态信息存储在内存大概要耗费300byte,如果一个job有10万个instance,每个instance又有10个状态需要监控,那么将耗费10000*10*300=30m的内存,其对应的xml文件大小也应该是10m级别的。
对 于IO来说,Gmetad默认15秒向gmond取一次xml数据,如果gmond和gmetad都是在同一个节点,这样就相当于本地io请求。同时 gmetad请求完xml文件后,还需要对其解析,也就是说按默认设置每15秒需要解析一个10m级别的xml文件,这样cpu的压力就会很大。同时它还 有写入RRD数据库,还要处理来自web客户端的解析请求,也会读RRD数据库。这样本身的IO CPU 网络压力就很大,因此这个节点至少应该是个空闲的而且能力比较强的节点。
n Gmetad RRD写入瓶颈
需 要格外注意的是gmetad守护进程使用RRDtool,会在/var/lib/ganglia/rrds/目录下的一个子目录存储这些rrd数据信息, 如果集群节点超过100个,你可能应将这个目录放在RAM文件系统上,因为这个数据库的磁盘I/O将会非常高。由于RRD特有的存储方式,它会为每个 metric存放一个文件,如果配置了多个采样频率,它还会为每个采样频率保存一个单独的文件。这就意味着gmetad将metric的值保存到rrd数 据库的操作,将是针对大量小文件的IO,假设集群有300个节点,每个节点有50个metric,那么意味着gmetad会记录15000个 metric,如果这些metric都是一秒更新一次,那么意味着每秒15000的随机写入操作,通常来说硬盘都是撑不住的。
一 个可能的解决方法就是将集群内的节点划分为多个子集,为每个子集配置一个中央收集节点。但这样会带来部署和结果查看的不方便性。另外可以通过 RRDcached来缓解这个gmetad使用RRDTool的问题大量随机写入,它会缓存这些写入,批量进行更新。此外就是降低metric的采样频 率,减少metrics的数目,尽量减少这种写入请求量。如果机器具有多块磁盘,尽量利用多个磁盘来保存RRD数据。还有就是使用上面我们所说的将rrd 目录加载为tmpfs。
n 使用的服务及端口以及依赖的库
Ganglia 的gmond进程使用了udp进行单播,默认端口8649,同时还有负责tcp监控的端口8651 8652 8650也会被使用,这些端口需要在集群内部打开,这些使用的端口可以进行配置。另外apache也需要一个端口提供服务,这个端口会被从外部访问,默认 是80。
n 同一个host的不同进程的相同Metirc可能混淆
由 于ganglia本身是根据host+metric_name来区分不同的状态参数的,也就是它无法区分同一host内的不同进程相同的名称的状态变量。 但是对于单纯的一个状态量,虽然可能是多个进程的状态,但对它来说只能看到一个名称,所以当多个进程同时向它报告具有同一个名称的状态的value时,它 无法区分出进程间的不同。如果要区分它们,就需要加入一个命名机制区分它们。
程 序运行完毕,该程序对应的自定义的那些metric不会消失,这意味着虽然程序运行结束,但我们依然可以查看其历史记录。但另一方面这样也会带来新的问 题,由于我们采用的针对metric的命名机制,会导致metric积累到很多,这样会导致xml变得越来越大,增加中央节点解析该文件时的压力,也不方 面查阅。目前有一个可行的方法就是修改gmetad的配置文件,减少数据的保存时间的设置。
======================================================================================================================================================
- Ganglia 配置文件:
globals段:gmond的全局配置,一般不需要修改
cluster段:这一段是重要的一段,至少需要定义name变量,所有name相同的节点将认为在同一个集群里,其他变量是对该集群的说明。
host段:只有一个变量,location,是对这个节点的一些说明
udp_send_channel段:这也是很重要的一段,可以定义多个这样的段,不过如果在通一局域网内,只有一个集群的环境下,这一段保持默认也可以工作的很好。ganglia默认采用多播发送监控数据,mcast_join变量指定多播组。但是,并非所有环境都适合多播,例如,我的环境就不适合多播,幸运的是,ganglia也支持单播的方式,host变量指定一台gmond服务器接受监控数据。值得注意的是,mcast_join和host不能同时出现在一个channel里。port 指定端口号,ttl指定跳数一般为1,如果需要经过gmond中转,需要修改这个跳数。
udp_recv_channel段:对应于udp_send_channel段,也可以设置多个。如果采用单播的方式,需要注意bind变量指出的ip,你的所有其他gmond可以访问到,事实上,可以使用0.0.0.0
tcp_accept_channel段:指定一个端口,可以通过TCP的的方式,从这个端口读取XML格式的监控数据
modules段和collection_group段:
这个modules区域包含每个模块被加载的配置数据。他应该包含一个或者多个module子节点。每一个module子节点里面就是度量模块的name,里面的language以及其他的一些参数说明:name这个名字和你创建的模块名字想对应(.py结尾)language除非你用C/C++编写你的模块,否则你必须明确的声明模块所用的语言。声明‘python’作为你的语言,告诉gmond到python_modules这个目录里搜索你的模块文件。param每个param子节点有一个name和一个value,他们组成了name/value对作为参数被传递到上面描述的metric_init()函数中。这个参数是字典类型的,’name’是键,’value’是值。因此你可以自定义你的参数像下面这样:
Collection_group
配置文件剩下的部分具有相同的格式,collection_group 或者 metric。查阅gmond.conf的帮助文档是很有收获的,不过我们将简单介绍例子中的 collection_group 指令。collect_every or collect_oncecollect_every 告诉 gmond 从定义在collection_group的度量中收集数据的频率(秒为单位)。在例子中,’temp’度量会间隔十秒被收集。你也可以设定collect_once=yes命令gmond收集静态度量,他们在会在gmond启动时被收集一次。这对那些在运行期间不会改变的东西是很有用的(比如运行的CPU个数)time_threshold将度量数据报告给Ganglia的最大频率(秒为单位)。在例子中,temp模块会至少每50秒报告一次。这个指令会在被收集度量的值大于metirc定义的‘value_threshold’时被抛弃哦。metric这是你定义特殊度量设置的地方
name:特殊度量的名字,也定义在你模块里描述符字典类型上
title:可选的友好度量名称,将会在Ganglia前台被显示
value_threshold: 如果收集到的度量报告的值(在你的描述符中定义的单位)超过定义在这里的值,那么它就会报告给ganglia而忽略collection_group中定义的 ‘time_threshold’参数