Datanode本质上也是TCPServer,一般的TCPServer接到客户端请求以后会分配一个线程处理,对于Datanode而言,这个线程可以叫做Op处理线程。每个OP线程会多次和客户端交互,中间涉及多种packet。
Op线程
写在前面
写在前面,关于proto writeDelimitedTo方法
在整个处理流程中,会非常频繁的使用的到proto.writeDelimitedTo来传递相关proto,简单理解就是要写入proto时,写入总长度,再写入proto。读取proto时,先读取长度,在解析proto。
第一个包
Op线程第一个包总是来定义Op线程处理那种Op,例如读块op,写块op。这种包简单命名为OpPacket。
OpPacket的Request:
DataTransferProtocol.DATA_TRANSFER_VERSION:short,3.1.1版本默认为28,
OpCode:
OpProto:定义Op是哪种Op。Op在datatransfer.proto定义,包含OpReadBlockProto,OpWriteBlockProto,OpTransferBlockProto,OpReplaceBlockProto,OpCopyBlockProto,OpBlockChecksumProto,OpRequestShortCircuitAccessProto,ReleaseShortCircuitAccessRequestProto。
OpPacket的Response:
BlockOpResponseProto.writeDelimitedTo。
后续的包
后续的包根据不同的Op处理也不同。
ReadBlock:
DataNode写完第一个包的应答以后,立马会发送Block的数据包,数据包的结果如下:
PktLen:数据包长度,不同于字面意思,这个数值并不是包的总长度,而是4(pktLen所占字节数)+chunkchecksums字节数+chunkdatas字节数。
HeadLen:short,PacketHeaderProto的长度。不同于writeDelimitedTo,这边使用的proto.getSerializedSize。
PktHeadProto:PacketHeaderProto.writeTo。
Chunkchecksums:chunk校验数据。
ChunkData:实际数据。
数据会被分成多个数据包发送,发送完最后一个数据包以后,会发送一个空包(没有数据只有header),空包的PacketHeaderProto会有LastPackctInBlock的标记。空包发送完成后,会接受一个ClientReadStatusProto的包(客户端使用ClientReadStatusProto.writeDelimitedTo写入)。
WriteBlock:
当客户端接受BlockOpResponseProto后,就会发送数据包,数据包的格式和read相同。DataNode接受到数据以后,完成checksum后就把Status.success放入Responder的处理队列。Responder最终会返回PipelineAckProto(PipelineAckProto.writeDelimitedTo)给客户端。
还有很多后续包例如TransferBlock和ReplaceBlock,读者可以自行阅读。