由于项目中,需要统计每个业务组使用的计算机资源,如cpu,内存,io读写,网络流量。所以需要阅读源码查看Hadoop的默认counter。
MapReduce Counter可以观察MapReduce job运行期的一些细节数据,Counter有"组group"的概念,用于表示逻辑上相同范围的所有数值。
cpu如何衡量mapreduce的任务的计算量呢,如果按照任务的运行时间,有些任务的大部分时间可能卡在最后一个reduce,或者运行期间有资源抢占问题,造成运行时间较高。如果按照任务的map数和reduce数,也是不准确的,因为有些map和reduce处理的数据量很少,运行时间很短。
hadoop任务的运行使用的cpu时间,才是衡量任务的计算量,hadoop提供的counter:"Map-Reduce Framework:CPU time spent (ms)",就是任务运行耗费的cpu时间,这个cpu时间是如何统计出来的,是hadoop在运行期间,每个task会从/proc/<pid>/stat读取对应进程的用户cpu时间和内核cpu时间,他们的和就是cpu时间。
附:task获取cpu时间的源码:org.apache.hadoop.mapred.Task.updateResourceCounters--> org.apache.hadoop.util.LinuxResourceCalculatorPlugin.getProcResourceValues(获取cpu和内存资源)--> org.apache.hadoop.util.ProcfsBasedProcessTree.getProcessTree.
内存hadoop默认counter,获取内存信息,有以下参数:
"Map-Reduce Framework:Physical memory (bytes) snapshot" 每个task会从/proc/<pid>/stat读取对应进程的内存快照,这个是进程的当前物理内存使用大小。
"Map-Reduce Framework:Virtual memory (bytes) snapshot" 每个task会从/proc/<pid>/stat读取对应进程的虚拟内存快照,这个是进程的当前虚拟内存使用大小。
"Map-Reduce Framework:Total committed heap usage (bytes)" 每个task的jvm调用Runtime.getRuntime().totalMemory()获取jvm的当前堆大小。
附:task获取内存的源码:org.apache.hadoop.mapred.Task.updateResourceCounters
io读写hadoop读写文件,都是使用org.apache.hadoop.fs.FileSystem.open一个文件,如果是hdfs文件,就有hdfs://开头的文件url,如果是本地文件,就是file://开头的文件url。所以每个task的文件读写情况,都可以从FileSystem.getAllStatistics()获取,而hadoop使用FileSystemCounters记录了FileSystem的一切io读写大小,FileSystemCounters分析如下:
"FileSystemCounters:HDFS_BYTES_READ" job执行过程中,只有map端运行时,才从HDFS读取数据,这些数据不限于源文件内容,还包括所有map的split元数据。所以这个值应该比FileInputFormatCounters.BYTES_READ 要略大些。
"FileSystemCounters:HDFS_BYTES_WRITTEN" job执行过程中,累计写入HDFS的数据大小,reduce在执行完毕后,会写入到HDFS(存在只有map,没有reduce的情况,该情况是map执行完毕把结果写入到HDFS)。
"FileSystemCounters:FILE_BYTES_READ" 累计读取本地磁盘的文件数据大小,map和reduce端有排序,排序时需要读写本地文件。
"FileSystemCounters:FILE_BYTES_WRITTEN" 累计写入本地磁盘的文件数据大小,map和reduce端有排序,排序时需要读写本地文件,还有reduce做shuffle时,需要从map端拉取数据,也存在写入本地磁盘文件的情况。
附:FileSystemCounters相关代码:org.apache.hadoop.mapred.Task.updateResourceCounters--> org.apache.hadoop.mapred.Task.FileSystemStatisticUpdater.updateCounters
FileSystemCounters的counter对于io读写的数据,已经很齐全,但是hadoop还有一些细微的io读写的counter:
"File Input Format Counters:Bytes Read" job执行过程中,Map端从HDFS读取的输入的split的源文件内容大小,但是不包括map的split元数据,所以这个值和"FileSystemCounters:HDFS_BYTES_READ"略小,但是很接近。如果map输入的源文件是压缩文件,它的值只是压缩文件解压前的大小(附:代码位于org.apache.hadoop.mapred.MapTask.TrackedRecordReader.fileInputByteCounter)。
"Map-Reduce Framework:Map input bytes" job执行过程中,Map端从HDFS读取的输入的split的源文件内容大小,如果源文件是压缩文件,它的值是压缩文件解压后的大小(附:代码位于org.apache.hadoop.mapred.MapTask.TrackedRecordReader.inputByteCounter)。
"File Output Format Counters:Bytes Written" job执行过程中,会分为map和reduce,但是也可能存在只有map的情况,但是job执行完毕后,一般都要把结果写入到hdfs,该值是结果文件的大小,如果是压缩文件,它的值只是压缩文件解压前的大小(附:代码位于org.apache.hadoop.mapred.MapTask.DirectMapOutputCollector.fileOutputByteCounter和org.apache.hadoop.mapred.ReduceTask.NewTrackingRecordWriter.fileOutputByteCounter)。