Datanode中包含DataXceiverServer。DataXceiverServer是一個socket server,負責接收client發起的socket連接。DataXceiverServer接收到一個socket連接後,啓動一個線程DataXceiver,由DataXceiver具體負責該scoket的處理。DataXceiver從client讀取client想要進行操作的操作碼。如果操作碼是OP_READ_BLOCK,則DataXceiver負責讀取該block,並將其發送給client。
讀取block數據傳輸格式
Client爲了從Datanode讀取block,按照一定的格式向Datanode發送指令及其他一些數據,具體的格式如下:
Ø operator:byte Client所需要的操作,讀取一個block、寫入一個block等等Ø version:short Client所需要的數據與Datanode所提供數據的版本是否一致
Ø blockId:long 所要讀取block的blockId
Ø generationStamp:long 所需要讀取block的generationStamp
Ø startOffset:long 讀取block的的起始位置
Ø length:long 讀取block的長度
Ø clientName:String Client的名字
Ø accessToken:Token Client提供的驗證信息,用戶名密碼等
讀取過程
DataXceiver首先按照上面的數據格式依次讀取各變量。讀取完成後,如果需要進行訪問控制,則根據Client提供的accessToken進行驗證。驗證通過後,產生一個BlockSender實例blockSender,通過blockSender進行數據的讀取與傳輸。這裏有一個需要注意的地方,HDFS在保存文件的時候有幾個非常重要的概念:一個文件由多個block構成。HDFS在進行block讀寫的時候是以packet爲單位進行的。每一個packet由若干個chunk組成。Chunk是進行數據校驗的基本單位,對每一個chunk生成一個校驗和並將校驗和進行存儲(在默認情況下一個chunk的大小是512byte,生成的校驗和是4byte)。在讀取一個block的時候,數據傳輸的基本單位是packet,每個packet由若干個chunk組成。
爲了讀取一個block,首先從block的.meta文件中讀取block的版本號、校驗類型等,並生成相應的校驗工具類。Meta文件的格式如下所示:
Ø version:short 所保存block的版本號
Ø checksumType:int 校驗碼的類型,要麼沒有校驗碼,要麼是CRC32校驗碼(CHECKSUM_NULL、CHECKSUM_CRC32)
Ø bytesPerChecksum:int 表示這麼校驗和是由多少byte的源數據計算而來
Ø checksum:每一個chunk的校驗和
這裏有一個需要注意的地方,當讀取數據的時候讀取的起始位置必行是一個chunk的起始位置,如果client讀取的起始位置不是chunk的起始位置,那麼必須回退到chunk的起始位置開始讀取。確定好位置後,Datanode以packet爲單位依次發送block的數據,packet的具體格式如下圖所示:
Ø packetLen:int packet的長度,包括數據、數據的校驗等等
Ø offset:long packet在block中的偏移量
Ø sequenceNum:long 該packet在這次block讀取時的序號
Ø isLastPacket:byte packet是否是最後一個
Ø dataLen:int 該packet所包含block數據的長度,純數據不包括校驗和其他
Ø checksum:該packet每一個chunk的校驗和,有多少個chunk就有多少個校驗和
Ø data:該packet所包含的block數據