目录
本文出现的错误及解决方法均为亲身经历,太痛苦了....
在此将错误整理一下,供大家避坑。
首先hadoop的运行方式分为本地运行和集群运行,本机运行及在本机编写程序后直接执行,集群运行则是将程序写完后打包,上传到hdfs中运行。
一 、hadoop本地运行环境的配置。
hadoop的运行需要jdk的安装并配置,本文主要讲hadoop的配置,java环境没有配的请一并配置java环境。
下载hadoop,进入官网选择适合的版本并解压。
我在此放入我的hadoop版本需要的可以提
https://pan.baidu.com/s/1V0-Vo7ruScsKcaMb-gH_5A?pwd=9629
提取码:9629
hadoop解压后还需要在bin目录下放入winutils.exe和hadoop.dll才能保证程序的正常运行。
尽量放入和hadoop版本一样的文件,这是我的版本文件,需要的可以自提。
十亿少年的梦/hadoop - 码云 - 开源中国 (gitee.com)
成功放入后如图
环境变量的配置
输入win+R,输入sysdm.cpl,高级-->环境变量-->添加hadoop的系统环境变量
进去点击Path进入编辑环境变量界面
添加hadoop环境变量
点击CLASSPATH,如图
配置完成后,点击三次确定,打开cmd窗口,输入java -version 和 hadoop -version,如图所示
显示正确的版本信息及说明环境变量配置成功,
错误提示:
如果在此显示失败,则尝试在编辑环境变量的页面将hadoop和java的环境变量放在最上面后,重新尝试。
注意在hadoop的路径和java的路径下不要使用有空格或者中文出现,否则也会报错。
二 程序的编写
打开idea创建maven项目,配置依赖。
pom.xml
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
并在recources下创建log4j.properties文件,写入一下内容
log4j.rootLogger=debug, stdout, R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log
log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=5
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
错误提示:
如果不进行log4j依赖的配置则会出现:
log4j警告之log4j:WARN No appenders could be found for logger(org.apache.ibatis.logging.LogFactory).的错误。
在src-->main-->java下创建WordCount包,并在包下分别创建WordcountMapper.Class、WordCountReducer.Class、WordCountDriver.Class文件,内容如下:
WordCountDriver.Class
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.IntWritable;
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 WordCountDriver {
public static void main(String[] args) throws Exception{
Configuration conf = new Configuration();
//本地运行
conf.set("mapreduce.framework.name","local");
//集群中运行
// conf.set("mapreduce.framework.name","yarn");
Job job = Job.getInstance(conf);
//2:获取jar包信息
job.setJarByClass(WordCountDriver.class);
//3:关联自定义的mapper和reducer
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//4:设置map输出类型数据
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//5:设置最终输出数据类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//本地运行路径
FileInputFormat.setInputPaths(job,new Path("D:/input"));
FileOutputFormat.setOutputPath(job,new Path("D:/input/output"));
//集群运行路径
// FileInputFormat.setInputPaths(job, new Path(args[0]));
// FileOutputFormat.setOutputPath(job,new Path(args[1]));
// 提交job
boolean flag = job.waitForCompletion(true);
//成功后退出
System.exit(flag ? 0 : -1);
}
}
WordCountMapper.Class
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
/**
* description:
* KEYIN: Map任务读数据的key类型,offset,是每行数据起始位置的偏移量,Long
* VALUEIN:Map任务读数据的value类型,其实就是一行行的字符串,String
* Deer Bear River
* KEYOUT: map方法自定义实现输出的key的类型,String
* VALUEOUT: map方法自定义实现输出的value的类型,Integer
*词频统计:相同单词的次数 (Deer,1)
*
* Long,String,String,Integer是Java里面的数据类型
* Hadoop自定义类型:序列化和反序列化
* LongWritable,Text
*
* date: 2021/10/5 12:24 <br>
* author: Neal <br>
* version: 1.0 <br>
*/
public class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// 把value对应的行数据按照指定的分隔符拆开
String[] words = value.toString().split(" ");
// 将每个字符串放入上下文中
for (String word : words) {
context.write(new Text(word),new IntWritable(1));
}
}
}
WordCountReducer.Class
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
import java.util.Iterator;
/**
* description:
* (Deer,1) (Bear,1) (River,1)
*
* map的输出到reduce端,是按照相同的key分发到一个reduce上去执行 可参考上面的图解
*
* reduce1: (Car,1)(Car,1)(Car,1) ==> (Car, <1,1,1>)
* reduce2: (Deer,1)(Deer,1) ==> (Deer, <1,1>)
* reduce3: (River,1)(River,1) ==> (River, <1,1>)
* reduce4: (Beer,1)(Beer,1) ==> (Beer, <1,1>)
*
* Reducer和Mapper中使用到了模板设计模式
* date: 2021/10/5 12:28 <br>
* author: Neal <br>
* version: 1.0 <br>
*/
public class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int count = 0;
Iterator<IntWritable> it = values.iterator();
while(it.hasNext()) {
IntWritable value = it.next();
count += value.get();
}
context.write(new Text(key),new IntWritable(count));
}
}
WordCountDriver.Class文件中有本地运行和集群运行两种方式,首先进行本地运行,注意修改为自己的text.txt路径。
错误提示:
output文件在运行前要保证不存在,否则会出现already exist 错误。
保证input文件夹下有文件,并且路径要写对。
三 运行
本地运行:
三个类写好后,先进行本地运行,控制台出现
则表示运行成功。找到对应的output文件查看运行结果。
错误提示:
程序是没有任何问题的,如果出现错误则说明可能是以上一个步骤没有配置好,请仔细检查。
如果出现运行成功但是,没有output文件,则说明上面的一个步骤没有执行好,检查一下环境变量的配置,不要出现空格和中文,导入的包一定要是下载的依赖里的。
集群运行
在本地成功运行后,保证程序是没有问题的对项目进行打包,进行集群运行。
将WordCountDriver.Class文件下的集群运行的方式和路径的注释放开,将本地运行的方式和路径进行注释。(即只需要修改这两个地方即可)
找到屏幕右边MAVEN--> 生命周期-->package,双击package进行打包。
运行成功后,在控制台的提示信息里找到对应的tar文件。
打开hadoop虚拟机,并开始集群,打开hdfs的web界面。
切换到你的用户hdfs用户下
su hadoop01 //hadoop01 是我的用户名,你的可能不是,请自行修改
错误提示:
一定要先切换用户在创建文件夹,否则将会因为权限问题报错。
Permission denied: user=root, access=EXECUTE, inode="/tmp":hadoop01:supergroup:drwx------
通过xftp或者s输入sudo rz命令将打包好的jar和准备好的text.txt文件文件传到虚拟机上。
创建在hdfs上创建input目录,将text.txt文件上传到input目录下。可以通过web界面查看。
hdfs dfs -mkdir /input
hdfs dfs -put text.txt /input
错误提示:
修改input文件夹的权限,保证hadoop01 用户对input有执行的权限。不修改还是会报错++++
到此,你就可以真正的运行了,执行命令
hadoop jar hadoop_api-1.0-SNAPSHOT.jar wordCount.WordCountDriver /input /output
结果显示如下,则运行成功
通过cat查看也可以在web界面查看。
到此,两种运行方式,实现词频统计结束。