上一篇文章忘了提了,这一组博客是我为了要做一个hdfs的项目,对hadoop学习的一组文章。并且只关注了我觉得会用到的API和相关流程,主要是了解DFSClient的工作过程,涉及到DFSClient与NN和DN的通信。以前没有用过java,只了解一些基本语法,对hadoop的了解也比较粗浅,如果有什么理解错误的地方,希望看到这个博客的人能给我指出来,先谢过了。
这次看的问题是如何从Datanode中读取一个block?
之前看过http://blog.jeoygin.org/category/technology/hadoop上的一组博客,学习了一下hadoop0.20.2的结构,但是2.2.0上很多代码结构已经有了特别大的变化。下面记录一下读取一个block的主要过程。
1.Client向DN发出读取block的请求,操作码在Op.java中定义。
2.DN的DataXceiverServer.java接到请求后,启动一个DataXceiver.java线程,处理实际请求。
3.DataXceiver.java的run() -> readOp()得到操作码。
4.run()->processOp()调用相应的函数,对于读取block调用的就是opReadBlock()
5.opReadBlock()通过protobuffer解析输入参数然后调用readBlock()
public void readBlock(final ExtendedBlock block,
final Token<BlockTokenIdentifier> blockToken,
final String clientName,
final long blockOffset,
final long length,
final boolean sendChecksum,
final CachingStrategy cachingStrategy) throws IOException {
...
BlockSender blockSender = null;
...
try {
try {
blockSender = new BlockSender(block, blockOffset, length,
true, false, sendChecksum, datanode, clientTraceFmt,
cachingStrategy);
} catch(IOException e) {
...
}
// send op status
writeSuccessWithChecksumInfo(blockSender, new DataOutputStream(getOutputStream()));
long read = blockSender.sendBlock(out, baseStream, null); // send data
...
} catch ( SocketException ignored ) {
...
}
...
}
6.重点在BlockSender.java中,看的还比较粗略
1) BlockSender发送的数据格式
+-----------------------------------------------------------------------+
| ChecksumHeader | Sequence of data PACKETS... |
+-----------------------------------------------------------------------+
ChecksumHeader = CHECKSUM_TYPE(1 byte) + BYTES_PER_CHECKSUM(4 bytes)
PACKET = packet header + checksum(x bytes) + data(BUFFER_SIZE bytes).
data是有chunk构成,x = data的chunk数量取上界 * CHECKSUM_SIZE
CHECKSUM_SIZE取决于checksum类型,CRC32是4bytes
client在读到LastPacketInBlock置为true的packet或者一个空packet的时候结束传输,返回OP_STATUS_CHECKSUM_OK给DN
2) 构造函数
输入参数:
block: 读取的blockstartOffset: 开始读取的偏移值
length: 读取的数据长度
corruptChecksumOk:verifyChecksum: 读取数据的时候是否验证校验码sendChecksum: 是否发送checksum给clientdatanode: block所在的datanodeclientTraceFmt: client记录log的格式
过程:
1.cache相关,略过
2.获取block的一个replica,如果block正在被写,则等待3s,如果需要访问的部分(startOffset+length)还不能够获取,则报错
3.检验replica的时间戳和可见性
4.根据replica,得到block的checksum,meta_file不存在的时候,生成一个新的checksum,不影响传输
5.根据checksum,得到chunksize,默认值为10M
6.根据读取block的偏移,设置checksumIn和blockIn的偏移位置
3) sendBlock
过程:
1.根据是否设置transferTo,分配packet的大小
2.循环调用sendPacket发送packet
3.检查线程是否被中断,没有被中断的话,关闭out,sentEntireByteRange = true,完成。
4) sendPacket
输入参数:
pkt 写入packet数据的缓冲区
maxChunks 最大chunk数
out stream to send data to
transferTo 是否使用transferTo的传输方式
throttler 调节传输带宽
过程:
1.按顺序写入header,checksum部分
2.如果不使用transferTo方式的话,写入data部分,需要的话,校验一下。
3.发送数据,transferTo的方式只发送header和checksum,估计是为了跳读吧。还不太清楚