Hadoop工作流引擎之JobControl
- Hadoop自帶的工作流控制主要包括依賴關係組合式(JobControl)MapReduce和鏈式(Chain)MapReduce兩類。
PS:需要注意的是目前由於Hadoop有新舊兩套API,分別對應源代碼裏的mapred和mapreduce兩個包,JobControl和Chain在這兩種API中的用法是不一樣的,而且Hadoop1.x目前海不支持Chain的新API調用(0.21.0支持,不過它只是一個過渡版本)。
- JobControl由兩個類組成:Job和JobControl。其中,Job類封裝了一個MapReduce作業及其對應的依賴關係,主要負責監控各個依賴作業的運行狀態,以此更新自己的狀態,其狀態轉移圖如下圖所示。作業剛開始處於WAITING狀態。如果沒有依賴作業或者所有依賴作業均已運行完成,則進入READY狀態。一旦進入READY狀態,則作業可被提交到Hadoop集羣上運行,並進入RUNNING狀態。在RUNNING狀態下,根據作業運行情況,可能進入SUCCESS或者FAILED狀態。需要注意的是,如果一個作業的依賴作業失敗,則該作業也會失敗,於是形成“多米諾骨牌效應”後續所有作業均會失敗。
編程示例(新API):........Configuration conf = new Configuration();Job job = new Job(conf, "word count");job.setJarByClass(WordCount.class);job.setMapperClass(TokenizerMapper.class);job.setCombinerClass(IntSumReducer.class);job.setReducerClass(IntSumReducer.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(IntWritable.class);FileInputFormat.addInputPath(job, new Path(otherArgs[0]));FileOutputFormat.setOutputPath(job, new Path("/output1"));Configuration conf2 = new Configuration();Job job2 = new Job(conf2, "word count1");.................Configuration conf3 = new Configuration();Job job3 = new Job(conf3, "word count2");.................ControlledJob controlledJob1 = new ControlledJob(job.getConfiguration());controlledJob1.setJob(job);ControlledJob controlledJob2 = new ControlledJob(job2.getConfiguration());controlledJob2.setJob(job2);ControlledJob controlledJob3 = new ControlledJob(job2.getConfiguration());controlledJob3.setJob(job3);controlledJob1.addDependingJob(controlledJob2);controlledJob1.addDependingJob(controlledJob3);JobControl jobControl = new JobControl("test");jobControl.addJob(controlledJob1);jobControl.addJob(controlledJob2);jobControl.addJob(controlledJob3);Thread thread = new Thread(jobControl);thread.start();while(true){if(jobControl.allFinished()){System.out.println(jobControl.getSuccessfulJobList());jobControl.stop();System.exit(0);}if(jobControl.getFailedJobList().size() > 0){System.out.println(jobControl.getFailedJobList());jobControl.stop();System.exit(1);}}
- ChainMapper/ChainReducer主要爲了解決線性鏈式Mapper 而提出的。也就是說,在Map或者Reduce階段存在多個Mapper,這些Mapper像Linux管道一樣,前一個Mapper的輸出結果直接重定向到下一個Mapper 的輸入,形成一個流水線,形式類似於 [MAP+REDUCE MAP*]。下圖展示了一個典型的ChainMapper/ChainReducer的應用場景:在Map階段,數據依次經過Mapper1和Mapper2處理;在Reduce階段,數據經過shuffle
sort後;交由對應的 Reducer處理,但Reducer處理之後並沒有直接寫到HDFS上,而是交給另外一個Mapper處理,它產生的結果寫到最終的HDFS輸出目錄中。
PS:需要注意的是,對於任意一個MapReduce作業,Map和Reduce階段可以有無限個Mapper,但Reducer只能有一個也就是說,下圖所示的計算過程不能使用ChainMapper/ChainReducer完成,而需要分解成兩個MapReduce 作業。
新API編程示例(1.x不支持),摘自Hadoop API說明文檔:...Job = new Job(conf);Configuration mapAConf = new Configuration(false);...ChainMapper.addMapper(job, AMap.class, LongWritable.class, Text.class,Text.class, Text.class, true, mapAConf);Configuration mapBConf = new Configuration(false);...ChainMapper.addMapper(job, BMap.class, Text.class, Text.class,LongWritable.class, Text.class, false, mapBConf);...job.waitForComplettion(true);......Job = new Job(conf);....Configuration reduceConf = new Configuration(false);...ChainReducer.setReducer(job, XReduce.class, LongWritable.class, Text.class,Text.class, Text.class, true, reduceConf);ChainReducer.addMapper(job, CMap.class, Text.class, Text.class,LongWritable.class, Text.class, false, null);ChainReducer.addMapper(job, DMap.class, LongWritable.class, Text.class,LongWritable.class, LongWritable.class, true, null);...job.waitForCompletion(true);...
- 簡單對比
Hadoop自帶的JobControl和Chain的工作流控制可以處理一些簡單的工作流控制,同時相對與Azkaban和Oozie它不需要安裝,使用簡單方便。但是它的功能遠遠不如後兩者,比較明顯的缺點是它不可以跟蹤運行進度(僅能跟蹤是否結束),沒有重試功能,沒有定時執行功能,並且只能控制用Java寫的Mapeduce任務(不支持Pig,Shell等)。
總體來講Hadoop自帶的工作流控制還是有用的,能滿足一些簡單的常規使用,可以作爲Azkaban或Oozie的補充來使用。