1 運行環境說明
1.1 硬軟件環境
1.2 機器網絡環境
2 書面作業1:安裝Eclipse並測試
2.1 書面作業1內容
2.2 實現過程
2.2.1 下載Eclipse
2.2.2 解壓elipse
2.2.3 啟動eclipse
2.2.4 加載eclipse插件
2.2.5 打開MapReduce視圖
2.2.6 啟動hadoop
2.2.7 新建 Hadoop Location
2.2.8 使用elipse上傳測試數據
2.2.9 創建MapReduce項目
2.2.10編寫代碼
2.2.11設置運行參數
2.2.12運行並查看結果
3 書面作業2:傳遞參數問題
3.1 書面作業2內容
3.2 程序代碼
3.2.1 Test_2_Adjust.java
3.3 實現過程
3.3.1 編寫代碼
3.3.2 准備數據
3.3.3 配置運行參數
3.3.4 運行作業
4 書面作業3:Setup函數的作用
4.1 書面作業3內容
4.2 回答
1運行環境說明
1.1 硬軟件環境
l 主機操作系統:Windows 64 bit,雙核4線程,主頻2.2G,6G內存
l 虛擬軟件:VMware® Workstation 9.0.0 build-812388
l 虛擬機操作系統:CentOS 64位,單核,1G內存
l JDK:1.7.0_55 64 bit
l Hadoop:1.1.2
1.2 機器網絡環境
集群包含三個節點:1個namenode、2個datanode,其中節點之間可以相互ping通。節點IP地址和主機名分布如下:
序號 |
機器名 |
類型 |
用戶名 |
運行進程 |
|
1 |
10.88.147.221 |
hadoop1 |
名稱節點 |
hadoop |
NN、SNN、JobTracer |
2 |
10.88.147.222 |
hadoop2 |
數據節點 |
hadoop |
DN、TaskTracer |
3 |
10.88.147.223 |
hadoop3 |
數據節點 |
hadoop |
DN、TaskTracer |
所有節點均是CentOS6.5 64bit系統,防火牆均禁用,所有節點上均創建了一個hadoop用戶,用戶主目錄是/usr/hadoop。所有節點上均創建了一個目錄/usr/local/hadoop,並且擁有者是hadoop用戶。
2書面作業1:安裝Eclipse並測試
2.1 書面作業1內容
在linux或win下安裝eclipse,並且連接到Hadoop集群(關鍵步驟是編譯插件),運行上周課里的求最高溫度的map-reduce程序作為測試,抓圖整個過程
2.2 實現過程
2.2.1下載Eclipse
可以以多種方式下載Eclipse,下面介紹直接從eplise官網下載和從中國鏡像站點下載,下載把eclipse上傳到Hadoop環境中。
第一種方式從elipse官網下載:
http://www.eclipse.org/downloads/?osType=linux
我們運行的環境為CentOS 64位系統,需要選擇eclipse類型為linux,然后點擊linux 64bit鏈接下載
會根據用戶所在地,推薦最佳的下載地址
在該頁面的下部分也可以根據自己的情況選擇合適的鏡像站點進行下載
第二種方式從鏡像站點直接下載elipse:
http://mirror.bit.edu.cn/eclipse/technology/epp/downloads/release/luna/R/
在鏡像站點選擇 eclipse-jee-luna-R-linux-gtk-x86_64.tar.gz進行下載
(http://mirror.bit.edu.cn/eclipse/technology/epp/downloads/release/luna/R/eclipse-jee-luna-R-linux-gtk-x86_64.tar.gz)
2.2.2解壓elipse
在/home/hadoop/Downloads/目錄中,使用如下命令解壓elipse並移動到/usr/local目錄下:
cd /home/hadoop/Downloads
tar -zxvf eclipse-jee-luna-SR1-linux-gtk-x86_64.tar.gz
sudo mv eclipse /usr/local/
cd /usr/local
ls
2.2.3啟動eclipse
登錄到虛擬機桌面,進入/usr/local/eclipse目錄,通過如下命令啟動eclipse:
cd /usr/local/eclipse
./eclipse
為了方便操作,可以在虛擬機的桌面上建立elipse的快捷操作
2.2.4加載eclipse插件
將hadoop-eclipse-plugin-1.1.2.jar拷貝到 eclipse的plugins目錄:
cd /home/hadoop/Downloads
mv hadoop-eclipse-plugin-1.1.2.jar /usr/local/eclipse/plugins
cd /usr/local/eclipse/plugins
ll hadoop-eclipse-plugin-1.1.2.jar
啟動eclipse,打開窗口 window-->preferences ,配置Hadoop MapReduce的安裝路徑,在實驗環境為/usr/local/hadoop-1.1.2,如下圖所示:
2.2.5打開MapReduce視圖
點擊eclipse菜單Window-->Show View-->Other 窗口,選擇 MapReducer Locations,如下圖所示:
添加完畢后在視圖區域中出現MapReduce視圖,同時在視圖區域右上方出現藍色小象的添加按鈕,如下圖所示
2.2.6啟動hadoop
使用如下命令啟動Hadoop:
cd /usr/local/hadoop-1.1.2/bin
start-all.sh
2.2.7新建 Hadoop Location
點擊藍色小象新增按鈕,提示輸入MapReduce和HDFS Master相關信息,其中:
l Lacation Name:為該位置命名,能夠識別該;
l MapReduce Master:與$HADOOP_DIRCONF/mapred-site.xml配置保持一致;
l HDFS Master:與$HADOOP_DIRCONF/core-site.xml配置保持一致
l User Name:登錄hadoop用戶名,可以隨意填寫
2.2.8使用elipse上傳測試數據
配置完畢后,在eclipse的左側DFS Locations出現CentOS HDFS的目錄樹,該目錄為HDFS文件系統中的目錄信息:
為運行求最高溫度MapReduce,通過eclipse上傳測試數據,可以在DFS Locations相對應目錄點擊右鍵,選擇Upload file to DFS出現選擇文件界面,如下圖所示:
可以看到MaxTemperatureData.txt已經成功上傳到HDFS文件系統中
2.2.9創建MapReduce項目
安裝插件之后,可以在New Project頁面建立Map/Reduce Project:
需要注意的是填寫完項目名稱Rock后,需要指定Hadoop MapReduce運行包的路徑,填寫完畢后點擊完成即可
2.2.10 編寫代碼
在Rock項目中創建/src/chapter06包,在該包下創建上一周求每年最大溫度的代碼,分別為MaxTemperature.java、MaxTemperatureMapper.java和MaxTemperatureReducer.java
2.2.11 設置運行參數
打開MaxTemperature.java,點擊Run-Run Configurations設置運行參數,需要在Arguments頁簽填寫MaxTemperature運行的輸入路徑和輸出路徑參數,需要注意的是輸入、輸出路徑參數路徑需要全路徑,否則運行會報錯:
l 輸入:運行數據路徑,這里為hdfs://hadoop1:9000/usr/hadoop/in/MaxTemperatureData.txt
l 輸出:運行結果路徑,這里為hdfs://hadoop1:9000/usr/hadoop/out_ch6_eplipse
2.2.12 運行並查看結果
設置運行參數完畢后,點擊運行按鈕:
運行成功后,刷新CentOS HDFS中的輸出路徑out_ch6_eclipse目錄,打開part-r-00000文件,可以看到運行結果:
3 書面作業2:傳遞參數問題
3.1 書面作業2內容
(選作)請閱讀Exercise_1.java,編譯並且運行。該程序從Test_1改編而來,其主要差別在於能夠讓用戶在結果文件中的每一行前面添加一個用戶自定義的字符串,而這個字符串將由參數傳遞到程序中。例如,運行 $hadoop jar Exercise_1.jar input_path output_path hadoop 之后,第三個參數“hadoop”將會在結果文件中顯示,例如附件“result_1”所顯示的。
問題:着重考慮Exercise_1.java里面”需要注意的部分“,改寫Test_2程序,得到的結果必須跟附件"resule_2"一致,並且其中hadoop必須由參數傳遞。
3.2 程序代碼
3.2.1Test_2_Adjust.java
注意:紅色字體為與Test_2.java不同之處
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
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;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
/**
* 有Reducer版本
*/
publicclass Test_2_Adjust extends Configured implements Tool {
/**
* 計數器用於計數各種異常數據
*/
enum Counter {
LINESKIP, // 出錯的行
}
/**
* MAP任務
*/
publicstaticclass Map extends Mapper<LongWritable, Text, Text, Text> {
publicvoid map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString(); // 讀取源數據
try {
// 數據處理
String[] lineSplit = line.split(" ");
String anum = lineSplit[0];
String bnum = lineSplit[1];
String name = context.getConfiguration().get("name");
context.write(new Text(bnum + "," + name), new Text(anum)); // 輸出
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
context.getCounter(Counter.LINESKIP).increment(1); // 出錯令計數器+1
return;
}
}
}
/**
* REDUCE任務
*/
publicstaticclass Reduce extends Reducer<Text, Text, Text, Text> {
publicvoid reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
String valueString;
String out = "";
for (Text value : values) {
valueString = value.toString();
out += valueString + "|";
}
String[] keySplit = key.toString().split(",");
context.write(new Text(keySplit[0]), new Text(out + keySplit[1]));
}
}
@Override
publicint run(String[] args) throws Exception {
Configuration conf = getConf();
/** 獲取傳入的hadoop字符 **/
conf.set("name", args[2]);
Job job = new Job(conf, "Test_2_Adjust"); // 任務名
job.setJarByClass(Test_2_Adjust.class); // 指定Class
FileInputFormat.addInputPath(job, new Path(args[0])); // 輸入路徑
FileOutputFormat.setOutputPath(job, new Path(args[1])); // 輸出路徑
job.setMapperClass(Map.class); // 調用上面Map類作為Map任務代碼
job.setReducerClass(Reduce.class); // 調用上面Reduce類作為Reduce任務代碼
job.setOutputFormatClass(TextOutputFormat.class);
job.setOutputKeyClass(Text.class); // 指定輸出的KEY的格式
job.setOutputValueClass(Text.class); // 指定輸出的VALUE的格式
job.waitForCompletion(true);
// 輸出任務完成情況
System.out.println("任務名稱:" + job.getJobName());
System.out.println("任務成功:" + (job.isSuccessful() ? "是" : "否"));
System.out.println("輸入行數:" + job.getCounters().findCounter("org.apache.hadoop.mapred.Task$Counter","MAP_INPUT_RECORDS").getValue());
System.out.println("輸出行數:" + job.getCounters().findCounter("org.apache.hadoop.mapred.Task$Counter", "MAP_OUTPUT_RECORDS").getValue());
System.out.println("跳過的行:" + job.getCounters().findCounter(Counter.LINESKIP).getValue());
return job.isSuccessful() ? 0 : 1;
}
/**
* 設置系統說明設置MapReduce任務
*/
publicstaticvoid main(String[] args) throws Exception {
// 判斷參數個數是否正確
// 如果無參數運行則顯示以作程序說明
if (args.length != 3) {
System.err.println("");
System.err.println("Usage: Test_2_Adjust < input path > < output path > < name >");
System.err.println("Example: hadoop jar ~/Test_2_Adjust.jar hdfs://localhost:9000/usr/hadoop/Test_2_Data.txt hdfs://localhost:9000/usr/hadoop/out_ch6_test2_adjust");
System.err.println("Counter:");
System.err.println("\t" + "LINESKIP" + "\t"+ "Lines which are too short");
System.exit(-1);
}
// 記錄開始時間
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date start = new Date();
// 運行任務
int res = ToolRunner.run(new Configuration(), new Test_2_Adjust(), args);
// 輸出任務耗時
Date end = new Date();
float time = (float) ((end.getTime() - start.getTime()) / 60000.0);
System.out.println("任務開始:" + formatter.format(start));
System.out.println("任務結束:" + formatter.format(end));
System.out.println("任務耗時:" + String.valueOf(time) + " 分鍾");
System.exit(res);
}
}
3.3 實現過程
3.3.1編寫代碼
打開eclipse,在Rock項目src/chapter6包下新建Test_2_Adjust.java:
3.3.2准備數據
使用SSH工具(參見第1、2周2.1.3.1Linux文件傳輸工具所描述)把提供的測試數據Test_2_Data.txt上傳到本地目錄/usr/local/hadoop-1.1.2/input中,然后使用eclipse的HDFS插件工具上傳該文件到/usr/hadoop/in目錄中,如下圖所示:
3.3.3配置運行參數
新建一個Java應用運行程序,需要在Arguments頁簽填寫Test_2_Adjust運行的輸入路徑、輸出路徑和輸入字符三個參數,需要注意的是輸入、輸出路徑參數路徑需要全路徑,否則運行會報錯:
l 輸入:運行數據路徑,這里為hdfs://hadoop1:9000/usr/hadoop/in/Test_2_Data.txt
l 輸出:運行結果路徑,這里為hdfs://hadoop1:9000/usr/hadoop/out_ch6_test2_adjust
l 輸入字符:為“hadoop”字符
3.3.4運行作業
配置完畢后,執行MapReduce作業,執行成功到eclipse的HDFS插件工具查看結果,下圖顯示在每行加入了傳入參數:
4 書面作業3:Setup函數的作用
4.1 書面作業3內容
(選作)閱讀Exercise_2.java,這是一個與Exercise_1.java有相同效果的程序,自行搜索關於setup函數的資料,回答上述兩個程序的不同。
4.2 回答
不同之處是:Exercise2中的name寫成了reduce的成員變量,而且該變量在setup方法進行初始化。從第二題代碼運行的console可以看出,不管運行多少次map和reduce方法,setup都只運行一次。setup方法是繼承於父類,在Mapper類和Reducer類中都有setup,Mapper的setup方法會在map之前運行,Reducer的setup方法會在reduce之前運行。同樣的Mapper類和Reducer類還有對應的cleanup方法,在整個過程中也只運行一次。而且Mapper的cleanup方法會在map之后運行,Reducer的cleanup方法會在reduce之后運行。