오예 !!!
[AWS] Hadoop MapReduce 기반 알파벳 Counter 구현하기 본문
이번 게시글에서는 AWS EC2에서 Hadoop MapReduce framework를 사용하여 알파벳 counter를 구현해 볼 것이다.
알파벳 counter는 이름 그대로 input string을 구성하고 있는 특정 알파벳이 몇 개인지 카운트하는 작업을 수행한다.
예시는 다음과 같다.
* input: Hello Ewha!
* output:
h 2
e 2
l 2
o 1
w 1
a 1
(알파벳 대소문자는 구분하지 않으며, 알파벳 외의 모든 문자는 무시한다.)
1. AWS EC2 인스턴스 생성
그럼 본격적인 구현에 앞서 AWS EC2 인스턴스를 생성해준다.
AMI로는 기본 ubuntu 서버를 이용하였으며, 인스턴스 타입은 t2.micro (프리티어 사용 가능)을 선택했다.


키 페어는 따로 설정하지 않고 "키 페어 없이 계속 진행(권장되지 않음)"을 선택했다.
보안 그룹은 새로 만들어주었는데, SSH 트래픽 허용으로 설정하였다,

그 외는 모두 기본으로 설정하였다.
인스턴스를 생성하였다면, 이제 인스턴스를 연결한다.
내 경우에는 브라우저 기반 SSH 연결을 선택하였다.

연결이 완료되었다면 아래와 같은 화면이 뜰 것이다.

2. Hadoop MapReduce Setup
이제 앞에서 생성한 EC2 인스턴스에 Hadoop MapReduce setup을 진행할 것이다.
이를 위해서는 자바 역시 설치가 되어야하기 때문에, 우선 OpenJDK를 설치한다.
$ sudo apt update
$ sudo apt install default-jdk
설치가 완료되면 버전을 확인한다.
$ java -version
다음과 같은 메시지가 출력될 것이다.

이제 Hadoop을 설치하기 위해 아래 코드를 실행한다.
$ wget https://dlcdn.apache.org/hadoop/common/hadoop-3.3.4/hadoop-3.3.4.tar.gz
$ tar -xzvf hadoop-3.3.4.tar.gz
$ sudo mv hadoop-3.3.4/ /usr/local/hadoop
Hadoop binary files를 가져와서 압축을 해제하였고, 추출된 파일을 /usr/local 로 이동시켰다.
참고로 두번째 명령을 실행할 때는 시간이 조금 걸린다.
이제 Hadoop's Java Home을 구성하기 위해 Hadoop-env.sh를 열어준다.
$ sudo vim /usr/local/hadoop/etc/hadoop/hadoop-env.sh
코드를 내리다 보면 "# export JAVA_HOME=" 을 찾을 수 있을 것이다.
이 부분을 아래와 같이 수정해준다.
| export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/ |
이제 환경 변수를 세팅해준다.
아래 명령어를 실행하여 .bashrc를 연다.
$ vim ~/.bashrc
맨 밑에 아래와 같은 코드를 삽입한다.

아래 코드를 실행하여 변경사항들을 적용한다.
$ source ~/.bashrc
아래 명령어를 통해 hadoop이 잘 설치되었는지 확인한다.
$ hadoop
3. 알파벳 Counter 코드 작성
이제 모든 설정은 끝났으니 본격적으로 코드를 작성해준다.
3개의 java 파일에 3개의 클래스를 따로 구현해주었다.
vim 명령어를 통해서 파일을 만든 후 코드를 작성하였다.
(1) AlphabetMapper.java
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;
public class AlphabetMapper extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable>{
// 문자열이 대문자로 이루어져있는지 확인하는 함수
public boolean isStringUpperCase(String str){
char[] charArray = str.toCharArray();
for(int idx = 0; idx < charArray.length; idx++){
if(!Character.isUpperCase(charArray[idx]))
return false;
}
return true;
}
public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException{
String line = value.toString();
String tokens[] = line.split("");
for(int i = 0; i < tokens.length; i++){
String ch = tokens[i];
// ch가 알파벳인지 확인
if(ch.matches("^[a-zA-Z]*$")){
// ch가 대문자인 경우 소문자로 변환
if(isStringUpperCase(ch))
ch = ch.toLowerCase();
Text outputKey = new Text(ch);
output.collect(outputKey, new IntWritable(1));
}
}
}
}
(2) AlphabetReducer.java
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Iterator;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reducer;
import org.apache.hadoop.mapred.Reporter;
public class AlphabetReducer extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable>{
public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException{
int sum = 0;
while(values.hasNext()){
sum += values.next().get();
}
output.collect(key, new IntWritable(sum));
}
}
(3) AlphabetCounter.java
import java.io.IOException;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.TextInputFormat;
import org.apache.hadoop.mapred.TextOutputFormat;
public class AlphabetCounter{
public static void main(String[] args) throws IOException {
JobConf conf = new JobConf(AlphabetCounter.class);
conf.setJobName("AlpahbetCount");
conf.setMapperClass(AlphabetMapper.class);
conf.setCombinerClass(AlphabetReducer.class);
conf.setReducerClass(AlphabetReducer.class);
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(IntWritable.class);
conf.setInputFormat(TextInputFormat.class);
conf.setOutputFormat(TextOutputFormat.class);
FileInputFormat.setInputPaths(conf, new Path(args[0]));
FileOutputFormat.setOutputPath(conf, new Path(args[1]));
JobClient.runJob(conf);
}
}
4. 코드 컴파일 및 실행
코드를 작성하였다면 이제 컴파일을 해준다.
아래 명령어를 통해 java 파일을 컴파일해 줄 수 있다.
$ javac -cp `hadoop classpath` AlphabetCounter.java AlphabetMapper.java AlphabetReducer.java
참고로 ` 이 심볼은 ' 심볼과는 다르다. Esc 키 아래에 있는 `를 사용하여야 한다.
명령어 실행 후 아무것도 출력되지 않았다면 컴파일이 성공한 것이고, 아래와 같은 3개의 class 파일이 생긴 것을 확인할 수 있을 것이다.
| - AlphabetCounter.class - AlphabetMapper.class - AlphabetReducer.class |
이제 jar 파일을 만들어준다.
$ jar -cvf AlphabetCounter.jar AlphabetCounter.class AlphabetMapper.class AlphabetReducer.class
명령어가 성공적으로 수행되었다면 AlphabetCounter.jar 파일이 생성된다.
알파벳 카운터를 실행하기 전에, input 파일을 위치시킬 input 폴더를 만들어준다.
$ mmkdir input
디렉토리 생성 후 해당 경로에 input 파일을 생성한다. input의 내용은 자유이다.
$ vim input/file01.txt
input 파일까지 만들어줬다면 이제 jar 파일을 실행한다.
$ hadoop jar AlphabetCounter.jar AlphabetCounter input output
error가 발생하지 않고 성공적으로 실행되었다면 output 폴더가 생성되었을 것이다.
output 디렉토리로 가보면 part-00000 라는 이름의 파일이 생성되어 있는 것을 확인할 수 있다.
바로 이 파일에 알파벳 counter의 output이 저장되어 있다.

이렇게 해서 AWS EC2 상에 Hadoop MapReduce frameword를 이용하여 알파벳 counter를 구현해보았다.
'💻 > 클라우드 컴퓨팅' 카테고리의 다른 글
| [AWS] Hadoop MapReduce 기반 word Counter 구현하기 (0) | 2022.12.19 |
|---|---|
| [AWS] WordPress blog 생성 및 DDoS attack 방어 (5) (0) | 2022.11.23 |
| [AWS] WordPress blog 생성 및 DDoS attack 방어 (4) (0) | 2022.11.23 |
| [AWS] WordPress blog 생성 및 DDoS attack 방어 (3) (0) | 2022.11.23 |
| [AWS] WordPress blog 생성 및 DDoS attack 방어 (2) (0) | 2022.11.23 |