基於計算機資源分析hadoop的默認counter

前言

由於項目中,需要統計每個業務組使用的計算機資源,如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框架,自行產生網絡通信,這部分流量是無法被統計。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章