1 运行环境说明
1.1 硬软件环境
1.2 机器网络环境
2 :安装Eclipse并测试
2.1 内容
2.2 实现过程
2.2.1
2.2.2
2.2.3
2.2.4
2.2.5
2.2.6
2.2.7
2.2.8
2.2.9
2.2.10编写代码
2.2.11设置运行参数
2.2.12运行并查看结果
3 :传递参数问题
3.1 内容
3.2 程序代码
3.2.1
3.3 实现过程
3.3.1 编写代码
3.3.2 准备数据
3.3.3 配置运行参数
3.3.4 运行作业
4 :Setup函数的作用
4.1 内容
运行环境说明
1.1 硬软件环境
线程,主频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 机器网络环境
个namenode、2个datanode,其中节点之间可以相互ping通。节点IP地址和主机名分布如下:
序号 |
IP地址 |
机器名 |
类型 |
用户名 |
运行进程 |
10.88.147.221 |
hadoop1 |
名称节点 |
hadoop |
NN、SNN、JobTracer |
|
10.88.147.222 |
hadoop2 |
数据节点 |
hadoop |
DN、TaskTracer |
|
10.88.147.223 |
hadoop3 |
数据节点 |
hadoop |
DN、TaskTracer |
所有节点均是CentOS6.5 64bit系统,防火墙均禁用,所有节点上均创建了一个hadoop用户,用户主目录是/usr/hadoop。所有节点上均创建了一个目录/usr/local/hadoop,并且拥有者是hadoop用户。
书面作业1:安装Eclipse并测试
内容
在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文件,可以看到运行结果:
书面作业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准备数据
、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插件工具查看结果,下图显示在每行加入了传入参数:
书面作业3:Setup函数的作用
内容
(选作)阅读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之后运行。