OS X下MapReduce程序運行的幾種模式

1.MapReduce程序運行的模式簡介

  1. 程序運行模式

    • 本地模式
      • 利用本地的JVM運行,使用本地的IDE進(jìn)行debug
    • 遠(yuǎn)程模式
      • 提交至遠(yuǎn)程的集群上運行,使用本地的IDE進(jìn)行debug
      • 提交至遠(yuǎn)程的集群上運行,不使用本地IDE進(jìn)行debug
  2. 數(shù)據(jù)存放路徑

    • 遠(yuǎn)程文件系統(tǒng)(hdfs)
    • 本地文件系統(tǒng)(local file system)


2.開發(fā)環(huán)境簡介

  • 操作系統(tǒng):macOS Sierra 10.12.6
  • Java版本:1.8.0_131-b11
  • Hadoop版本:hadoop-2.7.4
  • IDE:IntelliJ IDEA


3.MapReduce程序運行例子

3.1 程序需求

學(xué)校里開設(shè)了多門課程,有語文(chinese)、數(shù)學(xué)(math)、英語(english)等。經(jīng)過了一次年級統(tǒng)考后,每個學(xué)生的成績都被記錄在多個文本文件中,文本文件格式如下。

  • math.txt
Ben 75
Jack 60
May 85
Tom 91
  • english.txt
Jack 72
May 60
Tom 62
Ben 90
  • chinese.txt
Ben 79
May 88
Tom 68
Jack 70

現(xiàn)需要根據(jù)以上的文本文件,算出每個學(xué)生在本次統(tǒng)考中的平均分,并將結(jié)果用一個總的文件averageScore.txt進(jìn)行存儲。averageScore.txt的格式如下。

  • averageScore.txt
#name #score
Ben 0.0
May 0.0
Tom 0.0
Jack 0.0


3.2 程序設(shè)計思路

3.2.1 Mapper的處理邏輯

Mapper每次從文本文件中讀取1行內(nèi)容,即調(diào)用1次map方法。Mapper需要把原始數(shù)據(jù)中一行的內(nèi)容拆分成學(xué)生姓名(student name)和該門課程的分?jǐn)?shù)(score)。按照需求,本程序最終要算出每一個學(xué)生的平均分,所以學(xué)生姓名應(yīng)作為一個key,對應(yīng)的value即為該生的平均分(實際上是不嚴(yán)謹(jǐn)?shù)模驗樵趯嶋H環(huán)境中會出現(xiàn)多個學(xué)生重名的現(xiàn)象,若不作特殊處理,key是不允許重復(fù)的。最根本的解決方案是采用學(xué)號作為key,但為了演示直觀,僅采用學(xué)生姓名作為key)

Mapper讀完一行的數(shù)據(jù)后,把{student name,score}這個key-value寫入中間結(jié)果,準(zhǔn)備傳送給Reducer作下一步的運算。

3.2.2 Reducer的處理邏輯

Reducer接收到的數(shù)據(jù),實際上是一個key與該key對應(yīng)的value的一個集合(并不僅僅是一個value)。在本需求中,傳入reduce方法的參數(shù)是學(xué)生姓名,以及該生多門課程分?jǐn)?shù)的集合,類似于Ben,[60,70,80,...]。所以Reducer需要將集合中的分?jǐn)?shù)求和,然后求出平均值,最終得到一個{student name, average score}key-value對。

3.2.3 具體代碼設(shè)計

  • AVGMapper類
    用于實現(xiàn)map方法
package mr;

import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;

/**
 * Created by marco on 2017/8/17.
 */
public class AVGMapper extends Mapper<LongWritable, Text, Text, DoubleWritable>
{
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException
    {
        String line = value.toString();
        if(line.length() == 0)  // 文件格式錯誤,出現(xiàn)空行
            return;
        String[] split = line.split(" ");
        String stuName = split[0];
        String stuScore = split[1];
        double score = Double.parseDouble(stuScore);    // 轉(zhuǎn)成double類型,方便后續(xù)求均值計算
        context.write(new Text(stuName), new DoubleWritable(score));
    }
}
  • AVGReducer類
    用于實現(xiàn)reduce方法
package mr;

import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;

/**
 * Created by marco on 2017/8/17.
 */
public class AVGReducer extends Reducer<Text, DoubleWritable, Text, DoubleWritable>
{
    @Override
    protected void reduce(Text key, Iterable<DoubleWritable> values, Context context) throws IOException, InterruptedException
    {
        double sum = 0;
        int length = 0;
        for(DoubleWritable value : values)
        {
            sum += value.get();
            length++;
        }

        double avgScore = sum / (double)length;
        context.write(key, new DoubleWritable(avgScore));
    }
}

  • AVGRunner類
    用于關(guān)聯(lián)Mapper與Reducer,并創(chuàng)建MapReduce任務(wù)(Job)提交運行。基本代碼如下所示。
package mr;

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

/**
 * Created by marco on 2017/8/17.
 */
public class AVGRunner
{
    static public void main(String[] args) throws Exception
    {
        // 設(shè)置hdfs的handler
        Configuration fsConf = new Configuration();
        fsConf.set("fs.default.name","hdfs://localhost:9000/");
        FileSystem fs = FileSystem.get(fsConf);

        // MapReduce的配置參數(shù)
        Configuration mrConf = new Configuration();

        // 新建一個求平均值的Job
        Job avgJob = Job.getInstance(mrConf);
        avgJob.setJarByClass(AVGRunner.class);

        // 設(shè)置Mapper類與Reducer類
        avgJob.setMapperClass(AVGMapper.class);
        avgJob.setReducerClass(AVGReducer.class);

        // 設(shè)置輸入輸出的數(shù)據(jù)結(jié)構(gòu)
        avgJob.setMapOutputKeyClass(Text.class);
        avgJob.setMapOutputValueClass(DoubleWritable.class);
        avgJob.setOutputKeyClass(Text.class);
        avgJob.setOutputValueClass(DoubleWritable.class);

        // 檢查結(jié)果輸出目錄,若已存在則刪除輸出目錄
        if(fs.exists(new Path("/avg/output")))
        {
            fs.delete(new Path("/avg/output"), true);
        }

        // 設(shè)置數(shù)據(jù)目錄以及結(jié)果輸出目錄
        FileInputFormat.setInputPaths(avgJob, new Path(""));
        FileOutputFormat.setOutputPath(avgJob, new Path(""));

        // 提交任務(wù),等待完成
        System.exit(avgJob.waitForCompletion(true)?0:1);
    }
}


3.3 MapReduce程序運行

若使用本地文件系統(tǒng)的數(shù)據(jù)文件,且在本地模式運行,無需配置hdfs相關(guān)的參數(shù),數(shù)據(jù)目錄以及結(jié)果輸出目錄填寫本地路徑即可。(確保結(jié)果輸出文件夾未被創(chuàng)建,否則會報異常)

// 均填寫本地文件路徑即可
FileInputFormat.setInputPaths(avgJob, new Path(""));
FileOutputFormat.setOutputPath(avgJob, new Path(""));


若使用hdfs上的數(shù)據(jù)文件,且在本地模式運行,應(yīng)配置hdfs相關(guān)參數(shù),數(shù)據(jù)目錄以及結(jié)果輸出目錄均填寫hdfs的路徑。(確保結(jié)果輸出文件夾未被創(chuàng)建,否則會報異常)

// 設(shè)置hdfs參數(shù),并用該配置創(chuàng)建一個新的Job
Configuration fsConf = new Configuration();
fsConf.set("fs.default.name","hdfs://localhost:9000/");
Job avgJob = Job.getInstance(fsConf);


// 均填寫hdfs路徑即可
FileInputFormat.setInputPaths(avgJob, new Path(""));
FileOutputFormat.setOutputPath(avgJob, new Path(""));

3.3.1 本地模式運行

本地模式運行,直接編譯執(zhí)行AVGRunner的main方法即可,程序運行結(jié)束后會在自行設(shè)置的結(jié)果輸出目錄中生成運行結(jié)果。

3.3.2 遠(yuǎn)程集群運行

首先使用IDE將程序打成一個jar包,本例中命名為hadoop.jar

提交到遠(yuǎn)程集群上運行分兩種情況

  • 使用本地IDE(IntelliJ IDEA)運行,任務(wù)被提交到集群運行,但可使用IDE進(jìn)行跟蹤debug

    新建一個MapReduce的配置對象,將已經(jīng)打包好的jar包傳入配置中

      // MapReduce的配置參數(shù),遠(yuǎn)程運行,本地debug
      Configuration mrConf = new Configuration();
      mrConf.set("mapreduce.job.jar","hadoop.jar");
      mrConf.set("mapreduce.framework.name","yarn");
      
      //利用以上配置新建一個Job
      Job avgJob = Job.getInstance(mrConf);
      avgJob.setJarByClass(AVGRunner.class);
    


  • 在終端直接使用hadoop命令將任務(wù)提交到集群運行,無法使用IDE進(jìn)行跟蹤debug

    直接在終端中輸入hadoop命令

    hadoop jar $jar包名稱 $待執(zhí)行的類的名稱
    

    在本例中應(yīng)輸入

    hadoop jar avg.jar mr.AVGRunner
    

####################### 注意?? #######################

在OS X中,使用IntelliJ IDEA打包jar包后,若在終端中直接使用hadoop jar $jar包名稱 $待執(zhí)行的類的名稱提交MapReduce任務(wù),會報出異常,因為OS X系統(tǒng)的文件系統(tǒng)對大小寫不敏感(case-insensitive)

經(jīng)過對此異常的搜索,暫時的解決方案是通過刪除jar包中的LICENSE文件,使任務(wù)順利提交。

# 在終端中執(zhí)行以下命令
zip -d $jar包名稱 META-INF/LICENSE
zip -d $jar包名稱 LICENSE

#####################################################

可以看到使用了hadoop命令提交任務(wù)后,系統(tǒng)調(diào)用了RPC框架和Yarn框架中的一些服務(wù),用于遠(yuǎn)程運行,而非使用LocalJobSubmitter于本地運行。

并且在MapReduce任務(wù)管理頁面可看到任務(wù)已經(jīng)完成的歷史記錄。

4.總結(jié)

MapReduce任務(wù)可在本地運行,也可提交到集群上運行。

在開發(fā)初期,需要編寫Demo程序時,可在本地進(jìn)行開發(fā)與測試,將數(shù)據(jù)文件放置在本地文件系統(tǒng),直接使用IDE運行主類的main方法,觀察運行結(jié)果。

上線前調(diào)試,可采用遠(yuǎn)程模式運行,不直接使用hadoop命令提交,而是使用IDE進(jìn)行提交與debug,這樣既可以保證程序運行在遠(yuǎn)處集群上(生產(chǎn)環(huán)境or開發(fā)環(huán)境),也可以在本地方便跟蹤調(diào)試。

可上線時,使用hadoop命令直接提交到遠(yuǎn)程集群,并通過localhost:50070(默認(rèn)配置)的任務(wù)管理頁面進(jìn)行觀察。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內(nèi)容