【Hadoop】IDEA調試Docker上的Hadoop

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項目,如下圖所示,後續步驟設置即可
創建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>

添加Hadoop依賴

編寫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文件可以看到執行任務的結果,輸出了單詞的統計數量
WordCount執行結果

連接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>

修改core-site.xml

vim /usr/local/hadoop/etc/hadoop/hdfs-site.xml

添加以下內容

    <property>
        <name>dfs.permissions</name>
        <value>false</value>
    </property>

hdfs-site.xml
重新啓動Hadoop

# 先停止Hadoop相關程序
stop-all.sh

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]

本文是在本人第一次配置完成很久之後才寫的,可能有些容易出錯的細節沒寫清楚或者有錯誤,如果有問題,歡迎在下方留言糾正或提問

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章