天天看點

hadoop-wordcount本地模式及叢集模式運作

前言

上一篇文章,我們利用3台雲伺服器搭建了一個Hadoop叢集,并通過hadoop -jar指令運作了Hadoop自帶的一個wordcount例子,那本片文章就通過實作一個wordcount程式,并在本地模式下運作這個程式,了解一下mapreduce編碼規範,最後 再将這個jar包送出到真正的叢集上運作。

Hadoop maven依賴

本想使用springboot內建的hadoop,但是發現其版本最高隻內建到Hadoop2.7.3,于是乎,不适用spring boot,直接使用hadoop2.9.2的包。maven依賴如下:

<dependencies>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>2.9.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-hdfs</artifactId>
        <version>2.9.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>2.9.2</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.14</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
    </dependency>
</dependencies>
           

Hadoop本地(windows環境)運作依賴

由于是本地模式運作,是以需要導入windows下的hadoop.dll和winutils.exe,否則将會抱錯

java.lang.UnsatisfiedLinkError

hadoop-wordcount本地模式及叢集模式運作

各個版本的hadoop.dll以及winutils.exe下載下傳位址:

https://download.csdn.net/download/wxgxgp/11072195

(CSDN資源預設需要積分,若沒有積分,請在我的部落格-留言闆留下郵箱,将郵件發送。)

hadoop-wordcount本地模式及叢集模式運作

當然你也可以去github下載下傳(這裡并不包含2.9.2版本):

https://github.com/4ttty/winutils

編寫MapReduce程式

由于之前對storm有所研究,是以,這次了解mapreduce還是較為容易的,關于mapreduce的原理以及解釋本人不在重複造輪子,詳情請看下方連結:

MapReduce工作流程最詳細解釋

以下内容隻是從代碼層面說明mapreduce注意的一些問題。

Map階段

public class MapperTest extends Mapper<Object, Text, Text, IntWritable> {

    @Override
    protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
        String[] words = value.toString().split(" ");
        for(String word : words){
            context.write(new Text(word),new IntWritable(1));
        }
    }
}
           

繼承Mapper類即可。注意泛型參數格式為<輸入key類型,輸入value類型,輸出key類型,輸出value類型>

注意輸入類型一般是檔案中每一行首的偏移量。

這個程式隻能統計英文單詞個數,但無法統計中文詞語個數,因為英文單詞之間有空格分割,而中文則沒有,是以若需要統計中文詞語,則需要先進行分詞處理,而這就屬于nlp的範圍了。

Reduce階段

public class ReduceTest extends Reducer<Text, IntWritable, Text, IntWritable> {

    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int sum = 0;
        for (IntWritable val : values) {
            sum += val.get();
        }
        context.write(key, new IntWritable(sum));
    }
}
           

同樣的隻需要繼承Reducer類即可,泛型參數格式為<輸入key類型,輸入value類型,輸出key類型,輸出value類型>,注意這裡的輸入key和value的類型要和map階段輸出的key和value的類型一緻。

整個map-reduce從代碼層面看起來很簡單,就是把單詞根據空格分割,然後寫入到contex,然後在根據相同的單詞進行一個累加計數的彙總,其實更多的是Hadoop架構為我們做了大量的事情。

編寫主類

public class WordCount {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        if (args == null || args.length == 0) {
            args = new String[2];
            args[0] = "E:/hadoop/input/test.txt";
            args[1] = "E:/hadoop/output";
        }
        Configuration configuration = new Configuration();

        Job job = Job.getInstance(configuration);
        job.setJarByClass(WordCount.class);

        job.setMapperClass(MapperTest.class);
        job.setReducerClass(ReduceTest.class);

        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        Path inputPath = new Path(args[0]);
        Path outputPath = new Path(args[1]);
		//自動删除已存在的目錄
        outputPath.getFileSystem(configuration).delete(outputPath, true);
        FileInputFormat.setInputPaths(job,inputPath);
        FileOutputFormat.setOutputPath(job,outputPath);
        boolean wait = job.waitForCompletion(true);

        System.exit(wait?0:1);
    }
}
           

運作一下:

hadoop-wordcount本地模式及叢集模式運作

送出到叢集運作

打包jar

因為使用的是maven,是以就用maven打包jar了。

需要注意的是:

要在pom.xml中添加打包類型:

<packaging>jar</packaging>
           

添加主類:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>test.WordCount</mainClass>
                <addClasspath>true</addClasspath>
            </manifest>
        </archive>
    </configuration>
</plugin>
           

不添加主類則送出到叢集後會出現找不到主類的錯誤。

送出到叢集

将jar包上傳到伺服器上,執行指令:

hadoop jar hadooptest-1.0-SNAPSHOT.jar /test/input /test/output
           

(注意這裡的路徑修改為自己的,hadooptest-1.0-SNAPSHOT.jar為打包後的jar包名稱,若沒有在程式裡設定job名稱,則會預設一jar包名稱作為job名稱)

其中/test/input下有一個檔案text.txt,其内容如下:

哈哈哈哈
a
adad
adads 
asdddqwd
asda
adds
13
132
132
a
           
hadoop-wordcount本地模式及叢集模式運作

我們也可以在web界面上看到執行情況:

hadoop-wordcount本地模式及叢集模式運作

最後我們在web界面檢視一下結果:

hadoop-wordcount本地模式及叢集模式運作

表明叢集上運作成功。