Hadoop2.6.0子專案hadoop-mapreduce-examples的簡單介紹

泰山不老生發表於2016-04-29

引文

學習Hadoop的同學們,一定知道如果執行Hadoop自帶的各種例子,以大名鼎鼎的wordcount為例,你會輸入以下命令:

hadoop org.apache.hadoop.examples.WordCount -D mapreduce.input.fileinputformat.split.maxsize=1 /wordcount/input /wordcount/output/result1

當然,有些人還會用以下替代方式:

hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0.jar wordcount /wordcount/input /wordcount/output/result1

相比於原始的執行方式,使用jar命令方式,讓我們不用再敲入繁瑣的完整包路徑。比如我們知道hadoop-mapreduce-examples專案中還提供了其它的例子,比如計算圓周率的例子,我們只需要記住此應用的簡單名字pi,就可以執行它:

hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0.jar pi 5 10

雖說我們只是使用這些現成的例子,沒有必要較真,但是這種簡潔的使用方式,無疑還是值得借鑑的。本文將分析下這種方式實現的原理,有興趣的同學可以一讀。

原始碼分析

這一節,我們通過對hadoop-mapreduce-examples專案中的關鍵原始碼進行分析,理解簡潔執行的原理。在hadoop-mapreduce-examples專案的pom.xml檔案中配置了org.apache.hadoop.examples.ExampleDriver作為jar命令的入口,配置如下:

   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-jar-plugin</artifactId>
      <configuration>
       <archive>
         <manifest>
           <mainClass>org.apache.hadoop.examples.ExampleDriver</mainClass>
         </manifest>
       </archive>
     </configuration>
    </plugin>

這決定了使用jar命令執行hadoop-mapreduce-examples-2.6.0.jar包時,實際執行了ExampleDriver的main方法,ExampleDriver的實現如下:

public class ExampleDriver {
  
  public static void main(String argv[]){
    int exitCode = -1;
    ProgramDriver pgd = new ProgramDriver();
    try {
      pgd.addClass("wordcount", WordCount.class, 
                   "A map/reduce program that counts the words in the input files.");
      // 省略其它例子的註冊程式碼
      pgd.addClass("pi", QuasiMonteCarlo.class, QuasiMonteCarlo.DESCRIPTION);
      // 省略其它例子的註冊程式碼
      exitCode = pgd.run(argv);
    }
    catch(Throwable e){
      e.printStackTrace();
    }
    
    System.exit(exitCode);
  }
}

以上程式碼構造了ProgramDriver的例項,並且呼叫其addClass方法,三個引數分別是例子名稱(如wordcount、pi等)、例子的實現Class、例子的描述資訊。ProgramDriver的addClass方法的實現如下:

  public void addClass(String name, Class<?> mainClass, String description)
      throws Throwable {
    programs.put(name , new ProgramDescription(mainClass, description));
  }

首先,構造ProgramDescription物件,其建構函式如下:

    public ProgramDescription(Class<?> mainClass, 
                              String description)
      throws SecurityException, NoSuchMethodException {
      this.main = mainClass.getMethod("main", paramTypes);
      this.description = description;
    }

其中main的型別是java.lang.reflect.Method,用於儲存例子Class的main方法。
然後,將例子名稱(如wordcount、pi等)和ProgramDescription例項註冊到programs中,programs的型別定義如下:

  /**
   * A description of a program based on its class and a 
   * human-readable description.
   */
  Map<String, ProgramDescription> programs;

ExampleDriver的main方法在最後會呼叫ProgramDriver的run方法,其實現如下:

  public int run(String[] args)
    throws Throwable 
  {
    // Make sure they gave us a program name.
    if (args.length == 0) {
      System.out.println("An example program must be given as the" + 
                         " first argument.");
      printUsage(programs);
      return -1;
    }
    
    // And that it is good.
    ProgramDescription pgm = programs.get(args[0]);
    if (pgm == null) {
      System.out.println("Unknown program `" + args[0] + "` chosen.");
      printUsage(programs);
      return -1;
    }
    
    // Remove the leading argument and call main
    String[] new_args = new String[args.length - 1];
    for(int i=1; i < args.length; ++i) {
      new_args[i-1] = args[i];
    }
    pgm.invoke(new_args);
    return 0;
  }

ProgramDriver的run方法執行的步驟如下:

  1. 引數長度校驗;
  2. 根據第一個引數,從programs中查詢對應的ProgramDescription例項;
  3. 將其餘的引數傳遞給ProgramDescription的invoke方法,進而執行對應的例子。
    ProgramDescription的invoke方法的實現如下:
    public void invoke(String[] args)
      throws Throwable {
      try {
        main.invoke(null, new Object[]{args});
      } catch (InvocationTargetException except) {
        throw except.getCause();
      }
    }

由此我們知道具體例子的執行,是通過反射呼叫具體例子Class的main方法,最終實現的。

後記:個人總結整理的《深入理解Spark:核心思想與原始碼分析》一書現在已經正式出版上市,目前京東、噹噹、天貓等網站均有銷售,歡迎感興趣的同學購買。
_

京東(現有滿150減50活動)):http://item.jd.com/11846120.html
噹噹:http://product.dangdang.com/23838168.html


相關文章