hadoop DataNode实现分析
在前面说hadoop整体实现的时候, 说过DataNode的需要完成的首要任务是K-V存储。

第二个功能是 完成和namenode 通信 ,这个通过IPC 心跳连接实现。此外还有和客户端 其它datanode之前的信息交换。
第 三个功能是 完成和客户端还有其它节点的大规模通信,这个需要直接通过socket 协议实现。
下面开始分析源代码,看看DataNode是如何实现这些功能的。
分析代码采取自定向下的分析方式, 看看代码中做了啥,然后分析这些代码的作用。
首先看Datanode实现的接口。
- public class DataNode extends Configured
- implements InterDatanodeProtocol, ClientDatanodeProtocol, FSConstants,
- Runnable, DataNodeMXBean {
它实现了 InterDatanodeProtocol, ClientDatanodeProtocol, 这两个重要接口。 作用和之前分析haoop IPC的时候提到过, 为了是客户端 和其它datanode节点远程调用本dataNode节点方法的时候,提供方法实际运行的对象。
我们可以看到它并没有实现和datanode的接口,因为datanode是主动和nameNode联系,nameNode从来不会主动调用dataNode上的方法。
在main 方法中主要 通过一系列调用创建了datanode对象。
之后datanode的初始化工作主要由 startDataNode()来完成, 这是一个很复杂的方法,我们来一点一点的分析。
- void startDataNode(Configuration conf,
- AbstractList<File> dataDirs, SecureResources resources
- ) throws IOException {
- if(UserGroupInformation.isSecurityEnabled() && resources == null)
- throw new RuntimeException("Cannot start secure cluster without " +
- "privileged resources.");
- // connect to name node
- this.namenode = (DatanodeProtocol)
- RPC.waitForProxy(DatanodeProtocol.class,
- DatanodeProtocol.versionID,
- nameNodeAddr,
- conf);
- 这个是通过反射获取同dataNode节点通信的代理对象
- // get version and id info from the name-node
- NamespaceInfo nsInfo = handshake(); //立刻与名字节点通信
- StartupOption startOpt = getStartupOption(conf);
- assert startOpt != null : "Startup option must be set.";
- storage.recoverTransitionRead(nsInfo, dataDirs, startOpt);
- // adjust
- this.dnRegistration.setStorageInfo(storage);
- // initialize data node internal structure
- this.data = new FSDataset(storage, conf);
- // 创建数据存储KV 的对象 这个后面还要再细分析。
- }
- this.threadGroup = new ThreadGroup("dataXceiverServer");
- this.dataXceiverServer = new Daemon(threadGroup,
- new DataXceiverServer(ss, conf, this));
- this.threadGroup.setDaemon(true); // 创建流接口服务器 DataXServer 这个需要后面再分析
- ipcServer = RPC.getServer(this, ipcAddr.getHostName(), ipcAddr.getPort(),
- conf.getInt("dfs.datanode.handler.count", 3), false, conf, //创建IPC服务器。
- blockTokenSecretManager);
- }
上面代码分析中我们留了两个之后还要分析的方法,现在来看一下。
第一个是FsdataSet.
我们需要考虑的问题是 hadoop以64M大小为单位作为一个文件的大小 存储在linux 文件系统 上。 当文件多了,就有一个效率问题,同一个文件夹下有过多的文件
和文件目录过深都不利于检索速度(这个与linux文件系统inode结构有关,这里暂不讨论这个) 。所以我们这里要设计一个结构 需要创建文件夹 但文件夹目录不能过深。
此外 hadoop 还考虑了一个优化问题,如果一个datanode节点上插有多块硬盘的话,怎么提高并行吞吐量。好,有了这些我们来看具体实现。

一个FSdir对于着一个存储目录,一个FSVolume 对应着一个用户配置的数据目录(应该为一个磁盘最好) FsVolumeSet存储着所有的FSVolume对象。
在FsDataSet中海油一个最重要的成员变量,volumeMap 就是这个成员变量存储了 每一个Block 和它对应的存储路径等信息。
- HashMap<Block,DatanodeBlockInfo> volumeMap = new HashMap<Block, DatanodeBlockInfo>();;
第二个是 DataXServer
当往数据节点中填入数据或者数据节点之间做负载均衡的时候显然无法 使用Hdoop IPC 因为hadoop的IPC 在socket之上封装了方法的调用,如果在这之上封装一个大规模数据传输的方法,显然效率上不如直接用socket通信。
- ServerSocket ss;
- if(secureResources == null) {
- ss = (socketWriteTimeout > 0) ?
- ServerSocketChannel.open().socket() : new ServerSocket();
- Server.bind(ss, socAddr, 0);
- } else {
- ss = resources.getStreamingSocket();
- }
- ss.setReceiveBufferSize(DEFAULT_DATA_SOCKET_SIZE);
- //初始化处理类dataXceiverServer
- this.threadGroup = new ThreadGroup("dataXceiverServer");
- this.dataXceiverServer = new Daemon(threadGroup, new DataXceiverServer(ss, conf, this));
- this.threadGroup.setDaemon(true); // auto destroy when empty
DataXceiverServer 是个线程 我们看一下它的ruan方法
- Socket s = ss.accept();
- s.setTcpNoDelay(true);
- new Daemon(datanode.threadGroup,
- new DataXceiver(s, datanode, this)).start();
我们再看一下 DataXceiver的run方法
- public void run() {
- DataInputStream in=null;
- try {
- in = new DataInputStream(
- new BufferedInputStream(NetUtils.getInputStream(s),
- SMALL_BUFFER_SIZE));
- short version = in.readShort();
- if ( version != DataTransferProtocol.DATA_TRANSFER_VERSION ) {
- throw new IOException( "Version Mismatch" );
- }
- boolean local = s.getInetAddress().equals(s.getLocalAddress());
- byte op = in.readByte();
- // Make sure the xciver count is not exceeded
- int curXceiverCount = datanode.getXceiverCount();
- if (curXceiverCount > dataXceiverServer.maxXceiverCount) {
- throw new IOException("xceiverCount " + curXceiverCount
- + " exceeds the limit of concurrent xcievers "
- + dataXceiverServer.maxXceiverCount);
- }
- long startTime = DataNode.now();
- switch ( op ) {
- case DataTransferProtocol.OP_READ_BLOCK:
- readBlock( in );
- datanode.myMetrics.addReadBlockOp(DataNode.now() - startTime);
- if (local)
- datanode.myMetrics.incrReadsFromLocalClient();
- else
- datanode.myMetrics.incrReadsFromRemoteClient();
- break;
- case DataTransferProtocol.OP_WRITE_BLOCK:
- writeBlock( in );
- datanode.myMetrics.addWriteBlockOp(DataNode.now() - startTime);
- if (local)
- datanode.myMetrics.incrWritesFromLocalClient();
- else
- datanode.myMetrics.incrWritesFromRemoteClient();
- break;
- case DataTransferProtocol.OP_REPLACE_BLOCK: // for balancing purpose; send to a destination
- replaceBlock(in);
- datanode.myMetrics.addReplaceBlockOp(DataNode.now() - startTime);
- break;
- case DataTransferProtocol.OP_COPY_BLOCK:
- // for balancing purpose; send to a proxy source
- copyBlock(in);
- datanode.myMetrics.addCopyBlockOp(DataNode.now() - startTime);
- break;
- case DataTransferProtocol.OP_BLOCK_CHECKSUM: //get the checksum of a block
- getBlockChecksum(in);
- datanode.myMetrics.addBlockChecksumOp(DataNode.now() - startTime);
- break;
- default:
- throw new IOException("Unknown opcode " + op + " in data stream");
- }
- } catch (Throwable t) {
- LOG.error(datanode.dnRegistration + ":DataXceiver",t);
- } finally {
- LOG.debug(datanode.dnRegistration + ":Number of active connections is: "
- + datanode.getXceiverCount());
- IOUtils.closeStream(in);
- IOUtils.closeSocket(s);
- dataXceiverServer.childSockets.remove(s);
- }
- }
重点在这句
- byte op = in.readByte();
应该是根据流中的事先约定 来 第一个字节 来决定是
hadoop DataNode实现分析的更多相关文章
- hadoop源码分析(2):Map-Reduce的过程解析
一.客户端 Map-Reduce的过程首先是由客户端提交一个任务开始的. 提交任务主要是通过JobClient.runJob(JobConf)静态函数实现的: public static Runnin ...
- Hadoop启动脚本分析
Hadoop启动脚本分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 能看到这篇博客的你估计对Hadoop已经有一个系统的了解了,最起码各种搭建方式你应该是会的,不会也没有关系, ...
- Hadoop源码分析之数据节点的握手,注册,上报数据块和心跳
转自:http://www.it165.net/admin/html/201402/2382.html 在上一篇文章Hadoop源码分析之DataNode的启动与停止中分析了DataNode节点的启动 ...
- 4. hadoop启动脚本分析
4. hadoop启动脚本分析 1. hadoop的端口 ``` 50070 //namenode http port 50075 //datanode http port 50090 //2name ...
- Hadoop Datanode节点无法启动(All directories in dfs.data.dir are invalid)
Hadoop Datanode节点无法启动(All directories in dfs.data.dir are invalid) java.io.IOException: All director ...
- Hadoop DataNode不能正常工作的原因
在把Hadoop环境搭建成功,并且也Hadoop的各个组件都正常工作.在重启过几次Hadoop后发现DataNode不能正常工作,打开Hadoop 的后台http://localhost:50030和 ...
- hadoop编程:分析CSDN注冊邮箱分布情况
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/jdh99/article/details/37565825 hadoop编程:分析CSDN注冊邮箱分 ...
- hadoop datanode 和 tasktracker起不来
本篇文章主要介绍了"hadoop datanode 和 tasktracker起不来.",主要涉及到hadoop datanode 和 tasktracker起不来.方面的内容,对 ...
- 【Hadoop】Hadoop DataNode节点超时时间设置
hadoop datanode节点超时时间设置 datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间 ...
随机推荐
- ZOJ3238 Water Ring(计算几何)
题意:给你一个圆形和很多个矩形,然后要你求圆形的圆周有多少被矩形覆盖. 思路:比赛的时候是有思路的了,不过一直在调别的题,最后剩下30分钟肯定来不及敲.想法是这样的,要是我们可以求出每个矩形覆盖了圆周 ...
- C# 枚举类型操作
//定义一个枚举 public enum Colors { Red, Green, Blue, Yellow }; //根据key找value string name = Enum.GetName(t ...
- error LNK2019: 无法解析的外部符号 ___glutInitWithExit@12,该符号在函数 _glutInit_ATEXIT_HACK@8 中被引用 1>GEARS.obj : er
转: http://blog.csdn.net/bill_ming/article/details/8150111 opengl的高级菜鸟问题 看了一本书<OpenGL三维图形系统开发与应用技术 ...
- How to say "no"?
How to say "no"?7招教你如何拒绝别人 Do you have a hard time saying no to others? Do you say “y ...
- Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏
原文:Codelab for Android Design Support Library used in I/O Rewind Bangkok session--Make your app fanc ...
- 可扩展Web架构与分布式系统
原文:可扩展Web架构与分布式系统 开放源代码已经成为一些大型网站的基本原则.而在这些网站成长的过程中,一些优秀的实践经验和规则也出现在他们的结构中.本文旨在介绍一些在大型网站结构设计的过程中需要注意 ...
- Find K most Frequent items in array
给定一个String数组,求K个出现最频繁的数. 记录一下查到的资料和思路: 1. 使用heap sorting, 先用hashmap求出单词和词频.需要额外建立一个class Node,把单词和词频 ...
- 从一个前端项目实践 Git flow 的流程与参考
Git flow 出自 A successful Git branching model,这里使用了一个前端项目配合本文稿实施了 git flow 并记录流程作出示例和参考,对 hotfix 与持续部 ...
- Ubuntu对FireFox安装flash插件
有时候我们需要在Ubuntu下采用手动安装一些软件,比如Firefox的Flash插件.Adobe® Flash® Player 是一款轻量级浏览器插件,具有丰富的 Internet 应用运行时间,提 ...
- Java @override报错的解决方法
在eclipse中导入工程后@Overide报错 到入工程后,所有的@Override都报如下错误: Multiple markers at this line - The method getCou ...