Hadoop学习笔记(9) ——源码初窥

Hadoop学习笔记(9)

——源码初窥

之前我们把Hadoop算是入了门,下载的源码,写了HelloWorld,简要分析了其编程要点,然后也编了个较复杂的示例。接下来其实就有两条路可走了,一条是继续深入研究其编程及部署等,让其功能使用的淋漓尽致。二是停下来,先看看其源码,研究下如何实现的。在这里我就选择第二条路。

研究源码,那我们就来先看一下整个目录里有点啥:

这个是刚下完代码后,目录列表中的内容。


目录/文件


说明


bin


下面存放着可执行的sh命名,所有操作都在这里


conf


配置文件所在目录


ivy


Apache Ivy是专门用来管理项目的jar包依赖的,这个是ivy的主要目录


lib


引用的库文件目录,里面存放用到的jar包


src


这个里面就是主要的源码了


build.xml


用于编译的配置文件。 编译我们用的是ant


CHANGES.txt


文本文件,记录着本版本的变更历史


ivy.xml


Ivy的配置文件


LICENSE.txt


文件本文件,


NOTICE.txt


文本文件,记录着需要注意的地方


README.txt


说明文件。

进入src目录,我们看到了:


目录/文件


说明


ant


为ant命令编写的扩展指定


benchmarks


笔者也没弄明白L


build


就存放一个打包信息文件


c++


linux下amd64-64位系统以及i386-32位系统提供的库文件集合


contrib


是开源界或第三方为hadoop编写的一些扩展程序,如eclipse插件等


core


Hadoop的核心代码


docs


文档


examples


示例程序


hdfs


HDFS模块的代码


marped


MapReduce模块代码


native


笔者也没弄明白L


test


测试程序


tools


工具集


webapps


网页管理工具的代码,主要是jsp文件。


fixFontsPath.sh


用于修正字体路径的批处理命令。


saveVersion.sh


用于生成打包信息文件批处理命令。

这些目录及文件命名及分布还是很清晰的,基本上根据命名也能猜出其意思来了。当我们拿到这些文件时,做了两件事,编译运行,接下来我们一块块仔细来看看。

编译

当我们拿到手时,第一章中讲到,我们用了以下命令就完成了编译:

~/hadoop-0.20.2$ant

~/hadoop-0.20.2$ant jar

~/hadoop-0.20.2$ant examples

在编译完后,我们发现,目录中多了一个build文件夹。这个文件夹下,我们发现有大量的子文件夹,再深入看,可以找到了N多个.class文件。那这个正是java程序的编译产出物。

我们在第5章中,简要的描述了java程序与.net的差别。一个.java程序对应一个.class文件,手动的话用javac来编译。我们要将这么多的java文件都要编译成一个个的.class文件,敲javac命令肯定是不行的,我们得找个打包处理的办法。这个就是ant。简单的说ant就是将编译命名进行打包处理的程序,这个程序有一个配置文件就是build.xml。所以我们进入hadoop根目录后输入了ant后就开始运行了,因为它在当前目录下找到了build.xml文件。那ant能做啥,其实百度上一搜就有很多了。这里就不详述了。我们简要的来看一下build.xml。 打开一看,build.xml文件貌似很复杂,有1千8百多行。不要怕,简单看下:

一上来,定义了一个project,看来这是一个工程,有名称和default属性(default后面看是啥)。

接下来发现是一堆的property,然后是name-value的健值。应该猜的出,这些就是后面真正执行用的一些变量或参数。

再往下,看到有这些:

看到有target,然后取了个名,字面意思是目标,然后看看子结点,发现是mkdir,好熟悉的字眼,这不是在创建目录么,看下第一个dir是啥,${build.dir}。然后立即跑回上面property中,看下是否有呢?

果然,这个就是在编译后的产生的目录,第一步创建之,很正常。

既然这样,这个target就是一个个目标,然后往下拖一下,发现下面的都是一个个的目录,全文搜索一下:

发现里面有106个。

继续搜,发现了亮点:

这个target(目标)好眼熟,~/hadoop-0.20.2$ant jar 没错,当时在编译时,输入这个命令后,就产出了一个jar文件。看来这个target就是在形成jar文件,略看下其子命令,的确就是在生成jar包了。

简单了解了这个target后,就可以继续找找,我们的examples命令了。现回想起来,在编译时第一个命令是~/hadoop-0.20.2$ant,而这个好象没有写target么?又想到了:

难道这个default就是传说中的默认目标? compile。 熬不住了,立即展开搜索:

果然,猜的没错。找到了这个默认目录,然后发现好多target后还有depends,字面意思,依赖吧,然后可以继续找,依赖里面的目录,也是一个个的target。

了解了这个之后,我们又在想,现在知道的target也就 默认、jar、example,还有哪些呢,我们就可以搜target name="这个字符。当然会发现有很多,但是不是每个都对我们有用,因为好多是为了编写方便,将一个大的拆成多个小的,以便于维护。至于哪些有用的,这里我就不一一列出。可以自己看看。 比如clean就不错,可以把编译后的结果清理掉,还原到开始状态。

编译成.class包括jar包现在都没问题了。我们知道hadoop是用java写的,在src下可找到大量java类文件。难道这个hadoop就没有引用一个第三方的组件?答案是有的,一开始没看到几个,在lib下就只有几个。 但是在ant完后,在build下搜,发现有好多个jar文件。 哪来的? 下载的。谁负责下载的,为什么知道要下载这些文件?

我们发现,在build.xml中,第一个target init就有depends:

然后就可以一级级查到,是通用ivy进行下载的,至于下载哪些,在ivy.xml中就有配置。好了,这块并不是我们的重点,了解到这里就够了,反正所用到的lib文件都下来了。

运行

在第一章中,我们了解到启用整个hadoop,全到了这个命令:bin/start-all.sh,关闭是用到了bin/stop-all.sh。而这个又是什么文件,我们来研究一下看。

不急看start-all, 我们打开bin目录看一下:

在bin下有很多个sh文件,hadoop这个命令,虽然没有后缀,但打开看后,发现跟其他sh文件样,类似的脚本。

什么是sh文件? 在windows中我们知道bat文件,就是将若干个命令放到一个文件中,依次执行,称之为批处理文件。在Linux中,这个bat文件就是sh文件了。

先不急着打开文件内容,我们观察下所以文件,看到下面8个,很有规律,4个startXXX.sh然后4个stopXXX.sh文件。看来这些就是用户启动和关闭hadoop用的。

打开start-all.sh,发现内容并不多,也很好理解:

这里,先调了一下hadoop-config.sh,字面意思,设置配置文件。然后再调了start-dfs 和start-mapred。这里就很明显了,start-all是启动整个hadoop,然后里面包含了两个动作,启动dfs和mapreduce。 同理,如果我想只启动dfs,那么只需要运行start-dfs.sh即可。

同样,打开stop-all.sh文件,也可以看到比较简单,

发现是分别调了stop-mapred.sh和stop-dfs.sh这两个文件。

这里我们就不每个文件进行分析了,我们只挑几个关键文件看一下。

继续前行,打开start-dfs.sh和stop-dfs.sh文件,发现里面

大家可以打开其他所有的startXX和stopXX文件,发现所有的操作都又转入了hadoop-daemon.sh和hadoop-daemons.sh这两个命令,同时传入了参数—config stop/start 名称 (opt参数)。

继续,打开hadoop-daemons.sh,发现内容也很简单:

这里,先调用了slaves.sh后,又调回来hadoop-daemon.sh,所以现在目标焦点就只有两个了hadoop-daemon.sh和slaves.sh了。打开slaves.sh看一下:

这个文件的字面意思应该就是启动各分布式子机的hadoop咯。看一下代码,第一个if与fi之间,可以看到是取得conf文件夹下的slaves文件。记得在配置分配布式里面,在slaves中配置写了是node1 node2用回车换行隔开。 所以第二段代码,for循环slaves中的文件,然后调用ssh命令,调到了子系统中的相应的命令,这里,就完全可以想通了,为什么子系统中部署的hadoop目录需要与主目录相同,然后slaves中配置的是子系统机器的名称。

到这里,整个bin目录的脚本,就集中在剩下的两个hadoop-daemon.sh和hadoop了。胜利在望了。先看hadoop-daemon.sh。

一开始,代码是在取参数,startstop和command,从前面的传入可以看到,startstop参数传的是start和stop,看来是启动和关闭, command是namenode、datanode之类的。

继续往下看:

case语句下进行了分类,将start和stop命令分开处理。在start时,先是创建一个文件夹PID_DIR,具体值可以看上面,然后第一段if,是在判断进程有没有启动,然后最关健是执行nohup nice …. /bin/hadoop。也就是说归根到底又都是在执行hadoop命令了。这里nohup,是指启动进程后不被卡住,即转为后台进程,又称守护进程,所以该sh文件命名为daemon也不为过。

然后stop段时,把进程进行kill掉。这里有疑问了,启动的命令kill里需要知道进程的PID,而kill里哪里获取呢,在启动时,将启动进程后的pid记录在PID文件夹内,然后kill时就可以跟据这些PID来处理了。这块在代码中,也比较清晰的体现了。

在执行hadoop命令时,又将namenode、datanode、secondarynamenode等命令传入。所以现在可以打开hadoop命令文件了:(这里直接跳入重点看)

这里,看到有大量的if语句,条件是command判断,然后执行中对class和hadoop_opts进行了赋值。 继续往下看:(在最后)

我们发现,是在执行java命令,传入的main函数入口正是上面条件处理中的CLASS变量。换句话说,这个CLASS应该对应一个个的main函数咯? 验证一下,找一个,比如dataNode,其CLASS是org.apache.hadoop.hdfs.server.datanode.DataNode。按这路径在src中找到文件DataNode.java,打开,然后搜main:

果然,完全应正了我们的想法。

总结一下:整个hadoop程序,是一个java为主的程序,在编译是将.class文件生成在build目录,在运行时,虽然执行的是.sh文件,但一步步,最终都是在执行java命令,传入的入口,就是各个子程序的main函数入口。

想法1:看了这个sh命令后,又有一个想法,之前通过starg-all.sh就把整个程序启动起来了,而且是在后台运行的,输出内容只能从log文件夹内看,能否直接从命令行启动呢? 当然行,输入 bin/hadoop namenode试试,果然,启动了namenode程序,然后日志信息也直接打印在屏幕上了。

想法2:既然从hadoop这个sh文件夹内,可以看到所有的入口,那就可以整理一下,所有的入口成一个列表,方便以后找到其main函数。


命令


入口


namenode


org.apache.hadoop.hdfs.server.namenode.NameNode


secondarynamenode


org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode


datanode


org.apache.hadoop.hdfs.server.datanode.DataNode


fs / dfs


org.apache.hadoop.fs.FsShell


dfsadmin


org.apache.hadoop.hdfs.tools.DFSAdmin


mradmin


org.apache.hadoop.mapred.tools.MRAdmin


fsck


org.apache.hadoop.hdfs.tools.DFSck


balancer


org.apache.hadoop.hdfs.server.balancer.Balancer


jobtracker


org.apache.hadoop.mapred.JobTracker


tasktracker


org.apache.hadoop.mapred.TaskTracker


job


org.apache.hadoop.mapred.JobClient


queue


org.apache.hadoop.mapred.JobQueueClient


pipes


org.apache.hadoop.mapred.pipes.Submitter


version


org.apache.hadoop.util.VersionInfo


jar


org.apache.hadoop.util.RunJar


distcp


org.apache.hadoop.tools.DistCp


daemonlog


org.apache.hadoop.log.LogLevel


archive


org.apache.hadoop.tools.HadoopArchives


sampler


org.apache.hadoop.mapred.lib.InputSampler

至此整个目录有了一个初步的了解,接下来,那就可以顺着这些入口深入研究了。且慢,还差个调试环境呢! 下一章来。

Hadoop学习笔记(9) ——源码初窥

时间: 2024-08-02 06:52:15

Hadoop学习笔记(9) ——源码初窥的相关文章

Hadoop学习笔记_2_Hadoop源起与体系概述[续]

Hadoop源起与体系概述 Hadoop的源起--Lucene Lucene是Doug Cutting开创的开源软件,用java书写代码,实现与Google类似的全文搜索功能,它提供了全文检索引擎的架构,包括完整的查询引擎和索引引擎 早期发布在个人网站和SourceForge,2001年年底成为apache软件基金会jakarta的一个子项目 Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎 对于大数据的

Hadoop学习笔记_1_Hadoop源起与体系概述

Hadoop源起与体系概述 引[一个典型的实验环境]: 1.服务器: ESXi,可以在上面部署10多台虚拟机,能同时启动4台; ESXi可以直接安装在裸机上面,而不用首先安装一个WinServer或Linux(StandAlone安装). ESXi在本质上就是一个高度定制化的Linux,其内核与周边环境都被VMWare公司修改了. 2.PC:要求Linux环境或Windows+Cygwin,Linux可以是StandAlone或者使用虚拟机 3.SSH:Windows下可以使用SecureCRT

Linux简易APR内存池学习笔记(带源码和实例)

先给个内存池的实现代码,里面带有个应用小例子和画的流程图,方便了解运行原理,代码 GCC 编译可用.可以自己上网下APR源码,参考代码下载链接: http://pan.baidu.com/s/1hq6A20G 贴两个之前学习的时候参考的文章地址,大家可以参考: http://www.cnblogs.com/bangerlee/archive/2011/09/01/2161437.html http://blog.csdn.net/flyingfalcon/article/details/2627

马哥linux学习笔记:源码编译安装

由于rpm包在作者制作封装的时候已经把程序的一些特性固定了,如果我们根据自己的需求,需要运用程序的一些没有普适性相关特性,就需要下载程序的源码手动编译安装了,这里只是简单的介绍一下C代码的程序包编译安装方法. 为了能更直观的看到源码编译安装的过程,我演示一下在centos7.2环境中编译安装httpd2.2: 首先,编译的前提是得有称手的工具及环境了,编译c源代码就需要用到开发工具,make,gcc了,环境就需要开发库跟头文件了,如果系统中没有这些,就需要yum安装了. 这里我运行yum gro

java学习笔记-String源码分析(2)

承接上篇文章关于String源码的分析,我们继续总结String中的方法 方法汇总 4.subString方法 public String substring(int beginIndex) public String substring(int beginIndex, int endIndex) subString()有2个重载版本,beginIndex指定开始索引(包括),endIndex指定结束索引(不包括).两个方法实现类似,我们关注一个即可. public String substri

QuartZ .Net 学习笔记一: 源码下载与查看

最近因为工作需要研究一下QuartZ .net , 之前也用过不过但没有深入了解,  现想深入研究一下 网上相关QuartZ .net 的文章不少, 但大部分都是源于张善友的博客http://www.cnblogs.com/shanyou/category/102991.html. 写的很全面,看了之后受益匪浅. 在这里将学习的一些收获记录一下, 方便将来查看 Quartz.net 是Quartz的移植版本, 历史来源不做过多介绍 网上几乎所有相关介绍都是写到http://quartznet.s

05、NetCore2.0插件框架运行原理源码初窥

05.NetCore2.0插件框架运行原理之WebHostBuilder源码初窥 NetCore2.0的插件框架是要解决对象创建的问题,把创建对象与使用对象进行解耦.调用者不需要关心对象是单例的还是多实例的:插件的扩展和调用也更容易. 一.我们先看看插件框架是如何使用的 首先使用VS2017新建一个控制台程序,要使用插件框架,我们需要引入微软的依赖注入包: install-package Microsoft.Extensions.DependencyInjection 我们声明一个自己的接口,并

Hadoop学习笔记(10) ——搭建源码学习环境

Hadoop学习笔记(10) ——搭建源码学习环境 上一章中,我们对整个hadoop的目录及源码目录有了一个初步的了解,接下来计划深入学习一下这头神象作品了.但是看代码用什么,难不成gedit?,单步调试呢? 看程序不能调那多痛苦啊,想看跟踪一下变量,想看一下执行路径都难. 所以这里,我们得把这个调试环境搭建起来.Hadoop的主要代码是用java编写的,所以这里就选用eclipse作为环境. Hadoop目录下,本身就可以为作eclipse的一个工程来操作,但这里我不想,我想自己来建一个工程,

bootstrap学习笔记一: bootstrap初认识,hello bootstrap(下)

这一篇主要是补上源码,开始之前请先回顾:bootstrap学习笔记一: bootstrap初认识,hello bootstrap(上) 首先,我们的页面要求, lang,charset等就不用说了,老html属性, viewport是h5的属性,目的是 width=device-width 铺满设备宽度, initial-scale=1正常比较 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta c