HDFS1.0源代码解析—数据传输和接受的类BlockSender和BlockReceiver

2019-03-28 13:34|来源: 网络

本次主要介绍DN端进行数据传输和接受的类BlockSender和BlockReceiver,其中BlockSender是读取DN本地block数据传送回数据请求端,BlockReceiver是接受存储数据,写入到本地的block中。
首选介绍BlockSender的主要函数的作用:

构造函数

  1.  94       this.blockLength = datanode.data.getVisibleLength(block);  
  2.   
  3.  99         checksumIn = new DataInputStream(  
  4. 100                 new BufferedInputStream(datanode.data.getMetaDataInputStream(block),  
  5. 101                                         BUFFER_SIZE));  
  6.   
  7. 123       bytesPerChecksum = checksum.getBytesPerChecksum();  
  8.   
  9. 129       checksumSize = checksum.getChecksumSize();  
  10.   
  11. 145       offset = (startOffset - (startOffset % bytesPerChecksum));  
  12. 146       if (length >= 0) {  
  13. 147         // Make sure endOffset points to end of a checksumed chunk.   
  14. 148         long tmpLen = startOffset + length;  
  15. 149         if (tmpLen % bytesPerChecksum != 0) {  
  16. 150           tmpLen += (bytesPerChecksum - tmpLen % bytesPerChecksum);  
  17. 151         }  
  18. 152         if (tmpLen < endOffset) {  
  19. 153           endOffset = tmpLen;  
  20. 154         }  
  21. 155       }  
  22. 156  
  23. 157       // seek to the right offsets   
  24. 158       if (offset > 0) {  
  25. 159         long checksumSkip = (offset / bytesPerChecksum) * checksumSize;  
  26. 160         // note blockInStream is  seeked when created below   
  27. 161         if (checksumSkip > 0) {  
  28. 162           // Should we use seek() for checksum file as well?   
  29. 163           IOUtils.skipFully(checksumIn, checksumSkip);  
  30. 164         }  
  31. 165       }  
  32. 166       seqno = 0;  
  33. 167  
  34. 168       blockIn = datanode.data.getBlockInputStream(block, offset); // seek to offset  

在开始介绍构造函数之前,先说一下DN上每个block的存放形式,block以blk_3910275445015356807和blk_3910275445015356807_1001.meta这样的形式存在,第一个文件存储内容,第二个存储元信息,所以才读取block的时候需要读取这两个文件。

开始看一下构造函数的主要作用,94行获取block文件的长度,99行打开block对应的元信息文件,123行获取每个chunk的大小,129行获取chunksum的大小。那么chunk和chunksum是什么呢,这里需要介绍下DN传送和接受数据的特点,每次传输和接受一个package,每个package包含若干个chunk,每个chunk对应的元信息就是chunksum。有了这个背景知识就知道145行的含义了,我们要求读取的数据可以从任意位置开始,但是DN传送时却要从一个整的chunk开始,因为元信息就是按照chunk为单位计算和存储的,这个ooffset就是我们要求读取的位置和实际读取位置的一个偏移,这个需要传回客户端,根据这个值用户才不会多介绍数据。149和150行对应读取的末尾做同样的处理,但是这个地方为什么没有把多读取数据的偏移量返回呢,是因为我们既然已经知道了起始位置有知道了读取的长度,所以我们知道实际的末尾,即使传送的数据有多余信息也不会造成影响。163行是使读取的元信息的文件流移动到要读取的位置,168行是打开block文件,并将文件流偏移到读取的位置。

构造函数初始化完毕以后,再来看传送数据的主函数sendBlock

  1. 383   long sendBlock(DataOutputStream out, OutputStream baseStream,  
  2. 384                  BlockTransferThrottler throttler) throws IOException {  
  3.   
  4. 396       try {  
  5. 397         checksum.writeHeader(out);  
  6. 398         if ( chunkOffsetOK ) {  
  7. 399           out.writeLong( offset );  
  8. 400         }  
  9.   
  10. 433       ByteBuffer pktBuf = ByteBuffer.allocate(pktSize);  
  11. 434  
  12. 435       while (endOffset > offset) {  
  13. 436         long len = sendChunks(pktBuf, maxChunksPerPacket,  
  14. 437                               streamForSendChunks);  
  15. 438         offset += len;  
  16. 439         totalRead += len + ((len + bytesPerChecksum - 1)/bytesPerChecksum*  
  17. 440                             checksumSize);  
  18. 441         seqno++;  
  19. 442       }  
  20. 443       try {  
  21. 444         out.writeInt(0); // mark the end of block   
  22. 445         out.flush();  

397行是首先传送一些元数据信息,399传送读取数据时多余的偏移,433行声明读取数据的缓冲区,436调用另外一个函数真正进行数据的传输,每次传送一个package,444行传送一个0表示传送结束。

相关问答

更多
  • 记得以前做项目的时候 有这方面的 一种是点对点的传输吧 另外是共享式的 及服务器客户端这种类型的 只接触过这两种 其他的应该还有吧
  • 请参阅苹果指南,您将看到需要连接更新请求来加速连接。 https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf 我有最小= 20ms最大40毫秒 我希望我能帮忙 罗马 see at the guidlines of apple and you will see that a connection update request is required to speed up your connection. https: ...
  • 数据传输对象是用于封装数据并将其从应用程序的一个子系统发送到另一个的对象。 DTO最常用于N层应用程序中的服务层,用于在其层与UI层之间传输数据。 这里的主要优点是减少了需要在分布式应用程序中通过电线发送的数据量。 他们也在MVC模式中做出了很好的模型。 DTO的另一个用途可以是封装方法调用的参数。 如果方法需要超过4或5个参数,这将非常有用。 使用DTO模式时,您也可以使用DTO汇编器。 汇编器用于从Domain Objects创建DTO,反之亦然。 从Domain Object到DTO的转换可能是一个昂 ...
  • 我认为更多的背景会对此有所帮助。 匿名类型具有方法范围。 所以这意味着,它不能通过它的方法传递。 而数据传输对象在人生中的全部目的是通过它的方法传递的。 我怀疑他们通过匿名类型创建数据传输类型,然后将其投影到数据传输对象。 但是,包括你在这个词中找到的这句话对你有帮助。 I think some more context would help here. An anonymous type has method scope. So this means, it cannot be passed outsid ...
  • 您想要这样做: 与活动进行通信 您在本教程中所做的只是实现一个包含所需回调的接口。 所以你几乎就在那里。 至于做你的计算。 您应该将其保留在适当的片段中,除非您的Activity将要使用多个片段。 如果密集,请使用Loaders将其从UI线程中删除 。 You want to do this: Communicating with Activities All you're doing in the tutorial is implementing an interface with the callbac ...
  • HTTP over TLS很好。 而且,由于已经有相当多的工具,它应该是一个相当简单而富有成效的方法。 HTTP over TLS is fine. And, since there is already quite a bit of tooling around it, it should be quite an easy and productive approach.
  • Apache NiFi提供站点到站点功能,用于在两个实例之间传输数据。 你可以在这里读到它: https://nifi.apache.org/docs/nifi-docs/html/user-guide.html#site-to-site Apache NiFi provides the site-to-site feature for transferring data between two instances. You can read about it here: https://nifi.apac ...
  • 使用NUTCH 使用卡夫卡水槽 使用spring xd scrapper import.io 生产者消费者的java程序 Using NUTCH Using Kafka flume Using spring xd scrapper import.io java program by producer consumer
  • 我将在tomcat上启用访问日志记录 ,并确保这不是来自tomcat的数据。 您应该能够总结访问日志中的流量并确定tomcat是否为源。 我假设您没有前面的apache ,并且您正在使用Elastic Load Balancer将80转换为8080? 如果您确实在前面有apache或类似的,那么也启用访问日志记录。 不要在端口80上以root身份运行tomcat。 您在设置中使用了哪些其他组件? 检查这不是一些自动备份解决方案! 希望这可以帮助, I'd enable access logging on t ...