Thing's by Actruce

하둡 WordCount 예제 실행하기 본문

IT/Hadoop

하둡 WordCount 예제 실행하기

Actruce 2017. 12. 3. 22:15

    - 하둡 설치가 되지 않은 사람은 이전 포스트팅의 하둡 2.7.3 설치 를 참조하기 바란다.

    - WordCount 예제 실행은 Hadoop Apache 공식 사이트의 jar 생성방식을 사용한다.

           하둡 아파치 2.7.3 WordCount 예제 Documentation (jar command 를 사용하여 jar 파일 만들기)

           악명높은 WordCount 예제 실행하기 (maven 으로 jar 파일 만들기도 참조)

 

WordCount example 실행하기 (jar command 사용)

  1. WordCount.java 작성

    - 필자의 경우는 /usr/hduser/src_hadoop/mapreduce/WordCount_Origin/ 아래에 WordCount_Origin.java 파일을 생성하였다.

    - 하둡 공식 사이트의 Documentation 을 참조하여 WordCount_Origin.java 파일을 생성한다.

    - WordCount_Origin.java 파일 내용
      ※ 이 Code 는 Hadoop 2.X API 기준으로 작성된 코드이다. 다른 WordCount 예제들의 경우 1.X 기준으로 작성된 예제들도 있으므로 Compile 이 되지 않는 경우 코드가 설치한 하둡 버전과 맞는지 먼저 확인하자.

 

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);
  }
}

 

  2. ~/.bashrc 의 PATH 설정을 확인한다. 아래 내용이 없을 경우 추가하고 source ~/.bashrc 를 수행하자.

    export JAVA_HOME=/usr/java/default
    export PATH=${JAVA_HOME}/bin:${PATH}
    export HADOOP_CLASSPATH=${JAVA_HOME}/lib/tools.jar

 

  3. /usr/hduser/src_hadoop/mapreduce/WordCount_Origin/ 폴더의 java 파일을 compile 하고 jar 파일을 생성한다.

    hadoop com.sun.tools.javac.Main WordCount_Origin.java
    jar cf wc01.jar WordCount*.class

        ※ compile 이 되지 않는 이유는 오타나 하둡 API 버전이 맞지 않거나 1.X API 를 활용한 소스코드를 붙여넣은 경우이다.

        wc01.jar 파일이 생성된 것을 확인하자.

 

 4. /user/hduser/wordcount/input 폴더 생성

    - 우리가 설치한 hdfs 는 $HADOOP_HOME 으로 /usr/hduser 를 인식한다. hdfs 를 통해서 기록하기 위해서는 hdfs 명령어를 사용하여 폴더와 파일을 다뤄야 한다.

    - 많이 헷갈리는 부분중에 하나가 hadoop fs 또는 hadoop dfs 를 활용하지 않고 mkdir 나 cp 명령으로 파일과 폴더를 생성/복사 하는 경우인데 hadoop 은 자체 File System 을

      갖고 있으므로 그 내부는 hadoop file system 의 영역으로 생각해야 한다. 리눅스 OS 의 /usr/hduser 와 다름을 확인!

    - 이제 생성해 보자.

    hadoop fs -mkdir /user/hduser/wordcount/input

 

  5. wordcount 수행할 text 파일을 input 폴더에 삽입

    - wordcount example 을 수행할 텍스트 파일로 나는 버락 오바마 연설문 파일 3개를 사용했다. 버락 오바마 연설문

    - obama01.txt, obama02.txt, obama03.txt 파일을 /user/hduser/wordcount/input 폴더에 삽입하자.

    hadoop fs -put obama*.txt /user/hduser/wordcount/input

 

  6. /user/hduser/wordcount/output 폴더 삭제

    - 혹시라도 이미 WordCount example 을 수행하였다면, output 폴더가 생성되어 있을 것이다. 이 경우 이를 삭제하지 않으면 IOException 이 발생하게 된다.

    hadoop fs -rm -r /user/hduser/wordcount/output

 

  7. hadoop jar 명령으로 WordCount 수행

     - 3. 에서 만든 wc01.jar 파일을 사용하여 /user/hduser/wordcount/input 의 대상파일로 부터 단어별 수를 센 결과를 /user/hduser/wordcount/output 에 기록한다.

     hadoop jar wc01.jar WordCount_Origin /user/hduser/wordcount/input /user/hduser/wordcount/output

 

  8. 생성된 파일 조회하기 및 내용 확인

    - 먼저 생성된 output 폴더의 내용을 확인해 보자.

    hadoop fs -ls /user/hduser/wordcount/output

        다음과 같이 2개의 파일이 생성된 것을 알 수 있다

    Found 2 items
    -rw-r--r-- 1 hduser supergroup          0 2017-05-20 21:06 /user/hduser/wordcount/output/_SUCCESS
    -rw-r--r-- 1 hduser supergroup        963 2017-05-20 21:06 /user/hduser/wordcount/output/part-r-00000

    - 그 내용은 아래와 같다.

hadoop fs -cat /user/hduser/wordcount/output/part-r-00000 | more

Khe 1
Lady, 1
Latino, 1
Less 1
Let 5
Lincoln 1
Main 1
Maine, 1
Malia, 1
Manassas, 1
Manassas. 1
McCain. 1
Michelle 2
Moines 1
Montana. 1
Montgomery, 1
Muslim 1
Muslims, 1
My 1
Native 1
New 3
Night 2
Nixon 2
Nobody 1
Nor 1
Normandy 1
Northern 1
Not 2
November 2
Now, 1
Obama 1
Obama, 1
Obama. 1
On 2
Our 13
Overcome.” 1
Palin 1
 
 

WordCount example 실행하기 (maven 으로 jar 파일 생성하기)

  - maven 으로 패키지를 생성하고, vi editor 가 아닌 IDAE IntelliJ 를 사용한다는 점만 빼면 위의 예제와 흐름은 같다. 다만, 이 예제에서는 WordCount_Origin.java 안에 내부 클래스를 생성하는 형태가 아니라 Mapper, Reducer, Job Class 를 따로 생성하여 한번에 jar 파일로 생성한다는 점이 다르다.

  - 악명높은 WordCount 예제 실행하기   참조

 

  1. maven 설치

    sudo apt-get install maven

 

  2. IntelliJ 설치

    - IntelliJ 로 구글링하여 해당 사이트에서 tar 파일을 다운로드하고 압축을 해제하면 /bin/idea.sh 파일이 있다. 이를 실행하면 IDE 환경이 나온다.

 

  3. maven project 생성 및 pom.xml 편집

    - new maven project 를 생성하고 다음 항목을 입력해 준다.

    GroupId: org.hadoop.mapreduce-example
    ArtifactId: wordcount-demo
    Version: 1.0-SNAPSHOT

    - pom.xml 을 다음과 같이 편집한다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.hadoop.mapreduce-example</groupId>
    <artifactId>wordcount-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.7.3</version>
        </dependency>
    </dependencies>
</project>

    - project 에 3개 .java 파일을 추가한다.

WordCountMapper.java
    
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Created by ardilgulez on 27.11.2016.
 * Of course I would add my nickname somewhere
 */
public class WordCountMapper extends Mapper<Object, Text, Text, IntWritable> {

    @Override
    public void map(Object key, Text input, Context context){
        try {
            StringTokenizer tokenizer = new StringTokenizer(input.toString());
            while(tokenizer.hasMoreTokens()){
                Text word = new Text();
                word.set(tokenizer.nextToken());
                context.write(word, new IntWritable(1));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}


     WordCountReducer.java

     import org.apache.hadoop.io.IntWritable;
     import org.apache.hadoop.io.Text;
     import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/**
 * Created by ardilgulez on 27.11.2016.
 * What's a better place to plug your name than class javadoc
 */
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {

    @Override
    public void reduce(Text key, Iterable<IntWritable> values, Context context){
        try {
            int resultNumber = 0;
            for(IntWritable value : values){
                resultNumber += value.get();
            }
            IntWritable result = new IntWritable();
            result.set(resultNumber);
            context.write(key, result);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

 

    WordCountJob.java

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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

/**
 * Created by ardilgulez on 27.11.2016.
 * I do not create package name conflicts
 * and still get to plug my name
 */
public class WordCountJob {

    public static void main(String[] args){
        try {
            Configuration conf = new Configuration();
            Job job = Job.getInstance(conf, "WordCountJob");
            job.setJarByClass(WordCountJob.class);
            job.setMapperClass(WordCountMapper.class);
            job.setCombinerClass(WordCountReducer.class);
            job.setReducerClass(WordCountReducer.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);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

   4. maven 으로 jar 파일 생성

    mvn clean install

    - 이후의 과정은 같다.

    - 지금까지 기본적인 WordCount example 을 수행하는 방법을 확인해 보았다. 응용된 MapReduce 프로그램을 작성하고 활용하기 위해서는 많은 노력이 필요할 것이다.

 

 

'IT > Hadoop' 카테고리의 다른 글

하둡 소개글  (0) 2017.12.03
하둡 2.7.3 설치  (0) 2017.12.03
Comments