前言
本文主要介绍以下内容:
DFSOutputStream里的一些重要方法的作用
DFSOutputStream里关于写Packet的一些有趣的配置项。
重要方法
abort: 终止这个输出流,并且释放这个流相关的所有系统资源。
newStreamForCreate: 生成一个用于创建文件的输出流。
initWritePacketSize: 用于确保配置的writePacketSize永远不要超过PacketReceiver.MAX_PACKET_SIZE(16MB)。
adjustChunkBoundary: 用于调整chunk的边界 。
adjustPacketChunkSize: 用于调整Packet的chunk size。是用于append操作的场景,调整要追加数据时,最后一个block的chunk位置。例如在append之前,最后一个block的最后一个chunk不满512字节(我们管它叫partial chunk),没有生成checksum,这时候就会调整chunksize,让append的下一个Packet只包含一个chunk来fill up这个partial chunk(setChecksumBufSize),append之后的数据和append之前的数据共同构成一个完整的chunk。
enqueueCurrentPacketFull: 当packet full的时候(达到了packet所能容纳的max chunk数或者getBytesCurBlock==blocksize时),就要把这个full packet尝试入队dataQueue。
endBlock: 如果遇到了block的边界,发送一个empty packet来指示block的结束,重置bytesCurBlock字段。
setCurrentPacketToEmpty: 创建一个empty packet 标记end of block。
enqueueCurrentPacket: 将DFSOutputStream的currentPacket变量指向的DFSPacket对象入队到关联的DataStreamer#dataQueue里。入队成功后,将currentPacket置为null。
关于chunk、packet的一些日志
2023-12-14 15:34:06,036 [main] INFO hdfs.DFSClient (DFSOutputStream.java:writeChunkPrepare(496)) - WriteChunk allocating new packet seqno=3, src=/f, packetSize=65016, chunksPerPacket=126, bytesCurBlock=9728, output stream=DFSOutputStream:blk_1073741825_1001
packetSize是65016字节。
每个packet里chunks个数是126个。
所以每个chunk的大小是:65016/126 = 516字节。(512字节的data + 4字节checksum)
解释一下这里为啥是126个。 结合dfs.client-write-packet-size
这个配置项65536来看。
65536首先要减去MAX_PACKET_HEEADER_LEN(=6),之后变成65530。
65530/516 等于126.99x,不够127个整Chunk。所以每个Packet有126个chunk。
有趣的一些配置项
第一个:dfs.client.write.max-packets-in-flight
, 默认值80。表示dataQueue和ackQueue里的DFSPacket个数和的上限值。 如果OutputStream写满一个packet的数据后,想要把这个DFSPacket入队到dataQueue里,就必须满足dataQueue和ackQueue里的DFSPacket个数小于等于80时才行,否则就wait,等待条件满足。
<property>
<name>dfs.client.write.max-packets-in-flight</name>
<value>80</value>
<description>
The maximum number of DFSPackets allowed in flight.
</description>
</property>
第二个:dfs.client-write-packet-size
,默认值65536(即64KB)。表示一个DFSPacket的size。
<property>
<name>dfs.client-write-packet-size</name>
<value>65536</value>
<description>Packet size for clients to write</description>
</property>
dfs.bytes-per-checksum
dfs.stream-buffer-size
dfs.data.transfer.max.packet.size