一直认为Hadoop本身自带的HDFS和JobTracker监控页面是最好用的监控页面,简单明了。但是现在想要自己开发一套监控系统,那该怎样去获取Hadoop集群的当前状况呢?
- 网页抓取
首先,想到的办法是抓取网页,通过抓取50030和50070页面获得监控的数据。不得不说,这个办法实在是太土了,不到万不得已真的不好意思用。 - Hadoop JMX 接口
经过各种查阅,看到了一位大神写的文档(链接:http://slaytanic.blog.51cto.com/2057708/1179108),再次再膜拜一下这位大神吧。将http://namenode:50070/dfshealth.jsp 替换为 http://namenode:50070/jmx 就可以看到Hadoop自带的JMX接口所返回的JSON格式的数据,信息非常全面。同时,可以在链接的后面,添加参数来获取指定名称的监控信息,例如访问 http://namenode:50070/jmx?qry=Hadoop:service=NameNode,name=NameNodeInfo 就可以只获取NameNodeInfo的信息,通过更改qry=后面的参数,可以指定想要获取的内容,qry参数的值即为json信息中name所对应的内容。
通过同样的方法,可以获得:
JobTracker的信息:http://namenode:50030/jmxDataNode的信息:http://datanode:50075/jmxTaskTracker信息:http://datanode:50060/jmx上面这些链接基本上可以提供所有想要监控的信息了,但是,找了一圈儿也没找到我想要的Job列表,包括正在运行的作业、成功的作业以及失败的作业信息。
- Hadoop API
这时想到了早期版本的Hadoop API提交作业的时候都会用的JobClient这个类,抱着试试看的态度,去Hadoop API里面翻了半天,还真有收获。
直接上干货了:
[java]view plaincopy
- Configuration conf = new Configuration();
- InetSocketAddress inetSocket = new InetSocketAddress(MonitorUtil.getHostnameOfNamenode(), 9001);
- JobClient jobClient = new JobClient(inetSocket, conf);
- JobStatus[] jobsStatus = jobClient.getAllJobs();
- //这样就得到了一个JobStatus数组,随便取出一个元素取名叫jobStatus
- jobStatus = jobsStatus[0];
- JobID jobID = jobStatus.getJobID(); //通过JobStatus获取JobID
- RunningJob runningJob = jobClient.getJob(jobID); //通过JobID得到RunningJob对象
- runningJob.getJobState();//可以获取作业状态,状态有五种,为JobStatus.Failed 、JobStatus.KILLED、JobStatus.PREP、JobStatus.RUNNING、JobStatus.SUCCEEDED
- jobStatus.getUsername();//可以获取运行作业的用户名。
- runningJob.getJobName();//可以获取作业名。
- jobStatus.getStartTime();//可以获取作业的开始时间,为UTC毫秒数。
- runningJob.mapProgress();//可以获取Map阶段完成的比例,0~1,
- runningJob.reduceProgress();//可以获取Reduce阶段完成的比例。
- runningJob.getFailureInfo();//可以获取失败信息。
- runningJob.getCounters();//可以获取作业相关的计数器,计数器的内容和作业监控页面上看到的计数器的值一样。
- 计数器这块稍微有点儿麻烦,举个例子吧。想要获得HDFS_BYTES_READ的值,方法为:
[java] view plain copy
- runningJob.getCounters().getGroup("FileSystemCounters").getCounter("HDFS_BYTES_READ");
- 这里的FileSystemCounters为Group的名称,以该名称作为getGrout的参数可以取得相应的Group。Group的名称和50030页面上看到的组的名称并不相同,对应关系为:
org.apache.hadoop.mapred.JobInProgress$Counter | Job Counters |
org.apache.hadoop.mapreduce.lib.output.FileOutputFormat$Counter | File Output Format Counters |
FileSystemCounters | FileSystemCounters |
org.apache.hadoop.mapreduce.lib.input.FileInputFormat$Counter | File Input Format Counters |
org.apache.hadoop.mapred.Task$Counter | Map-Reduce Framework |
左边为getGroup函数参数名,后面为想要获取的组名称。
得到Group之后就可以通过计数器的名称来得到相应计数器的值了。