实验三—MapReduce实验报告

实验三—MapReduce实验报告

一、实验目的
1.通过实验掌握基本的MapReduce安装,连接,开启,编程方法;
2.掌握用MapReduce解决一些常见的数据处理问题,包括数据去重、数据排序和数据挖掘等。
二、实验平台
已经配置完成的Hadoop伪分布式环境。
三、实验步骤
 首先要先了解一下HDFS中的常用的命令
-mkdir        在HDFS创建目录    hdfs dfs -mkdir /data
-ls         查看当前目录      hdfs dfs -ls /
-ls -R        查看目录与子目录
-put         上传一个文件      hdfs dfs -put data.txt /data/input
-moveFromLocal    上传一个文件,会删除本地文件:ctrl + X
-copyFromLocal    上传一个文件,与put一样
-copyToLocal     下载文件  hdfs dfs -copyToLocal /data/input/data.txt
-get         下载文件  hdfs dfs -get /data/input/data.txt
-rm         删除文件  hdfs dfs -rm /data/input/data.txt -getmerge      将目录所有的文件先合并,再下载
-cp 拷 hdfs dfs -cp /data/input/data.txt  /data/input/data01.txt
-mv         移动: hdfs dfs -mv /data/input/data.txt  /data/input/data02.txt
-count            统计目录下的文件个数
-text、-cat       查看文件的内容  hdfs dfs -cat /data/input/data.txt
-balancer         平衡操作
然后在hadoop目录下创建一个文件夹,我的是/usr/local/hadoop/myapp,用于存放打包好的java jar文件
先在在hadoop的用户登录用户下建立一个HDFS用户目录
cd /usr/local/hadoop
./bin/hdfs dfs –mkdir –p /user/hadoop
在新建的目录下创建一个input目录,用于存放hadoop运行时需要输入的文件
./bin/hdfs dfs –mkdir /input
在创建一个output目录用于存放hadoop运行输出的文件
/bin/hdfs dfs –mkdir /output
在登录时的文件夹下创建一个data.txt,是本实验输入的文件
用命令./bin/hdfs dfs -put /home/hadoop/myLocalFile.txt  input存放到刚才创建的input目录下,当然也可以不这样做
用./bin/hdfs dfs –ls input查看是否上传成功
接下来就编译代码文件
WordCountMapper.java
import java.io.IOException;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

public class WordCountMapper extends Mapper<LongWritable, Text, Text, LongWritable> {
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
/*
* key: 输入的key
* value: 数据 I love Beijing
* context: Map上下文
*/
String data= value.toString();
//分词
String[] words = data.split(" ");

	//输出每个单词
	for(String w:words){
		context.write(new Text(w), new LongWritable(1));
	}
}

}

WordCountReducer.java
import java.io.IOException;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class WordCountReducer extends Reducer<Text, LongWritable, Text, LongWritable>{

@Override
protected void reduce(Text k3, Iterable<LongWritable> v3,Context context) throws IOException, InterruptedException {
	//v3: 是一个集合,每个元素就是v2
	long total = 0;
	for(LongWritable l:v3){
		total = total + l.get();
	}
	
	//输出
	context.write(k3, new LongWritable(total));
}

}

WordCountMain.java

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCountMain {

public static void main(String[] args) throws Exception {
	//创建一个job = map + reduce
	Configuration conf = new Configuration();
	
	//创建一个Job
	Job job = Job.getInstance(conf);
	//指定任务的入口
	job.setJarByClass(WordCountMain.class);
	
	//指定job的mapper
	job.setMapperClass(WordCountMapper.class);
	job.setMapOutputKeyClass(Text.class);
	job.setMapOutputValueClass(LongWritable.class);
	
	//指定job的reducer
	job.setReducerClass(WordCountReducer.class);
	job.setOutputKeyClass(Text.class);
	job.setOutputValueClass(LongWritable.class);
	
	//指定任务的输入和输出
	FileInputFormat.setInputPaths(job, new Path(args[0]));
	FileOutputFormat.setOutputPath(job, new Path(args[1]));		
	
	//提交任务
	job.waitForCompletion(true);
}

}

可以先运行一下wordCountMain.java,看看有没有错误
这里有错误是因为没有输入文件
点击WordCount工程,选择Export…
选在java->JAR file->next
JAR file:为我的创建的myapp文件,命名为WordCount.jar,点击next。
接着点击next。

Main class:点击Browse…
选择本工程的主类所在文件,几点ok。
到myapp文件夹下看有没有打包成功,WordCount.jar就是对应的打包文件。
输入hadoop jar ./myapp/WordCount.jar …/hadoop/input/data.txt …/hadoop/output/wc
命令含义为执行文件夹myapp下的WordCount.jar 输入文件为…/hadoop/input/data.txt 文件输出到…/hadoop/output/wc,wc文件夹会在执行命令的时候自动创建。
看到上图就说明运行成功了,可输入./bin/hdfs dfs -ls output/wc看一下输出文件
可以看到生成了_ SUCCESS文件和part-r-00000文件,查看part-r-00000文件
看到结果了,说明确实是运行成功了
四、实验过程中遇到的问题及其解决办法

1.访问HDFS无权限
报错内容一般如下:
org.apache.hadoop.security.AccessControlException: Permission denied: user=root, access=WRITE, inode="":nutch:supergroup:rwxr-xr-x
报错原因:主要是由于HDFS的文件系统都是有用户和权限的,如果当前用户无权限则在使用该文件或文件夹的时候会报错。
解决方案:

  • 使用hdfs dfs -chmod 命令来修改相关文件或文件夹权限;
    * 如果在测试环境,用户不想这么麻烦来修改权限的话,也可使用配置来禁用hdfs的权限管理,可以在hdfs-site.xml中配置以下内容

    dfs.permissions
    false

    2.运行过程中,无报错无日志,在http://hadoop:8088 界面中也无任务进度
    在运行的过程中,比较烦恼的一件事就是,运行的时候没有任何报错,任务调度界面中也没有任务显示
    将项目打成jar包放入Linux环境下,也是可以运行的,很奇怪。
    后来,就添加了log4j.properties文件,将root设置为DEBUG级别(内容如上所示),就看到了其中的报错。
    所以,我们在运行项目的时候,一定要添加日志文件
    3.创建对ResourceManager连接的时候报错
    DEBUG [org.apache.hadoop.ipc.Client] - closing ipc connection to 0.0.0.0/0.0.0.0:8032: Connection refused: no further information
    java.net.ConnectException: Connection refused: no further information
        报错原因:看报错信息,我们知道是在创建对0.0.0.0:8032的Connection时候失败。为什么会失败?应该是无法连接到0.0.0.0这个IP。我们没有在配置文件中配置这个IP和端口,那么这个应该是默认配置。我们去hadoop官网的core-default.xml、yarn-default.xml等默认配置文件进行查看的时候,发现在yarn-site.xml中发现以下内容
    yarn.resourcemanager.hostname 0.0.0.0 The hostname of the RM.
    yarn.resourcemanager.address ${yarn.resourcemanager.hostname}:8032
    那么可以确定这个IP:port是对ResourceManager的连接失败
    我们知道ResourceManager负责集群的资源分配,所有NodeManager都需要与ResourceManager进行通信交换信息,yarn.resourcemanager.hostname默认为0.0.0.0,我们将这个内容修改为hadoop,对应着当前本机地址即可

解决方案:在yarn-site.xml中添加

yarn.resourcemanager.hostname hadoop 4.no job control 报错信息如下所示: Exception message: /bin/bash: line 0: fg: no job control Stack trace: ExitCodeException exitCode=1: /bin/bash: line 0: fg: no job control at org.apache.hadoop.util.Shell.runCommand(Shell.java:545) at org.apache.hadoop.util.Shell.run(Shell.java:456) ... 报错原因:由于我们使用Windows平台进行开发并添加MR任务,而hadoop部署在Linux平台上,故针对跨平台的job会报该错 解决方案:在mapred-site.xml中添加以下配置 设置为job提交允许跨平台 mapreduce.app-submission.cross-platform true 5.ClassNotFoundException

Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class hadoop.mr.WordCount$WCMapper not found
at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2195)
at org.apache.hadoop.mapreduce.task.JobContextImpl.getMapperClass(JobContextImpl.java:186)

     报错原因:这个还是比较难解释的,需要对hadoop的运行原理有一定的了解。具体可参考这篇文章 https://blog.csdn.net/qq_19648191/article/details/56684268 
解决方案:在core-site.xml中设置如下配置:

mapred.jar C:/Users/lucky/Desktop/wc.jar     然后每次运行WordCount任务的时候,先将当前项目导出为一个jar包,命名为wc.jar,然后位置也要与我们配置的位置一致,这样再运行的时候就不会报错了 运行过程中遇到的问题: 6.问题:找不到主类的异 原因:没有指明主类,所以会出现找不到主类的异常。 解决方法: (1)在打包程序时,选择相应的主类,这样的话,这边即可以不用写主类,即使用上面的命令即可运行程序。 (2)如果在打包时没有指定主类,则需要在运行程序时指明主类(MRJoin.MRJoin),这样就不会出现找不到主类的异常了。 7.问题:发现出现输出文件路径存在的错误(上图箭头所指) 解决方法:删除输出路径,继续运行。 删除输出路径: [root@master ~]# hdfs dfs -rm -r /usr/MRJoin/out 或者使用 [root@master ~]# hadoop fs -rm -r -skipTrash /data/m2_3.txt也可以。 8.问题原因:在运行时出现了上述的版本不支持的问题,可以看出是由于java环境问题造成的,即为jdk版本不一致。 解决方法:修改项目的jdk版本: 9.还遇到过一种就是输入文件的路径错误的问题,这个需要查看代码有没有设置固定的路径,有的话改为自己想要设置的路径;其次如果代码中没有特别设定,则可能是输入时出错了,认真查看原因即可。 错误一: Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class wordCount.wordCount$Map not found at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2074) at org.apache.hadoop.mapreduce.task.JobContextImpl.getMapperClass(JobContextImpl.java:186) at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:742) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341) at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:163) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:415) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1628) at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158) Caused by: java.lang.ClassNotFoundException: Class wordCount.wordCount$Map not found at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:1980) at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2072) ... 8 more 问题分析:很烦人的一个问题,很久之前就碰见过,后来电脑linux换了一个版本,解决了 解决办法:eclipse添加hadoop配置文件问题,记住只需要在程序目录下新建一个conf的文件夹,把log4j.properties拷贝到该目录下,重启eclipse即可 错误二: eclipse 运行MR提示无法访问的情况 问题分析:权限不足

解决办法:重新给hdfs文件系统赋予权限(可能会经常遇到这种问题,可执行同一种操作即可)bin/hdfs dfs -chmod -R 777 /

错误三:

HMaster启动之后立即又关闭

问题分析:可能是zookeeper不稳定造成的,

解决办法:停止zookeeper服务(bin/zkServer.sh stop zoo1.cfg     bin/zkServer.sh stop zoo2.cfg    bin/zkServer.sh stop zoo3.cfg ),再重新启动

错误四:

15/08/23 11:10:07 INFO mapreduce.JobSubmitter: Cleaning up the staging area file:/usr/local/hadoop/tmp/mapred/staging/thinkgamer1735608800/.staging/job_local1735608800_0001
Exception in thread “main” ExitCodeException exitCode=1: chmod: 无法访问"/usr/local/hadoop/tmp/mapred/staging/thinkgamer1735608800/.staging/job_local1735608800_0001": 没有那个文件或目录

问题分析:eclipse的配置文件缺少

解决办法:把配置hadoop时所修改的配置文件全部复制到src文件夹下

错误五:

Exception in thread “main” org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://localhost:9000/thinkgamer/output already exists

问题分析:hdfs文件系统中的output文件夹已经存在

解决办法:删除即可(同时还可能出现找不到input目录的问题,此时注意检查input路径)

五、实验总结
通过本次实验,使我掌握基本的MapReduce编程方法;掌握用MapReduce解决一些常见的数据处理问题,包括数据去重、数据排序和数据挖掘等。短暂的大数据课程实验到此结束,但我知道对大数据的学习是没有尽头的。学习就是一个不断积累的过程,学到东西,或多或少,以另一种方式将它记录下来。
总结了一下排除上述问题的一个自己的心得:
感觉MapReduce任务离线调试真的坑比较多,很难定位到问题的所在,出现上述类问题主要有以下几点:1、集群环境处于不稳定状态;2、自己代码问题,可能是很小的一个细节;3、mapreduce任务配置参数的问题。
总之,遇到问题,不要怕麻烦,从程序的源头开始一步步排查,在排查的过程中不断总结,你的能力也就一步步在此过程中会慢慢提升。其实大多数人遇到问题最怕没有思路,不知道从哪里下手,这样会耗费大量时间。遇到问题能有个自己的思路是关键,我们首先得明白有哪些可能会导致出现这些问题,然后开始排查,这样处理问题才能有条不紊的进行下去,也是一种解决问题的比较好的方式。(踩得坑多了,路自然就平了,欢迎丢砖块)
越努力,越幸运,自己加油,陌生人,加油!!

  • 11
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值