centos7安装hadoop,配置eclipse和hdfs文件系统接口-运行案例测试
之前已经写了三篇博客,这一篇是最后的一步,也是最重要的一步,今天来讲一下eclipse 对接hadoop
在看这篇博客之前请先阅读之前三篇博客
这里hadoop,eclipse,jdk都已经安装好
- 安装 Hadoop-Eclipse-Plugin
首先我们需要下载 Hadoop-Eclipse-Plugin,这里可以去官网下载,下载 Github 上的 https://github.com/winghc/hadoop2x-eclipse-plugin(备用下载地址:http://pan.baidu.com/s/1i4ikIoP)。这个我也是在本地下载后,拷贝到虚拟机的下载目录的。
百度网盘下载应该会快一点
下载之后我们将文件解压
这里下载的地址为/opt
cd /opt
unzip hadoop2x-eclipse-plugin-master.zip
#之后就会解压完成
然后我们需要将hadoop-eclipse-kepler-plugin-2.6.0夹中的 release 中的 hadoop-eclipse-kepler-plugin-2.6.0.jar (还提供了 2.2.0 和 2.4.1 版本)复制到 Eclipse 安装目录的 plugins 文件夹中
我的eclipse 也安装在/opt 中
cp /opt/hadoop-eclipse-kepler-plugin-2.6.0/release/hadoop-eclipse-kepler-plugin-2.6.0.jar /opt/eclipse/plugins
此时我们则完成安装
- 配置hadoop-eclipse-kepler-plugin-2.6.0
现在启动eclipse 必须在 /opt/eclipse/eclipse 路径下启动,所以请大家仔细看清楚路径
注意只能在该路径下启动才可配置环境
并且事先必须启动hadoop
cd /hadoop/hadoop-2.6.0
sbin/start-all.sh
#启动hadoop
cd /opt/eclipse/eclipse
./eclipse -clean
#则启动
之后我们开始配置环境
按下面图片选中window -> preferences
此时会弹出一个窗体,窗体的左侧会多出 Hadoop Map/Reduce 选项,点击此选项,选择 Hadoop 的安装目录
注:填写自己hadoop的安装目录,上述目录不可随意填,我的是、hadoop/hadoop-2.6.0,所以我填的这个
第二步:切换 Map/Reduce 开发视图,选择 Window 菜单下选择 Open Perspective -> Other(CentOS 是 Window -> Perspective -> Open Perspective -> Other),弹出一个窗体,从中选择 Map/Reduce 选项即可进行切换。
之后应该可以看到界面的变化出现如下标志
第三步:建立与 Hadoop 集群的连接,点击 Eclipse软件右下角的 Map/Reduce Locations 面板,在面板中单击右键,选择 New Hadoop Location,(那个蓝色小象)
在弹出来的 General 选项面板中,General 的设置要与 Hadoop 的配置一致。这里DFS Master要跟配置文件的一致,比如我的设置 fs.defaultFS 为 hdfs://lsn-linux:9000,则 DFS Master 的 Port 要改为 9000。Map/Reduce(V2) Master 的 Port 用默认的即可,Location Name 随意填写。
当然也可以直接用本机ip地址那样更好,lsn-linux映射的其实就是本机ip地址
配置好后,点击左侧 Project Explorer 中的 MapReduce Location (点击三角形展开)就能直接查看 HDFS 中的文件列表了(HDFS 中要有文件,如下图是 WordCount 的输出结果),双击可以查看内容,右键点击可以上传、下载、删除 HDFS 中的文件,无需再通过繁琐的 hdfs dfs -ls 等命令进行操作了。
现在我们新建一个项目
填写 Project name 为 WordCount 即可,点击 Finish 就创建好了项目。
此时在左侧的 Project Explorer 就能看到刚才建立的项目了。
之后我们新建一个包,病建一个项目
如上图所示
3. 将hadoop的一些配置文件放到src下 并配置hadoop调试指令
开启 hadoop调试信息,防止hadoop出现进制问题
vim /etc/profile
加入如下代码:
export HADOOP_ROOT_LOGGER=DEBUG,console
传输文件
/root/eclipse-workspace 是我的工作路径
执行下面指令,为了覆盖eclipse的默认一些参数,所以才需要上传下面的文件
cp /hadoop/hadoop-2.6.0/etc/hadoop/core-site.xml /root/eclipse-workspace/WordCount/src
cp /hadoop/hadoop-2.6.0/etc/hadoop/hdfs-site.xml /root/eclipse-workspace/WordCount/src
cp /hadoop/hadoop-2.6.0/etc/hadoop/log4j.properties /root/eclipse-workspace/WordCount/src
- 测试
下面代码拷入WordCount类文件
package org.apache.hadoop.examples;
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class WordCount {
public static class TokenizerMapper extends
Mapper<Object, Text, Text, IntWritable>
//这个Mapper类是一个泛型类型,它有四个形参类型,分别指定map函数的输入键、输入值、输出键、输出值的类型。hadoop没有直接使用Java内嵌的类型,而是自己开发了一套可以优化网络序列化传输的基本类型。这些类型都在org.apache.hadoop.io包中。
//比如这个例子中的Object类型,适用于字段需要使用多种类型的时候,Text类型相当于Java中的String类型,IntWritable类型相当于Java中的Integer类型
{
//定义两个变量
//private final static LongWritable one=new LongWritable(1);
private final static IntWritable one = new IntWritable(1);//这个1表示每个单词出现一次,map的输出value就是1.
private Text word = new Text();//每行数据
//实现map函数
public void map(Object key, Text value, Context context)
//context它是mapper的一个内部类,简单的说顶级接口是为了在map或是reduce任务中跟踪task的状态,很自然的MapContext就是记录了map执行的上下文,在mapper类中,这个context可以存储一些job conf的信息,比如job运行时参数等,我们可以在map函数中处理这个信息,这也是Hadoop中参数传递中一个很经典的例子,同时context作为了map和reduce执行中各个函数的一个桥梁,这个设计和Java web中的session对象、application对象很相似
//简单的说context对象保存了作业运行的上下文信息,比如:作业配置信息、InputSplit信息、任务ID等
//我们这里最直观的就是主要用到context的write方法。
throws IOException, InterruptedException {
//The tokenizer uses the default delimiter set, which is " \t\n\r": the space character, the tab character, the newline character, the carriage-return character
String line= value.toString(); // 将输入的纯文本文件的数据转化成String
// 将输入的数据首先按行进行分割
StringTokenizer itr = new StringTokenizer(line);//将Text类型的value转化成字符串类型
//StringTokenizer是字符串分隔解析类型,StringTokenizer 用来分割字符串,你可以指定分隔符,比如',',或者空格之类的字符。
while (itr.hasMoreTokens()) {//hasMoreTokens() 方法是用来测试是否有此标记生成器的字符串可用更多的标记。
//java.util.StringTokenizer.hasMoreTokens()
word.set(itr.nextToken());//nextToken()这是 StringTokenizer 类下的一个方法,nextToken() 用于返回下一个匹配的字段。
context.write(word, one);
}
}
}
public static class IntSumReducer extends
Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
//实现reduce函数
public void reduce(Text key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
//Configuration类代表作业的配置,该类会加载mapred-site.xml、hdfs-site.xml、core-site.xml等配置文件。
//删除已经存在的输出目录
Path mypath = new Path("hdfs://lsn-linux:9000/usr/root");//输出路径
FileSystem hdfs = mypath.getFileSystem(conf);//获取文件系统
//如果文件系统中存在这个输出路径,则删除掉,保证输出目录不能提前存在。
if (hdfs.isDirectory(mypath)) {
hdfs.delete(mypath, true);
}
//job对象指定了作业执行规范,可以用它来控制整个作业的运行。
Job job = Job.getInstance();// new Job(conf, "word count");
job.setJarByClass(WordCount.class);//我们在hadoop集群上运行作业的时候,要把代码打包成一个jar文件,然后把这个文件
//传到集群上,然后通过命令来执行这个作业,但是命令中不必指定JAR文件的名称,在这条命令中通过job对象的setJarByClass()
//中传递一个主类就行,hadoop会通过这个主类来查找包含它的JAR文件。
job.setMapperClass(TokenizerMapper.class);
//job.setReducerClass(IntSumReducer.class);
job.setCombinerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//一般情况下mapper和reducer的输出的数据类型是一样的,所以我们用上面两条命令就行,如果不一样,我们就可以用下面两条命令单独指定mapper的输出key、value的数据类型
//job.setMapOutputKeyClass(Text.class);
//job.setMapOutputValueClass(IntWritable.class);
//hadoop默认的是TextInputFormat和TextOutputFormat,所以说我们这里可以不用配置。
//job.setInputFormatClass(TextInputFormat.class);
//job.setOutputFormatClass(TextOutputFormat.class);
FileInputFormat.addInputPath(job, new Path(
"hdfs://lsn-linux:9000/wordcount/zz.txt"));//FileInputFormat.addInputPath()指定的这个路径可以是单个文件、一个目录或符合特定文件模式的一系列文件。
//从方法名称可以看出,可以通过多次调用这个方法来实现多路径的输入。
FileOutputFormat.setOutputPath(job, new Path(
"hdfs://lsn-linux:9000/usz"));//只能有一个输出路径,该路径指定的就是reduce函数输出文件的写入目录。
//特别注意:输出目录不能提前存在,否则hadoop会报错并拒绝执行作业,这样做的目的是防止数据丢失,因为长时间运行的作业如果结果被意外覆盖掉,那肯定不是我们想要的
System.exit(job.waitForCompletion(true) ? 0 : 1);
//使用job.waitForCompletion()提交作业并等待执行完成,该方法返回一个boolean值,表示执行成功或者失败,这个布尔值被转换成程序退出代码0或1,该布尔参数还是一个详细标识,所以作业会把进度写到控制台。
//waitForCompletion()提交作业后,每秒会轮询作业的进度,如果发现和上次报告后有改变,就把进度报告到控制台,作业完成后,如果成功就显示作业计数器,如果失败则把导致作业失败的错误输出到控制台
}
}
之后我们需要在hdfs 根目录创建一个文件夹wordcount,并上传一个zz.txt问价
文件内容如下
hadoop
hdfs
hadoop
world
hello
hadoop
hdfs
world
hello
hello
hadoop
hadoop
world
之后我们即可运行程序
你会看到如下结果,则配置成功
那么我们的eclipse则可正常运行了,直接与hdfs 文件系统对接