티스토리 뷰

오늘은 하둡2의 이벤트 처리, 정확히는 YARN의 이벤트 처리 방식에 대해서 설명 드겠습니다. 얀의 이벤트 처리 모델은 얀의 아키텍처에서 가장 중요한 부분 중 하나 입니다. 기존 맵리듀스는 함수 호출 기반의 이벤트 모델을 사용했습니다. 이러한 모델에서는 이벤트들의 처리가 순차적으로 발생합니다. 즉, 여러 개의 이벤트가 발생할 경우, 하나의 이벤트가 완료된 후, 다음 이벤트가 실행되는 형태로 진행됩니다. 그림1은 함수 호출 기반의 이벤트 모델을 나타낸 그림입니다. EVENT1는 하위 이벤트들인 EVENT2, EVENT3의 호출이 완료되어야만 종료되도록 구성되어 있습니다.





그림1 함수 기반 이벤트 처리 모델


이러한 모델은 이벤트들이 동기식으로 동작하기 때문에, 이벤트들간의 상호 작용이 많습니다. 그러나 단일 스레드로 이벤트를 처리할 수 없을 경우, 여러 개의 스레드를 생성해서 이벤트를 처리해야 합니다. 이 경우 스레드를 많이 생성할 수록 시스템 자원 사용량도 그만큼 증가하게 됩니다. 또한 둘 이상의 스레드가 이벤트를 통해 공통의 자원에 접근하는 경우, 프로그램 의도와 다른 결과를 초래할 수 있습니다. 그래서 이러한 경우를 대비하기 위해, 이벤트를 동기화(synchronized) 처리해야 합니다.



예를 들어 기존 맵리듀스의 태스크 트래커는 로컬 디스크를 초기화하고, HDFS에서 공통 정보를 로컬 디스크로 다운로드한 후에 개별 태스크를 실행합니다. 이때 반드시 각각의 단계가 완료되어야만, 다음 단계가 실행될 수 있습니다. 그리고 중요 이벤트의 경우 동기화(synchronized) 처리가 되어 있어서, 대부분 하나의 스레드 단위로 제어를 하게 됩니다.


기존 맵리듀스는 이러한 구조 때문에 안정적으로 이벤트를 처리할 수 있습니다. 하지만 대규모 맵리듀스 잡을 실행할 경우, 상당수의 스레드가 다음 단계의 이벤트가 진행될 때까지 대기해야만 합니다. 이러한 경우 대기 시간 뿐만 아니라 서버의 CPU, 메모리 같은 자원까지 함께 소모를 하게 됩니다. 결국 단일 클러스터가 수용할 수 있는 맵리듀스 잡과 태스크 개수에 제한을 주게 됩니다.


그럼 이제 얀은  안정적인 이벤트 처리와 성능 개선이라는 두마리 토끼를 잡고자, 어떠한 방식으로 이벤트를 처리하는 지 설명 드리겠습니다. 얀의 이벤트 처리를 이해하기 위해서는 우선 얀의 서비스 인터페이스에 대한 사전 지식이 필요합니다. 얀은 org.apache.hadoop.service 패키지에 Service(서비스) 인터페이스를 제공합니다. 서비스 인터페이스는 다음과 같은 네 개의 상태를 유지하며, 각 상태에 따른 메소드가 호출됩니다.


  • NOTINITED: 서비스가 생성됐지만, 초기화되지 않은 상태

  • INITED: 서비스 초기화 상태

  • STARTED: 서비스 시작 상태

  • STOPPED: 서비스 종료 상태


얀은 서비스 인터페이스를 구현한 AbstractService라는 추상화 클래스를 제공하며, 이 클래스는 하나의 서비스 상태를 제어할 수 있습니다. 그리고 AbstractService를 상속받아서 구현한 CompositeService도 함께 제공하는데, CompositeService는 여러 개의 서비스 상태를 제어할 수 있습니다. 참고로 리소스 매니저, 노드 매니저등은 CompositeService를 상속받아서 구현됐으며, 앞으로 설명 드릴 이벤트 스케쥴와 어플리케이션 마스터용 클래스들은 AbstractService를 상속받아서 구현되어 있습니다.


그럼 본격적으로 얀의 이벤트 처리 모델을 설명 하겠습니다. 얀은 Event-driven concurrency model (이벤트 드리븐 동시성 모델)을 이벤트 처리 아키텍처로 선택했습니다. 이벤트 드리븐 동시성 모델은 하나의 스레드가 이벤트를 처리하는 형태의 구조입니다. 하나의 스레드는 요청되는 이벤트를 큐에 저장했다가, 해당 이벤트의 실행을 적절한 이벤트 핸들러에 위임합니다. 이벤트 핸들러는 이벤트 처리를 추상화한 클래스로, 이벤트 타입에 따라서 이벤트 로직을 수행하게 됩니다. 단일 스레드가 이벤트 결과를 즉시 반환하는 것이 아니라, 각각의 이벤트 핸들러들이 이벤트 수행을 종료했을 때 결과를 전달하는 비동기 방식으로 이벤트를 처리하게 됩니다. 이러한 이벤트 처리 모델은 얀 외에도 Node.js, 루비의 EventMachine, 펄의 POE에서도 적용하고 있습니다. 그럼 얀에서 이 모델이 어떻게 구현되었는지 설명하겠습니다. 그림2는 얀의 이벤트 처리 모델을 나타내는 그림입니다.






그림2 YARN 이벤트 처리 모델


얀은 이벤트를 제어하기 위한 단일 스레도로 AsyncDispacher(비동기 디스패처)를 사용합니다.

비동기 디스패처는 시스템에서 요청하는 이벤트를 큐(LinkedBlockingQueue)에 저장합니다. 이때 eventHandlingThread라는 내부 스레드가 큐에 저장된 이벤트를 처리하기 위한 해당 이벤트 핸들러를 검색합니다. 이벤트 타입과 일치하는 이벤트 핸들러가 검색되면, 해당 이벤트 핸들러에게 이벤트를 위임하고, 이벤트 핸들러가 실제 이벤트 관련 로직을 수행합니다.


그리고 얀은 주요 컴포넌트들의 상태 처리와 상태 변화에 따른 로직의 처리를 StateMachine으로 하게 됩니다. 이때 상태 변화에 따라서 다른 이벤트를 호출할 수도 있습니다. StateMachine은 이후에 자세히 설명하는 시간을 갖겠습니다. 마지막으로 최종 결과는 비동기 디스패처가 비동기 이벤트 형태로 출력합니다.


리소스 매니저, 노드 매니저, MRAppMaster(맵리듀스 잡의 어플리케이션 마스터)와 같은 얀의 주요 데몬들은 내부적으로 비동기 디스패처를 생성해서 이벤트를 사전 등록하고, 처리하게 됩니다.  

이렇게 중요 컴포넌트들의 이벤트를 다루고 있기 때문에, 비동기 디스패처를 중앙 이벤트 핸들러라고 부르기도 합니다.


참고로 아래 소스는 리소스 매니저에서 비동기 디스패처를 생성하고, 이벤트를 등록하는 내용입니다.


private Dispatcher rmDispatcher;


@Override

protected void serviceInit(Configuration conf) throws Exception {

this.rmDispatcher = createDispatcher();



// NodesListManager(노드리스트매니저)를 위한 이벤트 핸들러 등록

this.nodesListManager = new NodesListManager(this.rmContext);

   this.rmDispatcher.register(NodesListManagerEventType.class,

       this.nodesListManager);

}


// 비동기 디스패처 생성

protected Dispatcher createDispatcher() {

 return new AsyncDispatcher();

}



* 참고문헌

http://www.applicationarchitected.com/2013/10/yarn-resourcemanager.html

http://book.51cto.com/art/201312/422053.htm

http://book.51cto.com/art/201312/422056.htm

http://soft.vub.ac.be/~tvcutsem/invokedynamic/presentations/eda.pdf



저작자 표시 비영리 변경 금지
신고
댓글
댓글쓰기 폼