目前,淘宝的hbase监控平台上,主要借助ganglia来采集监控数据。采集到的监控数据会借助rrdtool开发库来解析数据,做进一步的处理,例如数据展现、报警触发、性能统计报表等等。

采集的监控数据主要包括四个方面:某台机器OS层面上的数据,例如内存、磁盘、网络、load、网络流量等;某台regionserver(或是master)上的RPC请求,主要是RPC的处理平均时间和请求次数;某台regionserver(或master)机器jvm的状态,例如关于线程的信息,GC的次数和时间,内存使用状况,以及ERROR、WARN、Fatal事件出现的次数;regionserver(或master)进程中的统计信息,例如读写请求的次数、读写请求的来源分布、每张表的请求次数、读写请求最大响应时间、region数量、split操作、compcat操作、memstore的信息、block的信息、fs操作的信息等。

OS层面上的数据采集主要实现在ganglia的gmond进程中,本文关注重点是hbase的进程层面上监控数据的统计收集,因此本文基本略过OS层面的数据统计,有兴趣的可以查看ganglia手册和源码来看看如何采集OS层面的数据的。对于hbase进程层面上监控数据的采集,简单的说来,在具体实现上,hbase完全使用了hdfs的metric框架来收集监控数据,这个是本文要详细描述的。

本文接下来将会详细描述hbase进程层面上数据的监控,主要分为以下几部分:hbase监控的配置说明、hadoop基于ganglia的metric监控框架、hbase中regionserver上RPC的监控数据计算采集、regionserver中jvm监控数据的计算采集、regionserver进程状态监控数据的计算采集。

 1 hbase的监控配置说明

在hbase的conf目录下,hadoop-metrics.properties文件中,对于hbase进程层面上数据(jvm、rpc等)的采集进行配置,主要是配置采集数据时使用的对象、采集的频率、采集数据的接收gmond进程,例如对于RPC的配置:

rpc.class=org.apache.hadoop.metrics.ganglia.GangliaContext31
rpc.period=10
rpc.servers=192.168.0.100:8649

由于线上安装的ganglia版本为3.1.7,因此rpc.class选择hadoop中3.1版本的GangliaContext31类,这个类主要负责监控数据的打包和发送。rpc.period默认为10秒,即10秒采集发送一次数据。rpc.servers配置指定了一台接受GangliaContext31类发送的监控数据,目前集群中ganglia采用单播的方式收集数据,一个集群内会指定一台机器上的gmond进程来专门接受集群内所有机器发来的监控数据,这个集群内负责接收数据的机器ip是192.168.0.100,机器上的gmond进程端口是默认的8649。(当然,还可以配置rpc.class为org.apache.hadoop.hbase.metrics.file.TimeStampingFileContext,以本地文件的方式来存储监控数据,这个就略去了)

在每个hbase集群内,会选择一台机器上的gmond进程来接受集群内其他机器上gmond发送来的监控数据,我们称之为主gmond。在hbase监控系统所在机器上运行gmeta进程,负责从每个hbase集群内的主gmond上拉取数据到本地,最终为被监控系统所访问。这是一个典型的多集群使用ganglia来构建监控系统的架构。

 2 hadoop基于ganglia的监控框架

下面以regionserver进程来简单描述下hbase内部采集metric的过程(master的进程中的过程基本类似,采集的数据略有区别)。

在hbase的HRegionServer类(regionserver进程的类)中,成员变量server是HBaseServer实例,在server对象中,rpcMetrics变量在初始化的时候,会采用反射机制的方式,来创建一个负责发送监控数据的对象,该对象的类名称就是前面提到的配置文件中rpc.class中指定的org.apache.hadoop.metrics.ganglia.GangliaContext31,在构造该对象的时候,也指定了发送数据的时间间隔是10秒钟。rpcMetrics主要负责处理rpc相关的信号数据的采集,负责采集jvm和regionserver的metric的对象的构造基本上和rpcMetrics相同,只是阶段不同,前者是在HRegionServer对象构造的时候创建的,后两者是在HRegionServer类的对象运行run方法的时候构造的。

以rpcMetrics为例,该变量是一个HBaseRpcMetrics类的对象(负责采集regionserver的metric采集的类是RegionServerMetrics,负责jvm的是JvmMetrics)。HBaseRpcMetrics对象在初始化的时候,会根据根据配置,使用反射机制来创建一个GangliaContext31的对象,并将数据的发送间隔设置为配置中指定的10秒,如果没有配置,则默认5秒。在构造完GangliaContext31对象后,会调用startMonitoring方法,该方法实际上位于GangliaContext31继承的AbstractMetricsContext中。startMonitoring方法中会构造一个异步执行的定时任务,该定时任务主要通过timerEvent接口来实现,该接口主要负责调用在AbstractMetricsContext中注册的各个updater,来获取各个updater的监控数据,并打成固定格式的UDP包,发送给指定的gmond进程。在完成了GangliaContext31的对象的构建后,会通过GangliaContext31的对象将自身作为一个updater注册到AbstractMetricsContext中。最后,调用HBaseRpcMetrics中的initMethods方法,为所有的RPC接口生成生成MetricsTimeVaryingRate对象,以对应的RPC接口的名称为key,以MetricsTimeVaryingRate对象存入一张hash表中。这样,就完成了HBaseRpcMetrics类的对象的初始化。

HBaseRpcMetrics类的对象会作为一个updater注册到AbstractMetricsContext中,被定时调用,这个调用的接口就是doUpdates。这个接口负责实现对RPC中各个MetricsTimeVaryingRate对象推送到GangliaContext31的对象缓冲(hash表)中。HBaseRpcMetrics类实现了Updater抽象类中的doUpdates接口。

在regionserver运行的过程中,当某个hanler线程处理RPC的时候,会调用HBaseRpcMetrics中的inc方法,该方法的参数是RPC的名称和RPC的处理时间,该方法根据参数,找到RPC对应的MetricsTimeVaryingRate对象的inc方法来将PRC的处理时间增加,并加RPC请求的数量自增1次。

上面简单描述了HBaseRpcMetrics对象的初始化、采集和rpc相关的metric、以及推送metric的过程。简单的说来,RegionServerMetrics以及JvmMetrics,和HBaseRpcMetrics相比,在后台推送监控数据的框架基本一致,区别在于这两个类在采集监控数据的流程。

(由于整个的过程较为复杂,大家可以结合代码和《Hbase The Definite Guide 》中第10章 Cluster Monitoring中的内容来理解,特别是第391页的时序图,很详细的描述了整个过程,可惜图太大,而且涉及版权,就不贴上来了)