HDFS寫入監控鏈路調研設計

1. 背景:

    線上HDFS的DataNode中頻繁出現Slow write日誌

     

     從日誌分析來看,Slow write分爲write to mirror和write to disk兩類
     爲便於分析網絡或者磁盤寫入的情況,設計了HDFS的寫入監控鏈路,採集DataNode中出現的slow日誌收集,供後續分析。

 

2. HDFS的源碼分析

    下面從源碼角度簡要分析下HDFS的block寫入流程:

     

    如圖所示,寫入的大致流程如下:
      1) DFSClient通過Sender.writeBlock方法觸發一個寫數據塊請求;
      2) 該請求通過數據流管道傳送到每一個數據節點,最後一個數據節點回復請求確認,該確認消息通過數據流管道逆向送回DFSClient;
      3) DFSClient收到確認消息後,將待寫入的數據切分成若干個數據包(packet),然後依次向數據流管道發送這些數據包;
      4) 數據包首先到達DataNode1,寫入磁盤之後,再發送給DataNode2,依次類推;
      5) 當數據包到達DataNode3時,DataNode3會對數據包進行校驗,如果校驗成功,則發送確認消息,並且逆向通過數據流管道傳回DFSClient;
      6) 當所有的數據包都發送完畢之後,DFSClient會發送一個空的數據包標識當前數據快發送完畢,至此,整個數據塊流程發送完畢。

     寫入過程涉及到的主要類包括:

     1) DataNode啓動時會創建一個DataXceiverServer類用於監聽客戶端的讀寫請求:

         

          在其run方法中,對於每個客戶端連接創建一個DataXceiver用於處理讀寫請求。

     2) DataXceiver中寫入數據塊的邏輯在writeBlock方法中:

         首先創建一個blockReceiver對象:

         

         連接到下游節點:

         

         調用blockReceiver的receiveBlock方法接收數據塊

         

     3) BlockReceiver類負責接收上游的數據塊,保存到當前節點,並寫入到下游節點,核心邏輯在receiveBlock方法中:

         首先讀取packet至本地緩存

         

         寫入數據流到下一個節點:

         

         如果接收到了完整的數據塊,並且啓動了sync標識,則寫入數據到本地磁盤
         否則驗證數據包的校驗和

         

          將數據寫入本地磁盤

           

 

3.  寫入鏈路埋點設計

     DataNode中對以下四種slow情況(超過300ms)進行了warning:

1) Slow BlockReceiver write packet to mirror
2) Slow BlockReceiver write data to disk
3) Slow flushOrSync
4) Slow manageWriterOsCache

     爲了追蹤記錄這4種耗時情況,在BlockReceiver類中對這四種耗時的地方打印出日誌,字段格式如下:

{
  blkId: block的id
  time:  時間戳
  srcAddress: 當前節點地址
  dstAddress: 目標節點地址
  slowType: 四種slow的類型
  duration: slow write的耗時
}

     在BlockReceiver類中添加以下代碼打印日誌:

      

     將日誌打印到單獨的文件中,通過filebeat收集到kafka中,再通過spark-streaming寫入到es中,打印出的日誌如下圖所示:

     

     收集到es之後,通過相關的聚合條件可以查詢出不同slow write的耗時情況:

      

 

4. 部署方式:

    將修改後的hadoop源碼重新打包,得到hadoop-hdfs-2.6.0-cdh5.5.0.jar包,替換掉hadoop路徑中的jar包。

    在CDH的DataNode高級配置中的日誌記錄高級配置代碼段中添加以下配置:

log4j.appender.PACKET_TRACE=org.apache.log4j.RollingFileAppender
log4j.appender.PACKET_TRACE.Threshold=INFO
log4j.appender.PACKET_TRACE.File=${hadoop.log.dir}/packet_trace.log
log4j.appender.PACKET_TRACE.Append=true
log4j.appender.PACKET_TRACE.MaxFileSize=30MB
log4j.appender.PACKET_TRACE.MaxBackupIndex=10
log4j.appender.PACKET_TRACE.layout=org.apache.log4j.PatternLayout
 
log4j.logger.packet-trace = INFO, PACKET_TRACE
log4j.additivity.packet-trace = false

     重啓該DataNode,則日誌信息會記錄到packet_trace.log文件中。

     同時在該節點上部署filebeat,收集packet_trace.log文件的信息,寫入到kafka中。

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