5.1 从“地方”到“中央”
如前所述,在Hadoop集群的YARN框架中,ResourceManager所在的节点起着“中央”的作用,这个节点统管着整个集群的计算(HDFS文件系统的运行另当别论),其余的节点则都处于相当于“地方”的地位。但是作业并非一定得在“中央”节点上才能提交,而完全可以从某个“地方”节点上提交。所以,作为典型的情景,作业提交的流程始自“地方”节点,但是会被提交给“中央”,然后由“中央”根据作业本身的要求(比方说需要有多少个Mapper、多少个Reducer,它们的数据从哪来,等等)和当时集群中的具体情况确定应该将此作业安排到哪些节点上去运行,并将其投运。不过,本章所关心的只是将作业提交到“中央”的过程,其余都是后面各章要关心的事。
这意味着,作业提交的过程涉及“地方”和“中央”两个节点上的程序流程。实际上这当然也涉及两个节点之间的IPC通信,但是我们现在可以不关心底层的细节。这样,作业提交的流程就自然分成了两段,我们不妨称之为“地方流程”和“中央流程”。而其中的第一段流程,就是在“地方”上的那一段,由于Hadoop提供了多种提交作业的途径,即多种具体的API(应用程序设计界面),而又可进一步分成两个阶段。这里先做点简单的介绍。
“地方流程”的第一阶段由三个平行的分支构成,这就是在Hadoop上提交作业的三种方法,就好像地铁站有三个入口一样。这三种方法最后都汇聚在一起,于是就开始了“地方流程”的第二阶段。
从汇聚点开始的“地方流程”第二阶段,是作业提交流程的主体。在这一段流程中,“地方”要为具体的作业向“中央”打报告,形成一个作业请求,并把有关这个作业的相关材料随同报送“中央”。这段流程要到把所有这些材料都发送到“中央”才算完成。
然后就是“中央”的事了。因为本章讲的只是作业的提交,所以这段“中央流程”至少在概念上是比较简单的,只是为这个作业“立案”,并将其排入一个队列,这就完成了作业的提交。至于对这个作业请求的处理,那是后面调度和指派的事了。
下面我们先讲作业提交的第一段流程,即“地方流程”的第一阶段。
如上所述,Hadoop为程序员提供了三种提交作业的方法,提供了三种这样的API。之所以有三种不同的方法,是因为Hadoop在其历史上曾经提供了新、老两种API,此外还提供了另一种变通的方法。这三种方法是:
(1)JobClient.runJob():调用由JobClient类提供的方法runJob(),这是所谓老API。
(2)Job.waitForCompletion():调用由Job类提供的方法waitForCompletion(),属于新API。
(3)ToolRunner.run():调用由ToolRunner类所提供的方法run()。这是一种变通的方法。
然而,光是知道有这么三种方法,并知道各自的界面定义(函数调用的参数表),还不足以向Hadoop正确提交一个作业。这是因为:所谓提交一个作业,主要就是提交一对Mapper和Reducer,这有可能是由系统提供的,也可能是由用户(程序员)开发的,实际的应用中以后者为多,所以这也牵涉到如何设计和实现具体的Mapper和Reducer的问题。而且,在提交具体的作业时,必须填写一份类似于申请表那样的东西。填写过各种申请表的人都知道,那常常是很令人沮丧的事情,最好能有示例和样板。
正因为如此,Hadoop的源码中提供了不少关于MapReduce编程的示例,这些示例自然也可用来作为Hadoop作业提交的示例。这些示例的源码基本上都在源码包内的目录hadoop-mapreduce-proj ect/hadoop-mapreduce-examples中。这些示例都在教我们怎样进行MapReduce编程和作业提交。同时,对于我们来说更重要的是,可以用这些示例作为情景分析的起点,来分析一个作业在Hadoop平台上从提交到完成的完整过程。
其实不光是这个专门的目录下面有好多MapReduce编程示例,Hadoop源码中还有许多别的测试程序,这些测试程序在一定程度上都可以用作编程示例。此外,Hadoop源码中还有一些工具性的、中间层次的类,这些类对于用户而言是Hadoop的一部分,但是对于Hadoop的基础平台而言却又类似应用并且可以直接启动执行,这样的类也可以用作示例。
既然提交作业即应用程序(App)的方法有三种,我们就通过三个不同的示例来分析在Hadoop上提交具体作业的流程。