作者:董西成
出版社:机械工业出版社
格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT
Hadoop技术内幕:深入解析MapReduce架构设计与实现原理试读:
前言
为什么要写这本书
突然之间,大数据一下子就“火”了,开源软件Hadoop也因此水涨船高。得益于一些国际领先厂商,尤其是FaceBook、Yahoo!以及阿里巴巴等互联网巨头的现身说法,Hadoop被看成大数据分析的“神器”。IDC在对中国未来几年的预测中就专门提到了大数据,其认为未来几年,会有越来越多的企业级用户试水大数据平台和应用,而这之中,Hadoop将成为最耀眼的“明星”。
尽管Hadoop整个生态系统是开源的,但是,由于它包含的软件种类过多,且版本升级过快,大部分公司,尤其是一些中小型公司,难以在有限的时间内快速掌握Hadoop蕴含的价值。此外,Hadoop自身版本的多样化也给很多研发人员带来了很大的学习负担。尽管当前市面上已有很多参考书籍,比如《Hadoop:The Definitive Guide》、《Hadoop in Action》、《Pro Hadoop》、《Hadoop Operations》等,但是,至今还没有一本书能够深入地剖析Hadoop内部的实现细节,比如JobTracker实现、作业调度器实现等。也正因如此,很多Hadoop初学者和研发人员只能参考网络上一些零星的源代码分析的文章,自己一点一点地阅读源代码,缓慢地学习Hadoop。而本书正是为了解决以上各种问题而编写的,它是国内第一本深入剖析Hadoop内部实现细节的书籍。
本书以Hadoop 1.0为基础,深入剖析了Hadoop MapReduce中各个组件的实现细节,包括RPC框架、JobTracker实现、TaskTracker实现、Task实现和作业调度器实现等。书中不仅详细介绍了MapReduce各个组件的内部实现原理,而且结合源代码进行了深入的剖析,使读者可以快速全面地掌握Hadoop MapReduce设计原理和实现细节。
读者对象
(1)Hadoop二次开发人员Hadoop由于在扩展性、容错性和稳定性等方面的诸多优点,已被越来越多的公司采用。而为了减少开发成本,大部分公司在Hadoop基础上进行了二次开发,以打造属于公司内部的Hadoop平台。对于Hadoop二次开发人员来说,深入而又全面地了解Hadoop的设计原理与实现细节是修改Hadoop内核的前提,而本书可帮助这部分读者快速而又全面地了解Hadoop实现细节。(2)Hadoop应用开发人员
如果要利用Hadoop进行高级应用开发,仅掌握Hadoop基本使用方法是远远不够的,必须对Hadoop框架的设计原理、架构和运作机制有一定的了解。对这部分读者而言,本书将带领他们全面了解Hadoop的设计和实现原理,加深对Hadoop框架的理解,提高开发水平,从而编写出更加高效的MapReduce应用程序。(3)Hadoop运维工程师
对于一名合格的Hadoop运维工程师而言,适当地了解Hadoop框架的设计原理、架构和运作机制是十分有帮助的。这不仅可以使Hadoop运维人员更快地排除各种可能的Hadoop故障,还可以让Hadoop运维人员与研发人员进行更有效的沟通。通过阅读这本书,Hadoop运维人员可以了解到很多其他书中无法获取的Hadoop实现细节。(4)开源软件爱好者
Hadoop是开源软件中的佼佼者。它在实现的过程中吸收了很多开源领域的优秀思想,同时有很多值得学习的创新。尤为值得一提的是,本书分析Hadoop架构设计和实现原理的方式也许值得所有开源软件爱好者学习和借鉴。通过阅读本书,这部分读者不仅能领略到开源软件的优秀思想,还可以掌握分析开源软件源代码的方法和技巧,从而进一步提高使用开源软件的效率和质量。
如何阅读本书
本书分为四大部分(不包括附录):
第一部分为基础篇,简单地介绍Hadoop的阅读环境搭建和基本设计架构,帮助读者了解一些基础背景知识。
第二部分为MapReduce编程模型篇,着重讲解MapReduce编程接口,主要包括两套编程接口,分别是旧API和新API。
第三部分为MapReduce核心设计篇,主要讲解Hadoop MapReduce的运行时环境,包括RPC框架、客户端、JobTracker、TaskTracker和Task等内部实现细节。
第四部分为MapReduce高级篇,主要讲解Hadoop MapReduce中的一些高级特性和未来发展趋势,包括多用户作业调度器、安全机制和下一代MapReduce框架等。
另外,本书最后还添加了几个附录:附录A为安装Hadoop过程中可能存在的问题及解决方案;附录B为Hadoop默认HTTP端口号以及HTTP地址。参考资料中包括了本书写作过程中参考的书籍、论文、Hadoop Jira和网络资源。
如果你是一名经验丰富的资深用户,能够理解Hadoop的相关基础知识和使用技巧,那么你可以直接阅读第三部分和第四部分。但是,如果你是一名初学者,请一定从第1章的基础理论知识开始学习。
勘误和支持
由于笔者的水平有限,加之编写时间仓促,书中难免会出现一些错误或者不准确的地方,恳请读者批评指正。为此,笔者特意创建了一个在线支持与应急方案的站点http://hadoop123.com。你可以将书中的错误发布在Bug勘误表页面中。如果你遇到问题,可以访问Q&A页面,我将尽量在线上为读者提供最满意的解答。如果你有什么宝贵意见,欢迎发送邮件至dongxicheng@yahoo.com,期待能够得到你的真挚反馈。
致谢
感谢我的导师廖华明副研究员。在我读研没空顾及项目的时候,她给了我一次又一次的鼓励,她甚至专门为我写书留出空闲时间。在廖老师的身边,我还学会了很多专业知识以外的东西。
感谢腾讯的蔡斌老师。正是由于他的推荐,才使本书的出版成为可能。
感谢机械工业出版社华章公司的杨福川老师和孙海亮老师。是他们在这一年多的时间中始终支持着我的写作,是他们的鼓励和帮助使我顺利完成了本书的编写工作。
感谢对本书部分章节提出改进建议的何鹏、姜冰、郑伟伟等人。另外,感谢给我提供各种帮助的战科宇、周礼、刘晏辰、孟椿智、王群、王颖、曹聪、朱雪峰等人。
最后,感谢我父母的养育之恩,感谢兄长的鼓励和支持,感谢他们时时刻刻给我信心和力量!感谢我的女朋友颛悦对我生活的悉心照料与琐事上的宽容。
谨以此书献给我最亲爱的家人,以及众多热爱Hadoop的朋友们!董西成于北京第一部分基础篇本部分内容阅读源代码前的准备MapReduce设计理念与基本架构第1章阅读源代码前的准备
一般而言,在深入研究一个系统的技术细节之前,先要进行一些基本的准备工作,比如,准备源代码阅读环境,搭建运行环境并尝试使用该系统等。对于Hadoop而言,由于它是一个分布式系统,且由多种守护进程组成,具有一定的复杂性,如果想深入学习其设计原理,仅仅进行以上几项准备工作是不够的,还要学习一些调试工具的使用方法,以便对Hadoop源代码进行调试、跟踪。边用边学,这样才能事半功倍。
本章的编写目的是帮助读者构建一个“高效”的Hadoop源代码学习环境,包括Hadoop源代码阅读环境、Hadoop使用环境和Hadoop源代码编译调试环境等,这主要涉及如下内容:
❑在Linux和Windows环境下搭建Hadoop源代码阅读环境的方法;
❑Hadoop的基本使用方法,主要包括Hadoop Shell和Eclipse插件两种工具的使用;
❑Hadoop源代码编译和调试方法,其中,调试方法包括使用Eclipse远程调试和打印调试日志两种。
考虑到大部分用户在单机上学习Hadoop源代码,所以本章内容均是基于单机环境的。本章大部分内容较为基础,已经掌握这部分内容的读者可以直接跳过本章。1.1 准备源代码学习环境
对于大部分公司而言,实验和生产环境中的服务器集群部署的都是Linux操作系统。考虑到Linux在服务器市场中具有统治地位,Hadoop从一开始便是基于Linux操作系统开发的,因而对Linux有着非常完美的支持。尽管Hadoop采用了具有跨平台特性的Java作为主要编程语言,但由于它的一些功能实现用到了Linux操作系统相关的技术,因而对其他平台的支持不够友好,且没有进行过严格测试。换句[1]话说,其他操作系统(如Windows)仅可作为开发环境,不可作为生产环境。对于学习源代码而言,操作系统的选择显得不是非常重要,读者可根据个人爱好自行决定。本节以64 bit Linux和32 bit Windows两种操作系统为例,介绍如何在单机上准备Hadoop源代码学习环境。1.1.1 基础软件下载
前面提到Hadoop采用的开发语言主要是Java,因而搭建Hadoop环境所需的最基础的软件首先应该包括Java基础开发包JDK和Java编译工具Ant。考虑到源代码阅读和调试的便利性,本书采用功能强大的集成开发环境Eclipse。此外,如果读者选择Windows平台搭建学习环境,还需要安装Cygwin以模拟Linux环境,这是因为Hadoop采用Bash Shell脚本管理集群。搭建Hadoop阅读环境需要的各种软件以及下载方式如表1-1所示。
[1]截至本书结稿时,Apache Hadoop SVN中已经出现了针对Windows操作系统的分支,具体见http://svn.apache.org/repos/asf/hadoop/common/branches/下的branch-1-win和branch-trunk-win,且Hortonworks公司发布了Windows安装版本,具体见http://hortonworks.com/partners/microsoft/
[2]注意,Indigo及以上版本与Hadoop Eclipse插件可能存在兼容问题。1.1.2 如何准备Windows环境
本小节将介绍如何准备Windows下的Hadoop学习环境,包括JDK、Ant、Cygwin和Eclipse等基础软件的使用方法。本小节假设用户的软件安装目录为D:\hadoop,且最终安装完成的目录结构为:1.JDK的安装
用户下载的安装包为jdk-6u25-windows-i586.exe,直接双击该安装包将JDK安装到D:\hadoop\Java\下,然后设配置环境变量JAVA_HOME、CLASSPATH、PATH(不区分大小写),方法如下。(1)配置JAVA_HOME
如图1-1所示,在Windows桌面上,右击“计算机”图标,然后在弹出的快捷菜单中依次选择“属性”→“高级系统设置”→“环境变量”命令,然后在系统变量栏,单击“新建”按钮,在弹出的对话框中的“变量名”文本框中填写JAVA_HOME,在“变量值”文本框中填写D:\hadoop\Java\jdk1.6.0_25,然后单击“确定”按钮。图 1-1 Windows环境下设置JAVA_HOME环境变量(2)配置CLASSPATH
参考JAVA_HOME另建一个系统变量,变量名为CLASSPATH,变量值为:
.;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar;(3)配置PATH
PATH变量已经存在,选中后再单击“编辑”按钮即可。在变量值中添加如下内容:
%JAVA_HOME%/bin;%JAVA_HOME%/jre/bin
经过以上配置,JDK已经安装完毕,可在DOS窗口中输入命令“java-version”以验证是否安装成功。如果输出以下内容,则说明安装成功:
java version"1.6.0_25"
Java(TM)SE Runtime Environment(build 1.6.0_25-b05)
Java HotSpot(TM)Client VM(build 20.6-b01,mixed mode, sharing)2.Ant的安装
假设下载的安装包为apache-ant-1.7.1-bin.zip,直接将其解压到工作目录D:\hadoop\下,并添加新的环境变量ANT_HOME,设置其值为D:\hadoop\apache-ant-1.7.1,同时在环境变量PATH后面添加如下内容:
;%ANT_HOME%\bin
经过以上配置,Ant已经安装完毕,可在DOS窗口中输入命令“ant-version”以验证是否安装成功。如果输出以下内容,则说明安装成功:
Apache Ant version 1.7.1 compiled on June 27 20083.Cygwin的安装(1)安装Cygwin
双击下载的Cygwin的安装包setup.exe,一直单击“下一步”按钮,直到出现如图1-2所示的界面,在“Net”一栏中选中OpenSSH相关软件包,会出现如图1-3所示的界面,然后单击“下一步”按钮,此时系统开始在线下载并安装Cygwin环境(时间比较长)。图 1-2 Windows环境下通过Cygwin安装OpenSSH——单击“Net”一栏图 1-3 Windows环境下通过Cygwin安装OpenSSH——选中OpenSSH软件包(2)安装并启动sshd服务
Hadoop启动/停止脚本需要通过SSH发送命令启动相关守护进程,为此需要安装sshd服务。安装sshd服务的方法是,以管理员身份打开Cygwin命令行终端(右击运行图标,单击“以管理员身份运行”命令),然后输入以下命令:
ssh-host-config
接着,按照命令行中的提示进行安装,具体如图1-4所示。图 1-4 Windows环境下通过Cygwin安装sshd服务
安装完毕后,输入以下命令启动sshd服务:
net start sshd4.Eclipse的安装
Eclipse官网提供的Eclipse版本均是免安装版,直接将下载的压缩包解压到“D:\hadoop\”下即可使用。1.1.3 如何准备Linux环境
本小节将介绍如何准备Linux下的Hadoop学习环境。搭建Linux学习环境需要安装JDK, Ant和Eclipse等软件。本书以64 bit Ubuntu为例,介绍安装这些软件的方法,最终安装完成的目录结构为:1.JDK的安装与配置
一般而言,Ubuntu系统会自带JDK,如果没有或者版本不符合要求,可按以下步骤进行安装:
步骤1 安装JDK。将下载的.bin文件复制到Linux的某个目录下,比如/usr/lib/jvm/下,然后在Shell中执行以下命令为该文件添加可执行权限:
chmod+x/usr/lib/jvm/jdk1.6.0_25.bin
然后执行以下命令安装JDK:
sudo/usr/lib/jvm/jdk1.6.0_25.bin
之后将会出现安装信息,直至屏幕显示要求按下回车键。此时按下回车键后,会把JDK解压到文件夹jdk1.6.0_25中。至此,JDK已安装完毕,下面进行配置。
步骤2 配置JDK。修改/etc/profile文件,在里面添加以下内容:
export JAVA_HOME=/usr/lib/jvm/jdk1.6.0_25
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
输入以下命令让配置生效:
source/etc/profile
步骤3 修改默认JDK版本。Ubuntu中可能会有默认的JDK,如openjdk,因而我们需要将自己安装的JDK设置为默认JDK版本,执行下面代码:
sudo update-alternatives--install/usr/bin/java java/usr/lib/jvm/jdk1.6.0_25/bin/java 300
sudo update-alternatives--install/usr/bin/javac javac/usr/lib/jvm/jdk1.6.0_25/bin/javac 300
sudo update-alternatives--install/usr/bin/jar jar/usr/lib/jvm/jdk1.6.0_25/bin/jar 300
sudo update-alternatives--install/usr/bin/javah javah/usr/lib/jvm jdk1.6.0_25/bin/javah 300
sudo update-alternatives--install/usr/bin/javap javap/usr/lib/jvm/jdk1.6.0_25/bin/javap 300
然后执行以下代码选择我们安装的JDK版本:
sudo update-alternatives--config java
步骤4 验证JDK是否安装成功。重启Shell终端,执行命令“java-version”。如果输出以下内容,则说明安装成功:
java version"1.6.0_25"
Java(TM)SE Runtime Environment(build 1.6.0_25-b06)
Java HotSpot(TM)Client VM(build 20.0-b11,mixed mode, sharing)2.Ant以及Eclipse的安装(1)安装与配置Ant
首先解压下载包,比如解压到文件/usr/lib/apache-ant-1.7.1目录下,然后修改/etc/profile文件,在里面添加以下内容:
export ANT_HOME=/usr/lib/apache-ant-1.7.1
export PATH=$PATH$:$ANT_HOME/bin
输入以下命令让配置生效:
source/etc/profile
同Windows下的验证方式一样,重启终端,执行命令“ant-version”。如果输出以下内容,则说明安装成功:
Apache Ant version 1.7.1 compiled on June 27 2008(2)安装Eclipse
同Windows环境下的安装方式一样,直接解压即可使用。1.2 获取Hadoop源代码
当前比较流行的Hadoop源代码版本有两个:Apache Hadoop和Cloudera Distributed Hadoop(CDH)。Apache Hadoop是由Yahoo!、Cloudera、Facebook等公司组成的Hadoop社区共同研发的,它属于最原始的开源版本。在该版本的基础上,很多公司进行了封装和优化,推出了自己的开源版本,其中,最有名的一个是Cloudera公司发布的CDH版本。
考虑到Apache Hadoop是最原始的版本,且使用最为广泛,因而本书选用了Apache Hadoop版本为分析对象。自从Apache Hadoop发布以来,已经陆续推出很多版本(具体介绍见2.1.3节)。其中,最具有标志性的版本是1.0.0,而该书正是基于该版本对Hadoop MapReduce进行深入分析的。Hadoop 1.0.0可从http://hadoop.apache.org/common/releases.html或http://svn.apache.org/repos/asf/hadoop/common/branches/branch-1.01处下载。1.3 搭建Hadoop源代码阅读环境1.3.1 创建Hadoop工程
本小节介绍如何创建一个Hadoop源代码工程,以方便阅读源代码。创建一个Hadoop工程,可分两个步骤完成:
步骤1 解压缩Hadoop源代码。将下载到的Hadoop源代码压缩包hadoop-1.0.0.tar.gz解压到工作目录下(对于Windows系统而言,为了操作方便,解压到Cygwin安装目录的home/${USER}文件夹下)。
步骤2 新建Java工程。打开Eclipse,进入Eclipse可视化界面后,如图1-5所示,依次单击“File”→“New”→“Java Project”,并在弹出的对话框中取消选中“Use default location”前的勾号,然后选择Hadoop安装目录的位置。默认情况下,工程名称与Hadoop安装目录名称相同,用户可自行修改。单击完成按钮,Hadoop源代码工程创建完毕。图 1-5 新建Hadoop工程
回到Eclipse主界面后,打开新建的Hadoop工程,可看到整个工程的组织代码,如图1-6所示,源代码按目录组织,且每个目录下以jar包为单位显示各个Java文件。图 1-6 Hadoop工程展示(部分)源代码方式
除了使用源代码压缩包导入Eclipse工程的方法外,读者可以尝试直接从Hadoop SVN上导入Hadoop源代码。这些源代码本身已经是从Eclipse工程导出的,Hadoop SVN地址为:http://svn.apache.org/repos/asf/hadoop/common/branches/。1.3.2 Hadoop源代码阅读技巧
本小节介绍在Eclipse下阅读Hadoop源代码的一些技巧,比如如何查看一个基类有哪些派生类、一个方法被其他哪些方法调用等。1.查看一个基类或接口的派生类或实现类
在Eclipse中,选中某个基类或接口名称,右击,在弹出的快捷菜单中选择“Quick Type Hierarchy”,可在新窗口中看到对应的所有派生类或实现类。
例如,如图1-7所示,打开src\mapred\目录下org.apache.hadoop.mapred包中的InputFormat.java文件,查看接口InputFormat的所有实现类,结果如图1-8所示。图 1-7 在Eclipse中查看Hadoop源代码中接口InputFormat的所有实现类图 1-8 Eclipse列出接口InputFormat的所有实现类2.查看函数的调用关系
在Eclipse中,选中某个方法名称,右击,在弹出的快捷菜单中选择“Open Call Hierarchy”,可在窗口“Call Hierarchy”中看到所有调用该方法的函数。
例如,如图1-9所示,打开src\mapred\目录下org.apache.hadoop.mapred包中的JobTracker.java文件,查看调用方法initJob的所有函数,结果如图1-10所示。图 1-9 在Eclipse中查看Hadoop源代码中所有调用JobTracker.java中initJob方法的函数图 1-10 Eclipse列出所有调用initJob方法的函数3.快速查找类对象的相关信息
同前两个小节类似,选中类对象,右击,在弹出的快捷菜单中选择“Open Declaration”,可跳转到类定义;选择“Quick Outline”,可查看类所有的成员变量和成员方法。具体细节本书不做详细介绍,读者可自行尝试。1.4 Hadoop源代码组织结构
直接解压Hadoop压缩包后,可看到图1-11所示的目录结构,其中,比较重要的目录有src、conf、lib、bin等。下面分别介绍这几个目录的作用:
❑src:Hadoop源代码所在的目录。最核心的代码所在子目录分别是core、hdfs和mapred,它们分别实现了Hadoop最重要的三个模块,即基础公共库、HDFS实现和MapReduce实现。
❑conf:配置文件所在目录。Hadoop的配置文件比较多,其设计原则可概括为如下两点。
〇尽可能模块化,即每个重要模块拥有自己的配置文件,这样使得维护以及管理变得简单。
〇动静分离,即将可动态加载的配置选项剥离出来,组成独立配置文件。比如,Hadoop 1.0.0版本之前,作业队列权限管理相关的配置选项被放在配置文件mapred-site.xml中,而该文件是不可以动态加载的,每次修改后必须重启MapReduce。但从1.0.0版本开始,这些配置选项被剥离放到独立配置文件mapred-queue-acls.xml中,该文件可以通过Hadoop命令行动态加载。conf目录下最重要的配置文件有core-site.xml、hdfs-site.xml和mapred-site.xml,分别设置了基础公共库core、分布式文件系统HDFS和分布式计算框架MapReduce的配置选项。
❑lib:Hadoop运行时依赖的三方库,包括编译好的jar包以及其他语言生成的动态库。Hadoop启动或者用户提交作业时,会自动加载这些库。
❑bin:运行以及管理Hadoop集群相关的脚本。这里介绍几个常用的脚本。
〇hadoop:最基本且功能最完备的管理脚本,其他大部分脚本都会调用该脚本。
〇start-all.sh/stop-all.sh:启动/停止所有节点上的HDFS和MapReduce相关服务。
〇start-mapred.sh/stop-mapred.sh:单独启动/停止MapReduce相关服务。
〇start-dfs.sh/stop-dfs.sh:单独启动/停止HDFS相关服务。图 1-11 Hadoop安装目录结构
本书重点介绍MapReduce的实现原理,下面就Hadoop MapReduce源代码组织结构进行介绍。Hadoop MapReduce源代码组[1]织结构如图1-12所示。图 1-12 Hadoop MapReduce源代码组织结构
总体上看,Hadoop MapReduce分为两部分:一部分是org.apache.hadoop.mapred.*,这里面主要包含旧的对外编程接口以及MapReduce各个服务(JobTracker以及TaskTracker)的实现;另一部分是org.apache.hadoop.mapreduce.*,主要内容涉及新版本的对外编程接口以及一些新特性(比如MapReduce安全)。1.MapReduce编程模型相关
❑org. apache.hadoop.mapred.lib.*:这一系列Java包提供了各种可直接在应用程序中使用的InputFormat、Mapper、Partitioner、Reducer和OuputFormat,以减少用户编写MapReduce程序的工作量。
❑org. apache.hadoop.mapred.jobcontrol:该Java包允许用户管理具有相互依赖关系的作业(DAG作业)。
❑org. apache.hadoop.mapred.join:该Java包实现了map-side join[2]算法。该算法要求数据已经按照key排好序,且分好片,这样可以只使用Map Task实现join算法,避免re-partition、sort、shuffling等开销。
❑org. apache.hadoop.mapred.pipes:该Java包允许用户用C/C++编写MapReduce作业。
❑org. apache.hadoop.mapreduce:该Java包定义了一套新版本的编程接口,这套接口比旧版接口封装性更好。
❑org. apache.hadoop.mapreduce.*:这一系列Java包根据新版接口实现了各种InputFormat、Mapper、Partitioner、Reducer和OuputFormat。2.MapReduce计算框架相关
❑org. apache.hadoop.mapred:Hadoop MapReduce最核心的实现代码,包括各个服务的具体实现。
❑org. apache.hadoop.mapred.filecache:Hadoop DistributedCache实现。DistributedCache是Hadoop提供的数据分发工具,可将用户应用程序中需要的文件分发到各个节点上。
❑org. apache.hadoop.mapred.tools:管理控制Hadoop MapReduce,当前功能仅包括允许用户动态更新服务级别的授权策略和ACL(访问权限控制)属性。
❑org. apache.hadoop.mapreduce.split:该Java包的主要功能是根据作业的InputFormat生成相应的输入split。
❑org. apache.hadoop.mapreduce.server.jobtracker:该Java包维护了JobTracker可看到的TaskTracker状态信息和资源使用情况。
❑org. apache.hadoop.mapreduce.server.tasktracker.*:TaskTracker的一些辅助类。3.MapReduce安全机制相关
这里只涉及org.apache.hadoop.mapreduce.security.*。这一系列Java包实现了MapReduce安全机制。
[1]不同版本Hadoop的源代码结构稍有差距,本书的分析是基于Hadoop 1.0.0版本的。
[2]Join算法是将两个表或者文件按照某个key值合并起来,在Hadoop中,可以在Map或者Reduce端进行合并。若在Reduce端进行合并,则需要进行re-partition、sort、shuffling等操作,开销很大。1.5 Hadoop初体验
一般而言,我们想要深入学习一个新的系统时,首先要尝试使用该系统,了解系统对外提供的功能,然后通过某个功能逐步深入其实[1]现细节。本节将介绍如何在伪分布式工作模式下使用Hadoop,包括启动Hadoop、访问HDFS以及向MapReduce提交作业等最基本的操作。本节只是有代表性地介绍Hadoop的一些基本使用方法,使读者对Hadoop有一个初步认识,并引导读者逐步进行更全面的学习。1.5.1 启动Hadoop
步骤1 修改Hadoop配置文件。在conf目录下,修改mapred-site.xml、core-site.xml和hdfs-site.xml三个文件,在<configuration>与</configuration>之间添加以下内容。
❑mapred-site. xml:
<property>
<name>mapred.job.tracker</name>
<value>localhost:9001</value>
</property>
❑core-site.xml:
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
❑hdfs-site.xml:
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
如果是Windows环境,还需要在hadoop-env.xml中添加以下配置:
export JAVA_HOME=D:/hadoop/Java/jdk1.6.0_27
步骤2 设置免密码登录。前面提到Hadoop启动启动/停止脚本时需要通过SSH发送命令启动相关守护进程,为了避免每次启动/停止Hadoop输入密码进行验证,需设置免密码登录,设置步骤如下。
1)打开命令行终端(Windows下为Cygwin终端,Linux下为Shell终端,下同),输入以下命令:
ssh-keygen-t rsa
执行上述命令后,将会在“~/.ssh/”目录下生成公钥文件id_rsa.pub和私钥文件id_rsa。
2)将公钥文件id_rsa.pub中的内容复制到相同目录下的authorized_keys文件中:
cd~/.ssh/
cat id_rsa.pub>>authorized_keys
步骤3 启动Hadoop。在Hadoop安装目录中,按以下两步操作启动Hadoop。
1)格式化HDFS:
bin/hadoop namenode-format
2)启动Hadoop:
bin/start-all.sh
通过以下URL可查看MapReduce是否启动成功:
http://localhost:50030/
通过以下URL可查看HDFS是否启动成功:
http://localhost:50070/
经过以上两步操作,Hadoop成功启动,接下来可以通过Hadoop Shell或者Eclipse插件访问HDFS和提交MapReduce作业。下面两小节分别介绍Hadoop Shell和Eclipse插件的使用方法。
[1]单机环境中,Hadoop有两种工作模式:本地模式和伪分布式模式。其中,本地模式完全运行在本地,不会加载任何MapReduce服务,因而不会涉及MapReduce最核心的代码实现;伪分布式模式即为“单点集群”,在该模式下,所有的守护进程均会运行在单个节点上,因而本节选用该工作模式。1.5.2 Hadoop Shell介绍
在1.4节中曾提到,bin目录下的Hadoop脚本是最基础的集群管理脚本,用户可以通过该脚本完成各种功能,如HDFS文件管理、MapReduce作业管理等。该脚本的使用方法为:
hadoop[--config confdir]COMMAND
其中,--config用于设置Hadoop配置文件目录,默认目录为${HADOOP_HOME}/conf。而COMMAND是具体的某个命令,常用的有HDFS管理命令fs、作业管理命令job和作业提交命令jar等。它们的使用方法如下:(1)HDFS管理命令fs和作业管理命令job
它们的用法一样,均为:
bin/hadoop command[genericOptions][commandOptions]
其中,command可以是fs或者job, genericOptions是一些通用选项,commandOptions是fs或者job附加的命令选项。看下面两个例子。
❑在HDFS上创建一个目录/test:
bin/hadoop fs-mkdir/test
❑显示Hadoop上正在运行的所有作业:
bin/hadoop job-list(2)作业提交命令jar
这个命令的用法是:
hadoop jar<jar>[mainClass]args..
其中,<jar>表示jar包名;mainClass表示main class名称,可以不必输入而由jar命令自动搜索;args是main class输入参数。举例如下:
bin/hadoop jar hadoop-examples-1.0.0.jar wordcount/test/input/test/ouput
其中,wordcount是hadoop-examples-1.0.0.jar中一个作业名称。顾名思义,该作业用于统计输入文件中的每个单词出现的次数,它有两个输入参数:输入数据目录(/test/input)和输出数据目录(/test/output)。
至于其他更多命令,读者可自行查阅Hadoop官方设计文档。1.5.3 Hadoop Eclipse插件介绍
Hadoop提供了一个Eclipse插件以方便用户在Eclipse集成开发环境中使用Hadoop,如管理HDFS上的文件、提交作业、调试MapReduce程序等。本小节将介绍如何使用该插件访问HDFS、运行MapReduce作业和跟踪MapReduce作业运行过程。1.编译生成Eclipse插件
用户需要自己生成Eclipse插件。Hadoop-1.0.0生成的jar包不能直接使用,需要进行部分修改,具体参考附录A中的问题2,其代码位于Hadoop安装目录的src/contrib/eclipse-plugin下,在该目录下,输入以下命令生成Eclipse插件:
ant-Declipse.home=/home/dong/eclipse-Dversion=1.0.0
其中,eclipse.home用来指定Eclipse安装目录,version是Hadoop版本号。${HADOOP_HOME}/build/contrib目录下生成的hadoop-eclipse-plugin-1.0.0.jar文件即为Eclipse插件。2.配置Eclipse插件
将生成的Eclipse插件hadoop-eclipse-plugin-1.0.0.jar复制到Eclipse安装目录的plugins文件夹下,然后重启Eclipse。
进入Eclipse后,按照以下步骤进行设置:在菜单栏中依次单击“Window”→“Show View”→“Other……”,在对话框中依次单击“MapReduce Tools”→“Map/Reduce Locations”,会弹出图1-13a所示的对话框,按图中提示填写内容。
经上述步骤后,回到主界面,如图1-13b所示,可在“Project Explore”视图中查看分布式文件系统的内容,说明Eclipse插件安装成功。图 1-13 配置Hadoop Eclipse插件a)配置MapReduce和HDFS的主机名和端口号 b)显示HDFS中的文件列表3.运行MapReduce作业
前面提到,在伪分布式环境下,单个节点上会同时运行多种Hadoop服务。为了跟踪这些服务的运行轨迹,我们采用了以下方法:向Hadoop提交一个MapReduce作业,通过跟踪该作业的运行轨迹来分析Hadoop的内部实现原理。
该方法可通过以下三个步骤完成:
步骤1 新建一个MapReduce工程。在菜单栏中,依次单击“New”→“Other…”→“MapReduce Project”,会弹出图1-14所示的对话框。在该对话框中填写项目名称,并配置Hadoop安装目录,此处可直接选择前面已经建好的Java工程“hadoop-1.0.0”。图 1-14 在Eclipse中创建MapReduce工程
步骤2 准备MapReduce作业。可直接将Hadoop源代码中src\examples\org\apache\hadoop\examples目录下的WordCount.java复制到新建的MapReduceJobs工程中。
步骤3 运行作业。
1)准备数据。如图1-15所示,在HDFS上创建目录/test/input,并上传几个文本文件到该目录中。图 1-15 使用Eclipse插件上传文件到HDFS
2)配置输入/输出路径。如图1-16所示,在WordCount.java中右击,在弹出的快捷菜单中依次单击“Run As”→“Run Configurations……”,会出现图1-17所示的对话框。双击“Java Applications”选项,在新建的对话框中输入作业的输入/输出路径(中间用空格分隔),并单击“Apply”按钮保存。图 1-16 在Eclipse中配置作业的输入/输出路径(1)图 1-17 在Eclipse中配置作业的输入/输出路径(2)
3)运行作业。在WordCount.java中右击,在弹出的快捷菜单中依次单击“Run As”→“Run on Hadoop”,会出现如图1-18所示的对话框。按图中的提示选择后,单击“Finish”按钮,作业开始运行。
此外,有兴趣的读者可以在MapReduce作业中设置断点,对作业进行断点调试。图 1-18 在Eclipse中运行作业1.6 编译及调试Hadoop源代码
读者在阅读源代码的过程中,可能需要修改部分源代码或者使用调试工具以便跟踪某些变量值的变化过程,此时要用到Hadoop源代码编译和调试方法。本节将介绍Hadoop在伪分布式模式下的编译和调试方法,其中,调试方法主要介绍使用Eclipse远程调试和打印调试日志两种。1.6.1 编译Hadoop源代码
在Windows或Linux环境下,打开命令行终端,转到Hadoop安装目录下并输入以下命令:
ant-Dversion=1.0.0{target}
其中,{target}值如表1-2所示,不同的target可对应生成不同的jar包,如:
ant-Dversion=1.0.0 examples
可生成hadoop-examples-1.0.0.jar,产生的jar包位于Hadoop安装目录的build文件夹下。1.6.2 调试Hadoop源代码
本小节介绍两种调试方式:利用Eclipse远程调试和打印调试日志。这两种方式均可以调试伪分布式工作模式和完全分布式工作模式下的Hadoop。本小节主要介绍伪分布式工作模式下的Hadoop调试方法。1.利用Eclipse进行远程调试
下面以调试JobTracker为例,介绍利用Eclipse进行远程调试的基本方法。调试过程可分三步进行:
步骤1 调试模式下启动Hadoop。
在Hadoop安装目录下运行内容如下的Shell脚本:
export HADOOP_JOBTRACKER_OPTS="-Xdebug-Xrunjdwp:transport=dt_socket, address=878 8,server=y, suspend=y"
bin/start-all.sh
如果脚本运行成功,则可以看到Shell命令行终端显示如下信息:
Listening for transport dt_socket at address:8788
此时表明JobTracker处于监听状态。JobTracker将一直处于监听状态,直到收到debug确认信息。
步骤2 设置断点。
在前面新建的Java工程“hadoop-1.0.0”中,找到JobTracker相关代码,并在感兴趣的地方设置一些断点。
步骤3 在Eclipse中调试Hadoop程序。
在Eclipse的菜单栏中,依次单击“Run”→“Debug Configurations”→“Remote Java Applications”,打开图1-19所示的对话框,按图中的提示填写名称、JobTracker所在的host以及监听端口,并选择Hadoop源代码工程,进入图1-20所示的调试模式。图 1-19 在Eclipse中配置远程调试器图 1-20 Eclipse中显示的Hadoop调试窗口
调试过程中,JobTracker输出的信息被存储到日志文件夹下的hadoop-XXX-jobtracker-localhost.log文件(XXX为当前用户名)中,可通过以下命令查看调试过程中打印的日志:
tail-f logs/hadoop-XXX-jobtracker-localhost.log2.打印Hadoop调试日志[1]
Hadoop使用了Apache log4j作为基础日志库。该日志库将日志分为5个级别,分别为DEBUG、INFO、WARN、ERROR和FATAL。这5个级别对应的日志信息重要程度不同,它们的重要程度由低到高依次为DEBUG<INFO<WARN<ERROR<FATAL。日志输出规则为:只输出级别不低于设定级别的日志信息。比如,级别设定为INFO,则INFO、WARN、ERROR和FATAL级别的日志信息都会被输出,但级别比INFO低的DEBUG则不会被输出。
在Hadoop源代码中,大部分Java文件中存在调试日志(DEBUG级别日志),但默认情况下,日志级别是INFO。为了查看更详细的运行状态,可采用以下几种方法打开DEBUG日志。(1)使用Hadoop Shell命令
可使用Hadoop脚本中的daemonlog命令查看和修改某个类的日志级别,比如,可通过以下命令查看TaskTracker类的日志级别:
bin/hadoop daemonlog-getlevel${tasktracker-host}:50075\
org.apache.hadoop.mapred.TaskTracker
可通过以下命令将JobTracker类的日志级别修改为DEBUG:
bin/hadoop daemonlog-setlevel${tasktracker-host}:50075\
org.apache.hadoop.mapred.TaskTracker DEBUG
其中,tasktracker-host为TaskTracker的host,50075是TaskTracker的HTTP端口号(其他服务的HTTP端口号可参考附录B)。(2)通过Web界面
用户可以通过Web界面查看和修改某个类的日志级别,比如,可通过以下URL修改TaskTracker类的日志级别:
http://${tasktracker-host}:50075/logLevel(3)修改log4j.properties文件
以上两种方法只能暂时修改日志级别。当Hadoop重启后会被重置,如果要永久性改变日志级别,可在目标节点配置目录下的log4j.properties文件中添加以下配置选项:
log4j.logger.org.apache.hadoop.mapred.TaskTracker=DEBUG
此外,有时为了专门调试某个Java文件,需要把该文件的相关日志输出到一个单独文件中,可在log4j.properties中添加以下内容:
#定义输出方式为自定义的TTOUT
log4j.logger.org.apache.hadoop.mapred.TaskTracker=DEBUG, TTOUT
#设置TTOUT的输出方式为输出到文件
log4j.appender.TTOUT=org.apache.log4j.FileAppender
#设置文件路径
log4j.appender.TTOUT.File=${hadoop.log.dir}/TaskTracker.log
#设置文件的布局
log4j.appender.TTOUT.layout=org.apache.log4j.PatternLayout
#设置文件的格式
log4j.appender.TTOUT.layout.ConversionPattern=%d{ISO8601}%p%c:%m%n
这些配置选项会把TaskTracker.java中的DEBUG日志写到日志目录下的TaskTracker.log文件中。
在阅读源代码的过程中,为了跟踪某个变量值的变化,读者可能需要自己添加一些DEBUG日志。在Hadoop源代码中,大部分类会定义一个日志打印对象。通过该对象,可打印各个级别的日志。比如,在JobTracker中由以下代码定义对象LOG:
public static final Log LOG=LogFactory.getLog(JobTracker.class);
用户可使用LOG对象打印调试日志,比如,可在JobTracker的main函数首行添加以下代码:
LOG.debug("Start to lauch JobTracker……");
然后重新编译Hadoop源代码,并将org.apache.hadoop.mapred.JobTracker的调试级别修改为DEBUG,重新启动Hadoop后便可以看到该调试信息。
[1]Apache log4j网址:http://logging.apache.org/log4j/index.html1.7 小结
搭建一个高效的源代码学习环境是深入学习Hadoop的良好开端,本章主要内容正是帮助读者搭建一个这样的学习环境。在作者看来,一个高效的Hadoop学习环境至少应该包括源代码阅读环境、Hadoop使用环境和源代码编译调试环境,而本章正是围绕这三个环境的搭建方法编写的。
本章首先分别介绍了在Linux和Windows环境下搭建Hadoop源代码阅读环境的方法;在此基础上,进一步介绍了Hadoop的基本使用方法,主要涉及Hadoop Shell和Eclipse插件两种工具的使用;最后介绍了Hadoop源代码编译和调试方法,其中,调试方法主要介绍了使用Eclipse远程调试和打印调试日志两种。第2章MapReduce设计理念与基本架构
第1章介绍了Hadoop学习环境的搭建方法,这是学习Hadoop需要进行的最基本的准备工作。而在这一章中,我们将从设计理念和基本架构方面对Hadoop MapReduce进行介绍,同样,这属于准备工作的一部分。通过本章的介绍将会为后面几章深入剖析MapReduce内部实现奠定基础。
MapReduce是一个分布式计算框架,主要由两部分组成:编程模型和运行时环境。其中,编程模型为用户提供了非常易用的编程接口,用户只需要像编写串行程序一样实现几个简单的函数即可实现一个分布式程序,而其他比较复杂的工作,如节点间的通信、节点失效、数据切分等,全部由MapReduce运行时环境完成,用户无须关心这些细节。在本章中,我们将从设计目标、编程模型和基本架构等方面对MapReduce框架进行介绍。
试读结束[说明:试读内容隐藏了图片]