hadoop學習筆記(1) 開發環境

剛開始學習hadoop,首先搭建了一下開發環境,最開始是在單獨編寫Map-Reduce程序,然後在命令行編譯,再通過hadoop命令運行打好的jar包,雖然也能夠運行,但是總感覺這樣用起來很麻煩,所以今晚又嘗試了直接通過eclipse來編輯和運行Map-Reduce程序,瞎弄了一下,居然讓我弄成功了,自然走了點彎路,擔心以後再走彎路,所以把自己的搭建過程記錄於此。

1.準備

1.1 軟件

redhat 6

hadoop-0.20.2 

java 1.6

1.2 java環境

修改環境變量,我這裏是修改的用戶目錄下的.bash_profile文件,在該文件中添加如下內容:

JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0
CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
PATH=$PATH:JAVA_HOME/bin
export JAVA_HOME
export CLASSPATH
export PATH

然後執行如下命令使修改對當前環境有效

% source /root/.bash_profile

我這裏的修改僅僅對當前用戶有效,如果想對所有用戶都有效,則要修改/etc/profile文件。另外,修改環境變量也可以直接在終端直接執行上述命令,不過這樣修改只對當前shell環境有效。

2.hadoop安裝

可以從http://hadoop.apache.org/common/releases.html#Download下載hadoop-0.20.2,再解壓到系統本地文件系統,我是解壓到/root/hadoop/目錄:

% tar xzf hadoop-0.20.2.tar.gz

創建一個指向hadoop安裝目錄的環境變量(HADOOP_HOME),再把hadoop的安裝路徑放到命令行路徑上(我還是修改的/root/.bash_profile文件):

HADOOP_HOME=/root/hadoop/hadoop-0.20.2
CLASSPATH=$CLASSPATH:$HADOOP_HOME/hadoop-0.20.2-core.jar
PATH=$PATH:$HADOOP_HOME/bin
export HADOOP_HOME
export CLASSPATH
export PATH

至此,hadoop基本環境搭建完成,如想在獨立模式(local mode)下運行,此環境已足夠。可以通過在終端下輸入如下命令來驗證:

% hadoop version

會輸出如下內容:

Hadoop 0.20.2
Subversion https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20 -r 911707
Compiled by chrisdo on Fri Feb 19 08:07:34 UTC 2010

3.命令行環境運行

以下的例子是來自《hadoop權威指南》。

在/root/hadoop目錄下創建java文件NewMaxTemperature.java:

// cc NewMaxTemperature Application to find the maximum temperature in the weather dataset using the new context objects MapReduce API
package ch2;

import java.io.IOException;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

// vv NewMaxTemperature
public class NewMaxTemperature {
  
  static class NewMaxTemperatureMapper
    /*[*/extends Mapper<LongWritable, Text, Text, IntWritable>/*]*/ {

    private static final int MISSING = 9999;
    
    public void map(LongWritable key, Text value, /*[*/Context context/*]*/)
        throws IOException, /*[*/InterruptedException/*]*/ {
      
      String line = value.toString();
      String year = line.substring(15, 19);
      int airTemperature;
      if (line.charAt(87) == '+') { // parseInt doesn't like leading plus signs
        airTemperature = Integer.parseInt(line.substring(88, 92));
      } else {
        airTemperature = Integer.parseInt(line.substring(87, 92));
      }
      String quality = line.substring(92, 93);
      if (airTemperature != MISSING && quality.matches("[01459]")) {
        /*[*/context.write/*]*/(new Text(year), new IntWritable(airTemperature));
      }
    }
  }
  
  static class NewMaxTemperatureReducer
    /*[*/extends Reducer<Text, IntWritable, Text, IntWritable>/*]*/ {
  
    public void reduce(Text key, /*[*/Iterable/*]*/<IntWritable> values,
        /*[*/Context context/*]*/)
        throws IOException, /*[*/InterruptedException/*]*/ {
      
      int maxValue = Integer.MIN_VALUE;
      for (IntWritable value : values) {
        maxValue = Math.max(maxValue, value.get());
      }
      /*[*/context.write/*]*/(key, new IntWritable(maxValue));
    }
  }

  public static void main(String[] args) throws Exception {
    if (args.length != 2) {
      System.err.println("Usage: NewMaxTemperature <input path> <output path>");
      System.exit(-1);
    }
    
    /*[*/Job job = new Job();
    job.setJarByClass(NewMaxTemperature.class);/*]*/

    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    
    job.setMapperClass(NewMaxTemperatureMapper.class);
    job.setReducerClass(NewMaxTemperatureReducer.class);

    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    
    /*[*/System.exit(job.waitForCompletion(true) ? 0 : 1);/*]*/
  }
}
// ^^ NewMaxTemperature
然後使用如下命令編譯該文件:

% javac -d ./ NewMaxTemperature.java

編譯的結果是在/root/hadoop/文件夾下生成了一個文件夾ch2,這是上面編譯結果類的包名,文件夾裏面包含如下三個.class文件:

NewMaxTemperature.class

NewMaxTemperature$NewMaxTemperatureMapper.class

NewMaxTemperature$NewMaxTemperatureReducer.class

接下來是將上面的ch2文件夾打包成可執行的jar包,方便hadoop調用執行。爲了打jar包,首先在/root/hadoop/目錄下創建文本文件manifest.mf,該文件內容如下:

Main-Class: ch2.NewMaxTemperature

注意:冒號後面一定要加一個空格,否則後果自負。

然後執行如下命令:

% jar cvfm ch2.jar manifest.mf ch2

不出意外,現在在/root/hadoop/目錄下應該已經生成了ch2.jar文件,OK,大功告成,這就是我們想要的,接下來就是通過hadoop命令來執行我們的第一個Map-Reduce程序了。哦,忘了,Map-Reduce程序是用來進行離線數據處理的,我們還沒有數據,無的放矢啊,既然Tom White先生(《hadoop權威指南》的作者)貢獻了他的上述程序,他當然也會爲我們提供數據集啦,對,數據集和上述源碼都可以從http://www.hadoopbook.com這裏獲取。我這裏用的是源碼包裏的sample.txt數據集,裏面內容很簡單,就下面五行數據(數據的含義參考《hadoop權威指南》):

0067011990999991950051507004+68750+023550FM-12+038299999V0203301N00671220001CN9999999N9+00001+99999999999
0043011990999991950051512004+68750+023550FM-12+038299999V0203201N00671220001CN9999999N9+00221+99999999999
0043011990999991950051518004+68750+023550FM-12+038299999V0203201N00261220001CN9999999N9-00111+99999999999
0043012650999991949032412004+62300+010750FM-12+048599999V0202701N00461220001CN0500001N9+01111+99999999999
0043012650999991949032418004+62300+010750FM-12+048599999V0202701N00461220001CN0500001N9+00781+99999999999
我們將sample.txt數據集放到/root/hadoop/文件夾下。OK,到這裏真就大功告成了,只需要執行如下命令進行驗證就可以了:

$ hadoop jar ch2.jar sample.txt output

ok,看到了什麼,是不是刷刷刷一串輸出,這就是上面作業運行的輸出的一些提示信息(考慮到篇幅問題,這裏只是部分輸出):

11/12/14 23:23:13 INFO jvm.JvmMetrics: Initializing JVM Metrics with processName=JobTracker, sessionId=
11/12/14 23:23:14 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
11/12/14 23:23:14 INFO input.FileInputFormat: Total input paths to process : 1
11/12/14 23:23:14 INFO mapred.JobClient: Running job: job_local_0001
11/12/14 23:23:14 INFO input.FileInputFormat: Total input paths to process : 1
11/12/14 23:23:14 INFO mapred.MapTask: io.sort.mb = 100
11/12/14 23:23:14 INFO mapred.MapTask: data buffer = 79691776/99614720
11/12/14 23:23:14 INFO mapred.MapTask: record buffer = 262144/327680
11/12/14 23:23:14 INFO mapred.MapTask: Starting flush of map output
注意:在執行上面的hadoop命令之前一定要保證/root/hadoop/目錄下沒有output文件夾,否則將不會運行成功,會提示:
Exception in thread "main" org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory output already exists

這是hadoop內置的保護措施,爲了防止數據覆蓋而丟失,想一想,一個花了幾個小時運行得到的結果被意外的覆蓋肯定是非常可怕的事情。

看一看/root/hadoop/目錄下發生了什麼變化,是不是多了一個output文件夾,裏面有個名爲part-r-00000的文件,文件裏面的內容就是我們通過hadoop計算得到的結果。

4.搭建hadoop的eclipse開發環境

前面是通過命令行來編輯和運行,當然這個是基本功,但是這個確實比較麻煩。所以,如果能像普通java程序一樣通過eclipse點擊運行,結果就刷刷刷的出來,那確實是比較爽的事情啊,呵呵。所以,我就網上找了點資料,弄了弄,不弄不知道,弄了才知道,原來和其他許多的eclipse功能一樣,只要添加個插件就可以,感謝那些無償開發這些插件的人們,主會保佑你們的,呵呵。

前面我們已經下載了hadoop的源碼包,ok,插件就在源碼包裏面,contrib/eclipse-pluginhadoop-0.20.2-eclipse-plugin.jar,這就是我們想要的,將這個插件拷貝到eclipse的/plugins文件夾下,重啓eclipse。

然後到‘Windows’ -> ‘Preference’ -> 'Hadoop Map/Reduce',配置Hadoop Installation Directory,這裏是/root/hadoop/hadoop-0.20.2。好了,現在,我們可以通過eclipse來開發了,新建—>項目,發現了什麼:

可以直接新建Map/Reduce工程了,這不就是我們想要的嗎,ok,把上面的例子再跑一遍吧,和普通的java項目一樣就行了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章