文章目录
IDEA调试Docker上的Hadoop
上一篇Docker搭建Hadoop环境文章中我介绍了一下如何在Docker上搭建Hadoop环境,这篇文章讲介绍如何通过IDEA连接Docker容器里的Hadoop并且调试Hadoop的代码
注意:文中多次提到容器终端是hadoop-master这个容器的终端
安装JDK
- Ubuntu默认安装的是OpenJDK,会少很多东西,我们需要重新下载JDK替换默认的OpenJDK,配置过程请参考Ubuntu修改默认JDK
安装IDEA
- 方式一:可以直接通过Ubuntu的应用商店安装Community版本的IDEA
- 方式二:通过Jetbrains官网下载https://www.jetbrains.com/idea/download/#section=linux下载IDEA,将其解压找到里面的启动文件双击之后就能运行了
- Ultimate版本的IDEA只有30天的试用期,可以在网上查找IDEA的激活服务器或者破解方法,学生可以通过学校的邮箱申请学生账号,学生账号可以免费试用IDEA
创建Maven项目
打开IDEA之后选择新建Maven项目,如下图所示,后续步骤设置即可
创建完成后,IDEA右下角会提示是否自动导入Maven以来,选择自动导入,这样每次只要修改保存了pom.xml文件Maven就会自动下载导入添加的依赖。然后往pom.xml文件里添加Hadoop依赖并保存
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
编写WordCount程序
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
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> {
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
public static class IntSumReducer
extends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
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();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
本地执行MapReduce程序
项目中导入Hadoop的依赖,可以在没有配置Hadoop分布式环境的情况下采用本地方式测试MapReduce程序
创建测试数据
在项目的根目录下创建一个input目录,并在该目录下输入一些测试数据
Hadoop
Spark
Hive
HBase
BigData
Hadoop
执行WordCount程序
首先我们先配置执行参数,如下图所示,Main class选择前面写的WordCount,Program arguments里填写两个参数——输入路径和输出路径:input/ output/
执行程序,执行完成后项目根目录下会多出一个output目录,查看part-r-00000文件可以看到执行任务的结果,输出了单词的统计数量
连接Docker集群执行WordCount
修改Hadoop配置
在IDEA通过Docker集群执行MapReduce任务是会报一个异常,说本机的用户名没有权限访问Docker容器内的HDFS,此时需要修改容器内Hadoop的两个配置文件,通过master的终端执行
vim /usr/local/hadoop/etc/hadoop/core-site.xml
添加以下内容
<property>
<name>hadoop.http.staticuser.user</name>
<value>root</value>
</property>
vim /usr/local/hadoop/etc/hadoop/hdfs-site.xml
添加以下内容
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
重新启动Hadoop
# 先停止Hadoop相关程序
stop-all.sh
# 再次启动Hadoop
./start-hadoop.sh
配置log4j
hadoop默认使用了log4j输出日志,如果没有自定义配置log4j,控制台不会输入mapreduce过程,所以需要在resources下配置日志信息,在IDEA中项目的src/main/resources下创建一个log4j.properties文件,将以下内容复制进去并保存(读者可以尝试不配置这一步,看控制台的输出信息是什么)
log4j.rootLogger = info,stdout
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志文件设置 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = vincent_player_debug.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志文件设置 ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File = vincent_player_error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
删除output目录
由于前面我们执行了一次./run-wordcount.sh脚本,这个脚本已经生成了一个目录output,hadoop默认是不能覆盖原来的执行的输出结果,因此在执行MapReduce时会报错,提示output已经存在,因此做实验时需要将原来的output删除,在容器终端通过以下命令删除
hdfs dfs -rm -R /user/root/output
配置执行参数
将原来本地执行的参数/input /output改成Docker容器中的hdfs
hdfs://localhost:9000/user/root/input
hdfs://localhost:9000/user/root/output
如果使用localhost显示无法连接,可能是端口没映射成功,这里可以先把localhost改为hadoop-master的IP地址,可通过在本地终端中执行以下命令查看hadoop-master的地址(也可在hadoop-master容器里使用ifconfig命令查看)
# sudo docker inspect 【contanier-id】
sudo docker inspect hadoop-master
执行WordCount
此时所有配置过程已经完成,可以执行WordCount程序了,在控制台可以看到有Docker容器集群的执行结果了
此时在容器终端输入以下命令可以看到单词统计结果
hdfs dfs -cat /user/root/output/part-r-00000
补充内容
备份镜像
1、配置好Docker容器之后建议将自己配置好的容器备份一份,方便迁移到其他机器使用,首先通过以下命令将容器保存为镜像
# docker commit [container-id] [new image-id]
docker commit hadoop-master my-hadoop-master
docker commit hadoop-slave1 my-hadoop-slave1
docker commit hadoop-slave2 my-hadoop-slave2
此镜像的内容就是你当前容器的内容,接下来你可以用此镜像再次运行新的容器
2、镜像备份,这一步是将上一步保存的镜像保存到文件中,执行以下命令
# docker save -o [filename.tar] [image-id]
docker save -o my-hadoop-master.tar my-hadoop-master
docker save -o my-hadoop-slave1.tar my-hadoop-slave1
docker save -o my-hadoop-slave2.tar my-hadoop-slave2
3、通过以下命令恢复镜像或将镜像迁移到其他设备
# docker load -i [image-file]
docker load -i my-hadoop-master.tar
docker load -i my-hadoop-slave1.tar
docker load -i my-hadoop-slave2.tar
可能要用到的一些命令
将hdfs里的文件移动到本地
hdfs dfs -copyToLocal [src] [local target]
或者
hadoop fs -copyToLocal [src] [local target]
本文是在本人第一次配置完成很久之后才写的,可能有些容易出错的细节没写清楚或者有错误,如果有问题,欢迎在下方留言纠正或提问