(하둡) 클러스터에서 실행하기

1. 잡 패키징

 로컬 잡 실행자는 잡을 실행할 떄 단일 JVM을 사용하므로 모든 잡에 필요한 모든 클래스가 로컬의 클래스 경로에 존재하면 문제없이 잘 동작한다.

하지만 분산환경은 조금 복잡하다. 잡을 시작할 떄  필요한 모든 클래스를 잡 JAR파일에 패키징해서 클러스터로 보내야한다.



* 클라이언트 클래스 경로


hadoop jar <jar>로 지정하는 클라이언트의 클래스 경로는 다음과 같이 구성된다.


  • 잡 JAR 파일
  • 잡 JAR 파일의 lib 디렉토리에 있는 모든 JAR파일과 classes 디렉토리
  • HADOOP_CLASSPATH에 정의한 클래스 경로

이는 가끔 로컬 잡 실행자를 잡 JAR 파일 없이 실행 (hadoop CLASSNAME) 할 때 HADOOP_CLASSPATH 의존 클래스와 라이브러리를 지정해야 하는 이유를 설명해준다.

* 태스크 클래스 경로


클러스터(의사분산 모드)에서 맵과 리듀스 태스크는 개별 JVM 으로 실행되며 클래스 경로로 HADOOP_CLASSPATH를 지정해도 소용없다. 
HADOOP_CLASSPATH는 클라이언트 측 설정이며 따라서 잡을 제출하는 드라이버 JVM의 클래스 경로에만 해당되기떄문이다.

  • 잡 JAR파일
  • 잡 JAR파일의 lib 디렉토리에 있는 모든 JAR파일과 classes디렉토리
  • -libjars 옵션이나 DistributedCache 혹은 Job의 ddFileToClassPath()메소드를 사용해서 분산 캐시에 추가한 모든 파일

* 의존 라이브러리 패키징


클라이언트와 태스크의 클래스 경로를 지정하는 다양한 방식이 있고, 각 방식에 따라 잡의 의존 라이브러리를 포함하는 옵션이 있다.

  • 라이브러리를 푼 후 잡 JAR에 넣고 다시 패키징 한다.
  • 잡 JAR의 lib디렉토리에 라이브러리를 패키징한다.
  • 잡 JAR와 다른 위치에 라이브러리를 두고, 이를 HADOOP_CLASSPATH와 -libjars를 이용해서 클라이언트의 클래스 경로와 태스크의 클래스 경로에 각각 추가한다.

* 태스크 클래스경로의 우선순위


사용자 JAR파일은 클라이언트의 클래스 경로와 태스크 클래스경로 마지막에 추가되므로, 하둡이 사용자 코드에서 사용하는 라이브러리와 다르거나 호환되지 않는 버전을 사용하면 하둡의 내장 라이브러리와 충돌할 가능성이 존재한다.
그래서 떄론 사용자 클래스가 먼저 선택되도록 태스크 클래스 경로를 제어할 필요가 ㅇㅆ다.
먼저 클라이언트에서는 HADOOP_USER_CLASSPATH_FIRST 환경변수를 true로 설정하여 사용자 클래스 경로를 하둡의 클래스 경로 검색 순서의 맨앞에 강제로 둔다.


2.  잡 구동하기


잡을 구동하기 위해 드라이버를 실행할 떄 --conf옵션으로 잡을 실행할 클러스터를 지정해야한다.

% hadoop jar hadoop-example.jar v2.MaxTemperatureDriver \
-conf conf/hadoop-cluster.xml input/ncdc/all max-temp


먼저 잡을 시작하기 전에 ID를 출력한다. 잡의 ID는 잡을 참조하거나(예를들어 로그파일에서) mapred job명령으로 조사를 할 떄  필요하다.


<잡, 태스크, 태스크 시도 ID>

하둡 2에서 맵리듀스의 잡의 ID는 YARN 리소스 매니저가 생성한 YARN 애플리케이션 ID를 기반으로 만들어진다.

애플리케이션 ID의 포맷은 리소스매니저(애플리케이션이 아닌)가 처음 시작된 시간과 애플리케이션을 
유일하게 식별하기 위해 유지되는 증가 카운터로 이루어진다.

예) application_1410450250506_0003
먼저 1410450250506은 타임스탬프이고 0003은 애플리케이션 ID세번쨰를 의미한다.(1부터 시작)

잡 ID는 단순히 application이 아니라 job으로 변경된다.
예)job_1410450250506_0003

잡의 태스크ID는 잡ID의 job접두사를 task로 변경한다.
예)task_1410450250506_m_0003
단 태스크ID는 0부터 시작한다.즉, 위 사항은 네번쨰를 의미한다. m이 붙은 것은 맵 태스크를 의미한다.

태스크 ID는 잡이 초기화될떄 생성된다.

3. 맵리듀스 웹 UI


리소스 매니저 페이지


리소스 매니저는 10000개의 완료된 애플리케이션을 메모리상에 유지한다.
(yarn.resourcemanager.max-completed-applications로 설정)
리소스 매니저에서 삭제된 애플리케이션은 잡 히스토리 페이지에서 조회할 수 있다.
잡 히스토리는 영속적이다.


잡 히스토리

맵리듀스 잡에 대한 이벤트와 설정을 갖고 있다.


4. 결과 얻기


잡이 완료되면 다양한 방법으로 그 결과를 얻을 수 있따
각 리듀서는 하나의 출력파일을 생성하기 때문에 max-temp디렉토리에는 part-r-00000로부터 
part-r-00029까지 명명된 30개의 부분파일이 있다.

출력결과가 매우 크면 한 개이상의 리듀서를 병렬로 수행하여 다수의 부분파일을 출력해야 한다.
일반적으로 하나의 파일이 이렇게 분리된 상황이라면 다른 맵리듀스 잡의 입력 등으로 쉽게 사용할 수 있다
또한 다수의 파티션 구조는 맵-사이드에서도 활용될 수 있다.


잡의 출력결과는 매우 작기 떄문에 HDFS에서 개발머신으로 쉽게 복사 할 수 있다.
hadoop fs 명령의 -getmerge옵션은 원본으로 지정된 디렉토리에 있는 모든 파일을 가져와서 하나의 파일로 병합한 후 로컬 파일 시스템에 저장한다.

$hadoop fs -getmerge max-temp max-temp-local
$sort max-temp-local | tail

출력결과가 적다면 -cat옵션을 사용해서 출력 파일의 전체 내용을 콘솔에 출력하는 방법도 있다.
$ hadoop fs -cat max-temp/*


5. 잡 디버깅 


맵 출렫에티러르 내본낸 후 리듀스 태스크에서 분서과 집계를 하는 방법도 있지만 . 이러한 접근 방법은 프로그램의 구조적인 변경이 필요하다.

그래서 매퍼에 디버깅 코드를 추가하는 방법이 있따.


public class MaxTemperatureMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
enum Temperature {
OVER_100
}

private NcdcRecorParser parser = new NcdcRecordParser();

@public void map(LongWritable key, Text value, Context context) {
parser.parse(value);
if(parser.isValidTemperature()) {
int airTemperature = parser.getAirTemperature();
if(airTemperature > 1000) {
System.err.println("~~~" + value);
context.getStatus("De")
context.getCount(Temperature.OVER_100).increment(1);
}
context.write(new Text(parser.getYear()), new Intwritable(airTemperature));
}
}
}


잡이 끝나면 의심스로은 데이터를 확인할수 있다 다음과같이

$mapred job -counter job_141045025506_0006 \
'v3.MaxTemperatureMapper$Temperature' OVER_100



댓글

이 블로그의 인기 게시물

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬

(18장) WebSocekt과 STOMP를 사용하여 메시징하기