IDEA遠程調試hadoop

以前都是在idea裏面寫好了hadoop程序,然後打成jar包,然後在服務器上通過jar 命令進行MR 程序的執行,這樣的方式不利於調試,下面給出在idea上進行遠程調試hadoop的方法。

平臺

hadoop:2.6.5
OS : OSX
IDE : IDEA

注意細節

不能用maven導包,否則會報如下錯誤:
ERROR security.UserGroupInformation: PriviledgedActionException as:root cause:org.apache.hadoop.ipc.RemoteException:
Server IPC version 9 cannot communicate with client version 4

發現是由於hadoop-core這個包的原因導致的,但是其最高支持1.2.1 筆者沒有找到解決方法。所以想在本地進行調試,只能乖乖的手動導包。

hadoop在IDEA上遠程調試的步驟

1. 導如hadoop所需要的包

這一步簡單的帶過吧,需要導的是common, hdfs, yarn, mapreduce 四個目錄下的lib下的所有包和其目錄下非example的包(多導入沒毛病,)
額,這幾個文件夾在hadoop/share/hadoop/下

2. 更改language level

更改用下圖表示,,很直觀
1.
這裏寫圖片描述

2.
這裏寫圖片描述

3.設置app 運行的參數

1. 點擊Edit Configuration->傳建一個application

2. 在右邊的program argument 中輸入服務器上HDFS的輸入路徑和程序的輸出路徑(如果程序中制定了輸入輸出路徑,這裏可以不用設置)

3. 和project directory中輸入:hadoop的路徑(這個hadoop可以從服務器上download一份下來,隨便你放在本地什麼地方)

任然上圖,可以參考一下我的設置

這裏寫圖片描述

4. 由於每一次執行後,輸出路徑不會自動的刪除,如果我們的輸出路徑不修改,那麼程序會報輸出文件已存在的錯誤,如下:

Exception in thread "main" org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://master1:9000/flow/output already exists

解決方法:
1. 去服務器上吧output paht 給手動刪除了
2.寫代碼
個人喜歡第二種,既然用本地遠程調試了,還跑去服務器上一次一次的刪,太麻煩了。下面給出刪除的代碼,其實就是HDFS的操作:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * Created by macan on 2017/1/14.
 */
public class HdfsConnection {

    private FileSystem fs = null;

    public HdfsConnection() throws URISyntaxException, IOException, InterruptedException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://master1:9000");

        fs = FileSystem.get(new URI("hdfs://master1:9000"), conf, "root");
    }

    /**
     * 刪除HDFS 中指定的目錄
     * @param path  需要刪除的目錄
     * @param is 是否進行遞歸刪除文件
     * @throws IOException
     */
    public boolean delete(String path, boolean is) throws IOException {
        boolean res = true;
        if (exits(path)) {
            res = fs.delete(new Path(path), is);
            fs.close();
        }
        return res;
    }

    /**
     * 查看文件是否存在
     * @param path 文件路徑
     * @return 如果文件存在,返回true,否則返回false
     * @throws IOException
     */
    public boolean exits(String path) throws IOException {
        boolean res = fs.exists(new Path(path));
        return res;
    }
}

在MR的主程序中調用示例:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
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;

import java.io.IOException;
import java.net.URISyntaxException;

/**
 * Created by macan on 2017/1/14.
 */
public class FlowCountWithPartitioner {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException {
        if (args.length < 2){
            System.out.println("please input 2 args, one is input path and second is output path");
            System.exit(-1);
        }

        //刪除hdfs上的output 路徑
        HdfsConnection hdfs = new HdfsConnection();
        hdfs.delete(args[1], true);


        Configuration conf = new Configuration();

        Job job = Job.getInstance(conf);
        //指定本程序jar包所在的目錄
        job.setJarByClass(FlowCountWithPartitioner.class);
        //指定本業務的job要使用的mapper/reduce 的業務類
        job.setMapperClass(FlowCountMapper.class);
        job.setReducerClass(FlowCountReduce.class);
        //指定自定義的Partiotioner
        job.setPartitionerClass(ProvincePartitioner.class);
        //指定相應數量的reducetask,num: 相應的數據分區數量
        job.setNumReduceTasks(5);

        //指定mapper的輸出數據類型kv
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(FlowBean.class);

        //指定最終輸出的數據類型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(FlowBean.class);

        //指定job輸出原始文件所在的目錄

        FileInputFormat.setInputPaths(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        //將job中設置的相關參數,以及所用的Java類所在的jar包,提交任務給yarn
//        job.submit();
        //true表示將集羣中運行的結果打印出來
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

重點在22,23 行

總結

Windows上的沒有使用過,改天試一下更新博客(可以看參考),如果有錯誤,請指教

參考

  1. http://www.jb51.net/article/88581.htm
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章