前言
由於項目中,需要統計每個業務組使用的電腦資源,如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)。
但是這些細微的counter,沒有統計map和reduce排序時檔案讀寫的情況,所以要衡量job任務的io讀寫情況,我覺得最合適的還是使用FileSystemCounters的counter。
io讀寫流量大致可以通過上述FileSystemCounters四個參數求和而得,存在不足就是:
"FileSystemCounters:HDFS_BYTES_WRITTEN",它只是一個副本的hdfs的寫入大小,而hdfs的塊副本是可以調整的,所以io讀寫流量,還需要"FileSystemCounters:HDFS_BYTES_WRITTEN" * 副本數。
map和reduce都是使用者自訂的,存在可能是使用者代碼繞過hadoop架構,不使用org.apache.hadoop.fs.FileSystem.open檔案,這部分io讀寫流量,是無法被統計的。
網路流量
hadoop任務產生網路流量的階段:map輸入從hdfs拉取資料,reduce shuffle時從map端拉取資料,reduce完成往hdfs寫入結果(如果沒有reduce,就是map完成往hdfs寫入結果)。
job和hdfs互動產生的流量,可以通過io讀寫分析的兩個counter擷取:"FileSystemCounters:HDFS_BYTES_READ"和"FileSystemCounters:HDFS_BYTES_WRITTEN"
而reduce shuffle時從map端拉取資料產生的流量,對應的counter是:
"Map-Reduce Framework:Reduce shuffle bytes" 它是reduce往map拉取中間結果的累計資料大小,如果map產生的中間結果是壓縮檔,它的值是壓縮檔解壓前的大小(附:代碼位於 org.apache.hadoop.mapred.ReduceTask.reduceShuffleBytes)。
網路流量大致可以通過上述三個參數求和而得,存在不足就是:
"FileSystemCounters:HDFS_BYTES_READ"和"FileSystemCounters:HDFS_BYTES_WRITTEN",它沒有考慮hadoop對hdfs的本地化最佳化,hdfs讀寫塊時,如果發現用戶端和目標塊在同一個節點,會直接通過本地讀寫,有些塊如果在本地,hadoop會直接通過本地檔案系統讀寫,不通過網路讀寫。
"FileSystemCounters:HDFS_BYTES_WRITTEN",它只是一個副本的hdfs的寫入大小,而hdfs的塊副本是可以調整的,所以網路流量,還需要"FileSystemCounters:HDFS_BYTES_WRITTEN" * 副本數。
map和reduce都是使用者自訂的,存在可能是使用者代碼繞過hadoop架構,自行產生網路通訊,這部分流量是無法被統計。
參考資料 http://www.cnblogs.com/xuxm2007/archive/2012/06/15/2551030.html