NameNode.create() 請求創建文件,獲取 DataNode 列表DataStreamer 線程,主線程讀取本地數據封裝為 Packet 放入 dataQueueDataStreamer 從隊列取 Packet,建立 BlockOutputStream 連接首個 DataNode,發送 DATA_TRANSFER_HEADERResponseProcessor 線程接收 ACK 確認

// Header 結構
DataTransferProtocol.DATA_TRANSFER_VERSION // 版本號
DataTransferProtocol.OP_WRITE_BLOCK // 操作類型
blockId, generationStamp, ... // 元數據
// Packet 結構
packetLen, offsetInBlock, seqno, lastPacketInBlock, dataLen
dataBytes...
checksumBytes (CRC32, 每 512 字節一個 checksum)
核心類:BlockReader(Hadoop 2.x 為 RemoteBlockReader2)
// 1. 建立 Socket 連接
Socket sock = new Socket(dnAddr, dnPort);
DataOutputStream out = new DataOutputStream(sock.getOutputStream());
// 2. 發送 Read Request Header
out.writeShort(DataTransferProtocol.DATA_TRANSFER_VERSION);
out.write(DataTransferProtocol.OP_READ_BLOCK);
out.writeLong(blockId);
out.writeLong(genStamp);
out.writeLong(startOffset);
out.writeLong(len);
Text.writeString(out, clientName);
out.flush();
// 3. 讀取 Response Header
DataInputStream in = new DataInputStream(sock.getInputStream());
short status = in.readShort(); // OP_STATUS_SUCCESS = 0
// 4. 讀取 Checksum 信息
DataChecksum checksum = DataChecksum.newDataChecksum(in);
// 默認:512 字節/Chunk,4 字節 CRC32
// 5. 讀取首個 Chunk 偏移量
long firstChunkOffset = in.readLong();
while (bytesNeeded > 0) {
int packetLen = in.readInt();
long offsetInBlock = in.readLong();
long seqno = in.readLong();
boolean lastPacketInBlock = in.readBoolean();
int dataLen = in.readInt();
// 讀取 checksum
IOUtils.readFully(in, checksumBytes.array(), 0, checksumBytes.limit());
// 讀取實際數據
IOUtils.readFully(in, buf, offset, chunkLen);
// 校驗 checksum
FSInputChecker.verifySum(chunkPos);
}