Hadoop源码分析(完整版)

所需积分/C币:50 2015-06-06 18:53:50 6.47MB PDF
42
收藏 收藏
举报

Hadoop源码分析(完整版),详细分析了Hadoop源码程序,为学习Hadoop的人提供很好的入门指导
表示层。将各种数据编码/解码,方便于在网络上 传输 net 封装部分网络功能,如DNS, socket security用户和用户组信息 con 系统的配置参数 metrics 系统统计数据的收集,属于网管范畴 util 工具类 record 根据DDL(数据描述语言)自动生成他们的编解 码函数,目前可以提供C++和Java http 基于etty的 Http seRvlet,用户通过浏览器可 以观察文件系统的一些状态信息和日志 lod 提供HTTP访问日志的HttpServlet Hadoop源代码分析(三) 由于 Hadoop的 MapReduce和HDFS都有通信的需求需要对通信的对象进行序列化。 Hadoop并没有采用Java的序列化, 而是引入了它自己的系统。 org. apache hadoop. io中定义了大量的可序列化对象,他们都实现了 Writable接口。实现了 Writable接口的一个典型例子 如下: Java代码 1. public class MyWritable implements Writable 2.∥ Some data private int counter, private long timestamp 5678 public void write(Data Output out)throws IOEXception out. writeInt(counter out writeLong(timestamp): 11. public void read Fields(DataInput in) throws IOException counter= in. readinto 13. timestamp=in. readlong0: 14. 16. public static MyWritable read(DataInput in)throws IOException t My Writable w= new My Writable O wread Fields(in) 19. retur 21.} 其中的 write和 read fields分别实现了把对象序列化和反序列化的功能,是 Writable接口定义的两个方法。下图给出了庞大 的 org. apache hadoop. io中对象的关系。 这里,我把 ObjectWritable标为红色,是因为相对于其他对象,它有不同的地位。当我们讨论 Hadoop的RPC时,我们会 提到RPC上交换的信息,必须是Java的基本类型, String和 Writable接口的实现类,以及元素为以上类型的数组。 ObjectWritable对象保存了一个可以在RPC上传输的对象和对象的类型信息。这样,我们就有了一个万能的,可以用于客户 端/服务器间传输的 Writable对象。例如,我们要把上面例子中的对象作为RPC请求,需要根据 MyWritable刨建一个 ObjectWritable, ObjectWritable往流里会写如下信息 类名长度,欢象类名,象自己的生行化结果 这样,到了对端, ObjectWritable可以根据对象类名创建对应的对象,并解串行。应该注意到, ObjectWritable依赖于 Writablefactories,那存储了 Writable子类对应的工厂。我们需要把 My Writable的工厂,保存在 Writable factories中(通 过 WritableFactories, retRactory)。 Hadoop源代码分析(五) 介绍完σ rg. apache hadoop. io以后,我们开始来分析 org. apache hadoop rpc。RPC采用客户机/服务器模式。请求程序就 是一个客户机,而服务提供程序就是一个服务器。当我们讨论HDFS的,通信可能发生在 Client- Namenode之间,其中 Namenode是服务器 Client- Datanode之间,其中 DataNode是服务器 Datanode- NameNode之间,其中 Namenode是服务器 Datanode- DateNode之间,其中某一个 DateNode是服务器,另一个是客户端 如果我们考虑 Hadoop的Map/ Reduce以后,这些系统间的通信就更复杂了。为了解决这些客户机/服务器之间的通信 Hadoop引入了一个RPC框架。该RPC框架利用的Java的反射能力,避兔了某些RPC解决方案中需要根据某种接口语言(如 CORBA的IDL)生成存根和框架的问题。但是,该RPC框架要求调用的参数和返回结果必须是Java的基本类型, String和 Writable接口的实现类,以及元素为以上类型的数组。同时,接口方法应该只抛出 IOEXception异常。(参考自 http://zhangyu8374javaeye.com/blog/86306) 既然是RPC,当然就有客户端和服务器,当然, org. apache hadoop rpc也就有了类 Client和类 Server。但是类 Server是一 个抽象类,类RPC封装了 Server,利用反射,把某个对象的方法开放出来,变成RPC中的服务器。 下图是 org. apache hadoop rpc的类图。 caanertions: Fasldnb e-itonoctiorId C3 Wier listener ListenEr -tinlAulress: Stms tepE clay bol=an SPont 点( Jin tiNy: Sect story getRenualF): -nisuke: AEdresy lL.CJuL) ieraRetencd Writhe n veTirr - IHs,w1 Responder RIC EpEe lesmond(in call Se ver. Call nerierat nn: Cass.> LAnDler Client CAll (r:r址:hr当 medIne: kagI: adalin aa l- Cliet. cal s: bouen RPC Exertion boa cal r.prare: write sndPuranmin sundaram: Clit Cul atforFuty( IE.gPA题 ess<>. in clientwesicn: JTE, ir adr, n t xponx QLcu:: -inked _ixwcalla pl*t> setra:ct valx:"wrtat 4 IICLILNTS (lieat. ParallelCadl - resuls ickt:Lr:Go即 plaforautin Envncatlo Fdtetbs: Hzshidap-Soxi keita:iuy, tlsTl'? n factry: Sack:,: Clie t k erver call lurId,Pr P-xmnelerConfiguraticn:C'ieTe Seiner Ciutat iu以t.Uh其n用 apone; ytellutrer 对rmd: Matlin.srg;x中水a cL儿 vesianadProoned Hadoopρ源代码分析(六) 既然是RPC,自然就有客户端和服务器,当然, org. apache hadoop rpc也就有了类cent和类 Server。在这里我们来仔细 考察 org. apache hadoop rpc Client。下面的图包含了 org. apache hadoop rpc Client中的关键类和关键方法。 由于 Client可能和多个 Server通信,典型的一次HDFS读,需要和 Namenode打交道,也需要和某个/某些 Datanode通 信。这就意味着某一个 Client需要维护多个连接。同时,为了减少不必要的连接,现在 Client的做法是拿 Connectionld(图 中最右侧)来做为 Connection的ID。 ConnectionId包括一个 InetSocketAddress(IP地址+端口号或主机名+端口号)对 象和一个用户信息对象。这就是说,同一个用户到同一个 Inetsocketaddress的通信将共享同一个连接。 ava. laag Threat Client connection conections Hashtable<Camectionld cornectiur> amiss: Witht ra.alain call)hanlan - remold ClienTE mumucliunlu -rurming: boolean waitFor Wor(): boolean configurutis enpIng) H-lieket UseiGrapllonmali mEdDle Time: in eIIParaln(iu MeIrlPuiain Client Call HtcpNoDelay: boolean soKletHactory: SosetHucmy isceroReterenct Client C all in parra: Writable[. in addres Ncw: IneSock:Address1): Writable am writable 上rmr:Oxr Callin param: writable ItyctYal c(iil value. wital t lient Parallell all[results -values: Wrings e 连接被封装在类 Client connection中,所有的RPC调用,都是通过 Connection,进行通信。一个RPC调用,自然有输入 参数,输出参数和可能的异常,同时,为了区分在同一个 Connection上的不同调用,每个调用都有唯一的id。调用是否结束 也需要—个标记所有的这些都体现在对象 Client. cal中。 Connection对象通过一个Hash表维护在这个连接上的所有Cal Java代码 1. private Hashtable<Integer, Call> calls new Hashtable<Integer, Call>o 个RPC调用通过 adda,把请求加到 Connection里。为了能够在这个框架上传输Java的基本类型, String和 Writab|e 接口的实现类,以及元素为以上类型的数组,我们一般把Ca要的参数打包成为 ObjectWritable对象 Client< onnection会通过 socket连接服务器连接成功后回校验客户端服务器的版本号( Client. Connectionwrite Header 方法),校验成功后就可以通过 Writable对象来进行请求的发送/应答了。注意,每个 Client connection会起一个线程,不 断去读取 socket,并将收到的结果解包,找出对应的Cal,设置Ca‖!并通知结果已经获取。 Cl!使用 obejct的wait和 notify,把RPC上的异步消息交互转成同步调用 还有一点需要注意,一个 Client会有多个 lient Connection,这是一个很自然的结果。 Hadoop源代码分析(七) 聊完了 Client聊 Server,按惯例,先把类图贴出来 ava.lang Thread Listener idoaccepr() Sener serier -bindAddress: String amup Connection( Responder eallQusue: BlockinyQueue call> serv HagetRemotelp): InetSocketAddress handlers Hdo Purged ocessResponser) H+doRespondtin cal]:ServerCall) lose Connection(y I-conneetionList erver Connection hannel: Socketchannel response Queue LinkedList <call> server call HostAddiress) -param: Writable eadAndProuess on: Server Connection H----- hEaded mess tad timestamp: long timeoUt) 需要注意的是,这里的 Server类是个抽象类,唯一抽象的地方,就是 Java代码 1. public abstract Writable call(Writable param, long receive Time) throws IO Exception: 这表明,Seve提供了一个架子, Server的具体功能,需要具体类来完成。而具体类,当然就是实现cl!方法。 我们先来分析 Server:Cal,和 Client. ca‖类似, Server. cal包含了一次请求,其中,id和paam的含义和 Client叫l是一 致的。不同点在后面三个属性, con nection是该C来自的连接,当然,当请求处理结束时,相应的结果会通过相同的 connection,发送给客户端。属性 timestamp是请求到达的时间戳,如果请求很长时间没被处理,对应的连接会被关闭,客 户端也就知道岀错了。最后的 response是请求处理的结果,可能是一个 Writable的串行化结果,也可能-个异常的串行化结 果 Server. Connection维护了一个来之客户端的 socket连接。它处理版本校验,读取请求并把请求发送到请求处理线程,接收 处理结果并把结果发送给客户端 Hadoop的 Server采用了Java的NIO,这样的话就不需要为每一个 socket连接建立一个线程,读取 socket上的数据。在 Server中,只需要一个线程,就可以 accept新的连接请求和读取 socket上的数据,这个线程,就是上面图里的 Listener。 请求处理线程一般有多个,它们都是 Server Handle类的实例。它们的run方法循环地取出一个 Server. Ca‖!,调用 Server call 方法,搜集结果并串行化,然后将结果放入 Responder队列中 对于处理完的请求,需要将结果写回去,同样,利用NIO,只需要一个线程,相关的逻辑在 Responder里 Hadoop源代码分析(八) (注:本节需要用到一些Java反射的背景) 有了 Client和 Server,很自然就能RPC啦。下面轮到 RPC java啦。 般来说,分布式对象一般都会要求根据接口生成存根和框架。如 CORBA,可以通过IDL,生成存根和框架。但是,在 org. apache hadoop rpc,我们就不需要这样的步骤了。上类图。 bixdAddress: String Queue i B ockitgqeue-call Full in perun: Writ ble, in receive T ims: Long): Writable RPC SeRveR Iemerrati: Classs> InvoeationHendler 555Naime Baselin elassName: String): String in param: Writ le, in mereiued'Time: long): writable RPC ddess: Inersesket Address etPruxy(in protos Class<>, in s ent version: lomg. in addr, in ti. ket, in conE, in fas tory isClosec: boclean revert +invoket(in proxy: Object. in me lod: Method, in xgs ObjecT[D): Ob I-CLENTS HEA>>org.e ache adop.io: Writable RPCClentc: ent: Client 为了分析 Invoker,我们需要介绍一些Java反射实现 Dynamic Proxy的背景。 Dynamic Proxy是由两个 class实现的 java. lang reflect Proxy和 java. lang. reflectInvocation handler,后者是一个接口 所谓 Dynamic Proxy是这样一种cass:它是在运行时生成的 class,在生成它时你必须提供一组 interface给它,然后该dass 就宣称它实现了这些 interface。 这个 Dynamic Proxy其实就是一个典型的Proy模式,它不会替你作实质性的工作,在生成它的实例时你必须提供一个 handler,由它接管实际的工作。这个 handler,在 Hadoop的RPC中,就是 Invoker对象 我们可以简单地理解:就是你可以通过一个接口来生成一个类,这个类上的所有方法调用,都会传递到你生成类时传递的 InvocationHandler实现中。 在 Hadoop的RPC中, Invoker实现了 Invocation handler的 invoke方法( invoke方法也是 Invocation handler的唯一方 法)。 Invoker会把所有跟这次调用相关的调用方法名,参数类型列表,参数列表打包,然后利用前面我们分析过的 Client, 通过 socke传递到服务器端。就是说,你在 proxy类上的任何调用,都通过 Client发送到远方的服务器上 Invoker使用 Invocation。 Invocation封装了一个远程调用的所有相关信息,它的主要属性有: methodName,调用方法名, parameterClasses,调用方法参数的类型列表和 parameters,调用方法参数。注意,它实现了 Writable接口,可以串行化。 RPC Server实现了 org. apache hadoop ipc Server,你可以把一个对象,通过RPC,升级成为一个服务器。服务器接收到的 请求(通过 Invocation);解串行化以后,就变成了方法名;方法参数列表和参数列表。利用Java反射,我们就可以调用对 应的对象的方法。调用的结果再通过 socket,返回给客户端,客户端把结果解包后,就可以返回给 Dynamic Proxy的使用者 Hadoop源代码分析(九) 一个典型的HDFS系统包括一个 NameNode和多个 Data Node。 NameNode维护名字空间;而 DataNode存储数据块。 DataNode负责存储数据,一个数据块在多个 Datanode中有备份;而一个 Datanode对于一个块最多只包含一个备份。所 以我们可以简单地认为 Datanode上存了数据块ID和数据块內容,以及他们的映射关系。 一个HDFS集群可能包含上千 Data node节点,这些 Datanode定时和 Namenode通信,接受 Namenode的指令。为了 减轻 NameNode的负担, NameNode上并不永久保存那个 DataNode上有那些数据块的信息,而是通过 DataNode启动 时的上报,来更新 Namenode上的映射表 DataNode和 NameNode建立连接以后,就会不断地和 Namenode保持心跳。心跳的返回其还也包含了 Namenode对 Data node的一些命令,如删除数据库或者是把数据块复制到另一个 Data node。应该注意的是: Namenode不会发起到 DataNode的请求,在这个通信过程中,它们是严格的客户端/服务器架构。 Datanode当然也作为服务器接受来自客户端的访问,处理数据块读/写请求。 Datanode之间还会相互通信,执行数据块复 制任务,同时,在客户端做写操作的时候, Datanode需要相互配合,保证写操作的一致性。 下面我们就来具体分析一下 Datanode的实现。 Datanode的实现包括两部分,一部分是对本地数据块的管理,另一部分, 就是和其他的实体打交道。我们先来看本地数据块管理部分。 安装 Hadoop的时候,我们会指定对应的数据块存放目录,当我们检查数据块存放目录目录时,我们回发现下面有个叫dfs的 目录,所有的数据就存放在dts/data里面 208-11-2715:41 Detach 2008-11-1410z3:0D edtmp 200-11-2715:41:m0 回n_ use lock 2Us-11-141028:00 回 orage 157 2DB-11-1410H28:0 其中有两个文件, storage里存的东西是一些出错信息,貌似是版本不对云云。 in use. lock是一个空文件,它的作用是如果 需要对整个系统做排斥操作,应用应该获取它上面的一个锁。 接下来是3个目录, current存的是当前有效的数据块, detach存的是快照( snapshot,目前没有实现),tmp保存的是 些操作需要的临时数据块 但我们进λα urrent目录以后,就会发现有一系列的数据块文件和数据块元数据文件。同时还有一些子目录,它们的名字是 subdir到 subdir63,子目录下也有数据块文件和数据块元数据。这是因为HDFS限定了每个目录存放数据块文件的数量,多 了以后会创建子目录来保存。 数据块文件显然保存了HDFS中的数据,数据块最大可以到64M。每个数据块文件都会有对应的数据块元数据文件。里面存 放的是数据块的校验信息。下面是数据块文件名和它的元数据文件名的例子 bk3148782637964391313 b|k3148782637964391313242812meta 上面的例子中,3148782637964391313是数据块的D号,242812是数据块的版本号,用于一致性检查。 在 current目录下还有下面几个文件 VERSION,保存了一些文件系统的元信息 dncp_block_verification. log. curr和 dncp _block_verification. log. prev,它记录了一些 DataNode对文件系定时统做—致性 检查需要的信息、 Hadoop源代码分析(一零) 在继续分析 Datanode之前,我们有必要看一下系统的工作状态。启动HDFS的时候,我们可以选择以下启动参数 FORMAT("- format"):格式化系统 REGULAR("- regular"):正常启动 UPGRADE("- upgrade"):升级 ROLLBACK("- rollback"):回滚 FINALIZE("- finalize"):提交 IMPORT("- import Checkpoint"):从 Checkpoint恢复。 作为一个大型的分布式系统, Hadoop内部实现了一套升级机制(htt// wiki. apache:org/ hadoop/ Hadoop_ Upgrade)。 upgrade参数就是为了这个目的而存在的,当然,升级可能成功,也可能失败。如果失败了,那就用 rollback进行回滚;如 果过了一段时间,系统运行正常,那就可以通过 finalize,正式提交这次升级(跟数据库有点像啊) import checkpoint选项用于 Namenode发生故障后,从某个检查点恢复 有了上面的描述,我们得到下面左边的状态图

...展开详情
试读 109P Hadoop源码分析(完整版)
立即下载 低至0.43元/次 身份认证VIP会员低至7折
一个资源只可评论一次,评论内容不能少于5个字
luyuefeng 不错挺详细的,入门的教材很好
2020-02-22
回复
JB_Goingdown 很好的资源,谢了
2018-08-10
回复
zxx178239 慢慢啃的书
2018-03-14
回复
cs_assassin 不错挺详细的
2016-07-23
回复
u010588763 作为入门的教材,不错
2016-03-30
回复
anbanglee 不错挺详细的
2015-11-18
回复
Hsienhua 不错 ,刚入门,还要多学习
2015-09-24
回复
leobelive 还不错,比较详细。
2015-08-20
回复
qq_24479795 我觉得写很不错,至少我是理解多了。
2015-08-16
回复
KRI-神 好东西,值得学习.
2015-08-10
回复
上传资源赚积分or赚钱
    最新推荐
    Hadoop源码分析(完整版) 50积分/C币 立即下载
    1/109
    Hadoop源码分析(完整版)第1页
    Hadoop源码分析(完整版)第2页
    Hadoop源码分析(完整版)第3页
    Hadoop源码分析(完整版)第4页
    Hadoop源码分析(完整版)第5页
    Hadoop源码分析(完整版)第6页
    Hadoop源码分析(完整版)第7页
    Hadoop源码分析(完整版)第8页
    Hadoop源码分析(完整版)第9页
    Hadoop源码分析(完整版)第10页
    Hadoop源码分析(完整版)第11页
    Hadoop源码分析(完整版)第12页
    Hadoop源码分析(完整版)第13页
    Hadoop源码分析(完整版)第14页
    Hadoop源码分析(完整版)第15页
    Hadoop源码分析(完整版)第16页
    Hadoop源码分析(完整版)第17页
    Hadoop源码分析(完整版)第18页
    Hadoop源码分析(完整版)第19页
    Hadoop源码分析(完整版)第20页

    试读结束, 可继续阅读

    50积分/C币 立即下载 >