标签:
1、Hadoop的包的功能分析
2、由于Hadoop的MapReduce和HDFS都有通信的需求,需要对通信的对象进行序列化。Hadoop并没有采用java的序列化,而是引入它自己的系统。org.apache.hadoop.io中定义了大量的可序列化对象,他们都实现了Writable接口。
3、介绍完org.apache.hadoop.io以后,我们开始来分析org.apache.hadoop.ipc。RPC采用客户机/服务器模式。
4、既然是RPC,自然就用客户端和服务端,当然,org.apache.hadoop.ipc也就有了类Client和类Server。在这里我们仔细考察org.apache.hadoop.ipc.Client。下面的图包含了org.apche.hadoop.ipc.Client中的关键类和关键方法。
5、聊完了Client聊Server,按惯例,先把类图贴出来。需要注意的是,这里的Server类是一个抽象类,唯一抽象的地方就是call方法。
6、有了Client和Server,很自然就能RPC啦。下面轮到RPC.java啦。
7、一个典型的HDFS系统包含一个NameNode和多个DataNode。NameNode维护名字空间;而DataNode存储数据块。
下面我们就来具体分析一下DataNode的实现。
8、在继续分析DataNode之前,我们有必要看一下系统的工作状态。大家先理解一下上面的状态图,它是下面我们要介绍DataNode的基础。
9、我们来看一下升级、回滚、提交的时候DataNode上会发生什么。
10、分析完Storage相关的类以后,我们来看下一个大家伙,FSDataset相关的类。
上面介绍Storage时,我们并没有涉及数据块Block的操作,所有和数据块相关的操作,都在FSDataset相关的类中进行处理。下面是类图。
11、通过上面的一系列的介绍,我们知道了DataNode工作时的文件结构和文件结构在内存中对应的对象。下面我们可以来分析DataNode上的动态行为。首先我们来分析DataXceiverServer和DataXceiver。DataNode上数据块的接受、发送并没有采用我们前面介绍的RPC机制,原因和简单,RPC是一个命令式接口,而DataNode处理数据部分,往往是一种流式机制。DataXceiverServe和DataXceiver就是这个机制的实现。其中,DataXceiver还依赖两个辅助类:BlockSender和BlockReceiver。下面是类图。
12、继续DataXceiver分析,下一块硬骨头是写数据。HDFS的写数据操作,笔读数据复制N多倍。我们先来看一下写数据的请求。接下来的处理就是数据处理和校验,并分别写到数据块文件和数据块元文件。
13、DataXceiver支持的六条操作,我们已经分析完最重要的两条。剩下的分别是:读取数据块元文件,替换一个数据块,拷贝一个数据块,读取数据块校验码。我们逐个讨论。
14、通过上面的讨论,DataNoda上读、写流程已经基本清楚了,我们来看下一个非主流程,DataBlockScanner用于定时对数据块进行校验。类图如下:
15、周围障碍扫清以后,我们可以开始分析类DataNodde。类图如下:
16、DataNode的介绍告一段落。我们开始分析NameNode。相比DataNode,NameNode比较复杂,系统中只有一个NameNode,做
为系统文件目录的管理者和“inode”表。为了提高可用性,系统中还存在着 从NameNode。
先前我们分析DataNode的时候,关注的是数据块。NameNode作为HDFS中文件目录和文件分配的管理者,它保存的最重要的信息,就是下面两个映射:
文件名->数据块
数据块->DataNode列表
17、我们先分析INode.java,类INode抽象了文件层次结构。如果我们对文件系统进行面向对象的抽象,一定会得到和下面一样的雷士的结构图(类INode):INode是一个抽象类,它的两个子类,分别对应着目录(INodeDirectory)和文件(INodeFile)。
18、前面我们提过关系:文件名->数据块持久化在磁盘上,所有对目录树的更新和文件名->数据块关系的修改,都必须能够持久化,为了保证每次修改不需要重新保存整个结构,HDFS使用操作日志,保存更新。
19、我们来分析FSEditLog.java,该类提供了NameNode操作日志和日志文件的相关方法,相关类图如下:通过上面的分析,我们应该清楚日志文件里记录了哪些信息。
20、我们开始对租约Lease进行分析,下面是类图。Lease是可以认为是一个文件写锁,当客户端需要写文件的时候,它需要申请一个Lease,NameNode负责记录哪个文件上有Lease,Lease的客户是谁,超时时间等,所有这些工作由下面三个类来完成
21、下面我们来分析FSDirectory。其实分析FSDirectory最好的地方,应该是在介绍完INode以后,FSDirectory在INode的基础上,保存了HDFS的文件目录状态。系统加载FSImage时,FSImage会在FSDirectory对象上重新建立文件目录状态,HDFS文件目录状态的变化,也有FSDirectory写日志,同时,它保存了 文件名->数据块的映射关系。
22、下来轮到FSNameSystem出场了。FSNameSystem.java一共有4573行,而整个NameNode目录下所有的java程序共有16876行,把FSNameSystem搞定了,NameNode也就基本搞定。
FSNameSystem是NameNode实际记录信息的地方,保存在FSNameSystem中的数据有:
文件名->数据列表(存放在FSImage和日志中)
合法的数据块列表(上面的逆关系)
数据块->DataNode(只保存在内存中,根据DataNode发过来的信息建立)
DataNode上保存的数据块(上面关系的逆关系)
最近发送过心跳信息的DataNode(LRU)
我们先来分析FSNameSystem的成员变量。
23、继续对FSNameSystem进行分析。NameNode上的线程,分别对应DataNode心跳检查,租约检查,安全模式检查和数据块复制,我们会在后面介绍这些线程对应的功能。接下来是一堆系统参数,比方说系统每个DataNode节点容许的最大数据块数,心跳检查间隔时间等。。。。。。
SafeModeInfo的类图如下,
讨论完SafeModeInfo,我们来分析一下SafeModeMonitor,它用于定期检查系统是否能够离开安全模式(smmthread就是它的一个实例)。系统离开安全模式后,smmthread会被重新赋值为null。
24、private Host2NodesMap,定义了HDFS的网络拓扑外,
25、我们接下来分析NameNode.java的成员变量,然后两个类综合起来,分析它提供的接口,并配合上接口说明请求对应的处理流程。
下面我们来看NameNode的启动过程。main方法是系统的入口。
26、万事俱备,我们可以分析NameNode上的流程啦。
首先我们来看NameNode上实现的ClientProtocol,客户端通过这个接口可以对目录树进行操作,打开、关闭文件等。
27、软柿子都捏完了,我们开始啃硬骨头。前面已经分析过getBlockLocation,create,append,setReplication,setPermission和setOwner,接下来我们讨论和文件内容相关的操作。
28、下面是和目录树相关的操作。
下面是和其他系统维护管理的方法。
29、搞定ClientProtocol,接下来是DataNodeProtocol部分。接口如下:
有了上面这些基础,我们来看FSSystem.handlerHeartbeat的处理过程。
下面分析应答的命令式如何构造的。
30、继续对NameNode实现的接口做分析
目前为止,我们已经完成了对NameNode上的ClientProtocol和DatanodeProtocol的分析了,NamenodeProtocol,我们在理解NamenodeProtocol的时候,才会进行分析。
31、除了对外提供的接口,NameNode上还定义了一系列的线程,不断检查系统的状态,下面是这些线程的功能分析。
32、转战进入Secondary NameNode,前面的分析我们也把他称为 从NameNode,从NameNode在HDFS里是个小配角。
跟Secondary NameNode有关系的类不是很多,如下图。
首先要讨论的是NameNode和Secondary NameNode间的通信。NameNode上实现了接口NameNodeProtocol,就是用于NameNode和Secondary NameNode间的命令通信。
33、SecondaryNameNode的成员变量很少,主要有:
具体的流程是:
34、我们可以开始从系统的外部来了解HDFS了,DFSClient提供了连接到HDFS系统并执行文件操作的基本功能。DFSClient也是个大家伙,我们先分析下它的一些内部类。我们先看LeaseChecker.租约是客户端对文件写操作时候的一个凭证,前面分析NameNode时,已经了解了租约,INodeFileUnderConstruction的关系,INodeFileUnderContruction只有在文件写的时候存在。客户端的租约管理很简单,包括了增加的put和删除的remove方法,run方法会定期执行,并通过ClientProtocol的renewLease,自动延长租期。
接下来我们分析内部为文件读引入的类。
35、接下来当然是分析输出流了
36、有了上面的基础,我们可以来解剖DFSOutputStreamle 。先看构造函数。
37、前面分析的DFSClient内部类,占据了这个类的实现部分的2/3,我们来看剩余的部分。
=================================
1、MapReduce概论
2、接下来我们来分析Task的两个子类,MapTask和ReduceTask。MapTask的相关
MapTask其实不复杂,复杂的是支持MapTask工作的一些辅助类。
MapTask最重要的方法是run。
接下来我们分析runOldMapper
3、MapTask的辅助类主要针对Mapper的输入和输出。首先我们来看MapTask中用的Mapper输入
4、有了上面Mapper输出的内存存储结构和硬盘存储结构讨论。我们来仔细分析MapOutputBuffer的流程。
首先是成员变量。
5、接下来讨论的是key,value的输出,这部分比较复杂,不过有了前面kvstart,kvend和kvindex配合的分析,有利于我们理解这部分代码。
6、Task的内部类和辅助类。从前面的图中,我们可以发现Task有很多内部类,并拥有大量的成员变量,这些类配合Task完成相应的工作
7、Map的结果,会通过partition分发到Reducer上,Reducer做完Reduce操作后,通过OutputFormat,进行输出,下面我们就来分析参与这个过程的类。
8、Mapper的输出,在发送到Reducer前是存放在本地文件系统的,IFile提供了对Mapper输出的管理。我们已经知道,Mapper输出的是<key,value>键值对,IFile以记录<key-len,value-len,key,value>的形式存放了这些数据。为了保存键值对的边界,很自然IFile需要保存key-len和value-len。
9、我们开始来分析Hadoop Mapreduce的内部运行机制。
我们先来分析一些辅助类,首先是和ID有关的类,ID的继承数如下:
10、前面已经完成了对org.apache.hadoop.mapreduce的分析,这个包提供了Hadoop MapReduce部分的应用API,用于用户实现自己的MapReduce应用。但这些接口是给未来的MapReduce应用的,目前MapReduce框架还是使用的老系统。下面我们来分析org.apache.hadoop.mapred。首先还是从mapred的MapReduce框架开始分析,下面的类图
11、接下来我们安装MapReduce过程中数据流动的顺序,来分解org.apache.hadoop.mapreduce.lib.*的相关内容,并介绍对应的基类的功能。首先是input部分,它实现了MapReduce的数据输入部分。类图如下:
类比较重要的方法有
12、Hadoop的MapReduce框架中,Map动作通过Mapper类来抽象。一般来说,我们会实现自己特殊的Mapper,并注册到系统中,执行时,我们的Mapper会被MapReduce框架调用。Mapper类很简单,包括一个内部类和四个方法,静态结构图如下
13、有了前面一节的分析,我们来看一下具体的接口,他们都处于包org.apache.hadoop.mapreduce中。
标签:
原文地址:http://www.cnblogs.com/shunliu-java/p/4195978.html