먼저 전반적인 흐름에 대해 알아보고, 각 단계별 동작 방식에 대해 알아보도록 하자. 전반적인 흐름은 다음과 같다.
2a. 리소스 매니저 : 노드 매니저에게 어플리케이션 마스터 실행 요청
2b. 노드 매니저 : 컨테이너에서 어플리케이션 마스터 실행
4a. 어플리케이션 마스터 : 할당받은 노드 매니저들에게 컨테이너 실행 요청
4b. 노드 매니저 : 컨테이너에 새로운 JVM 생성, 어플리케이션 실행
이번에는 각 컴포넌트 간 어떠한 상호작용이 발생하는지에 대해 알아보자.
위의 전반적인 흐름에서 클라이언트가 리소스 매니저에게 어플리케이션 실행을 요청하는 단계다.
(1 : submit YARN application 부분)
클라이언트가 어플리케이션을 얀 클러스터에서 실행하려면, 신규 어플리케이션 ID를 발급받아야 한다.
createNewApplication
메소드를 호출해 어플리케이션 ID 발급을 요청리소스 매니저 : 신규 어플리케이션 ID, 리소스 정보 설정되어있는 GetNewApplicationResponse
객체 반환
클라이언트 : 어플리케이션 ID가 정상적으로 반환되었는지 확인
submitApplication
메소드 호출클라이언트 : 리소스 매니저에게 getApplicationReport
요청
리소스 매니저 : 어플리케이션이 정상적으로 등록되었을 경우 ApplicationReport
반환
리소스 매니저가 노드 매니저에게 어플리케이션 마스터 실행을 요청하고 실행하는 단계다.
(2a : start container, 2b : launch 부분)
ApplicationAttemptId
생성ApplicationAttemptId
등록RMAppAttemptEventType.ATTEMPT_ADDED
이벤트 발생ApplicationAttemptId
에 대한 컨테이너 할당 요청ApplicationAttemptId
에게 컨테이너 할당RMContainerEventType.START
이벤트 발생ApplicationMasterLauncher
실행AMLauncher
실행해 어플리케이션 마스터 실행AMLauncher
가 요청한 컨테이너 실행StartContinersResponse
반환리소스 매니저는 클러스터 내 실행되는 여러 어플리케이션 마스터에게 자원 할당하고 상태를 모니터링한다.
따라서 어플리케이션 마스터가 실행되면 리소스 매니저에 등록되어야 한다.
(3: allocate resources 부분)
registerApplicationMaster
메소드 호출해 어플리케이션 마스터 등록 요청AllocateResponse
객체 반환allocate
메소드 호출해 어플리케이션 실행하는 데 필요한 리소스 할당 요청어플리케이션 마스터는 자신이 할당받은 컨테이너에서 어플리케이션을 실행한다.
(4a: start container, 4b: launch 부분)
startContainer
메소드 통해 노드 매니저에게 컨테이너 실행 요청StartContainersResponse
객체 반환getContainerStatus
주기적으로 호출해 컨테이너 실행 상태 확인GetContainerStatusesResponses
객체 통해 반환보조 서비스는 노드매니저 간의 서비스 제어를 위한 기능이다.
이러한 서비스를 이용해 서로 다른 노드 매니저 사이에 데이터를 전달하거나 다른 노드 매니저를 제어할 수 있다.
보조 서비스 설정은 다음과 같이 진행하면 된다.
<?xml vesrsion="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>yarn.nodemanager.aux-service</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce_shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
</configuration>
얀의 capacity scheduler는 계층적인 큐 형식으로 리소스를 정의한다.
capacity scheduler는 리소스에 여유가 있을 경우 큐에 설정된 자원보다 더 많은 자원을 사용할 수 있다.
하지만 리소스에 여유가 없는 경우 다른 큐에서 실행 중인 어플리케이션이 종료될 때까지 대기해야한다.
이처럼 자원을 공평하게 할당받지 못하는 상황에서, 다른 어플리케이션의 자원을 회수할 수 있는 기능을 프리엠션이라고 한다.
프리엠션의 호출 방식에 대해 알아보자.
리소스 매니저 : 프리엠션 구현 클래스를 SchedulingMonitor
에 등록
SchedulingMonitor
getMonitorInterval
메소드 호출 editSchedule
메소드 호출SchedulingEditPolicy : editSchedult
메소드에 구현된 프리엠션 실행
타임라인 서비스는 얀 클러스터에서 실행되는 어플리케이션의 히스토리 상태, 메트릭 정보를 유지하기 위한 서비스다.
타임라인 서비스 아키텍쳐는 다음과 같다.
얀이 동작할 때에 내부적으로 다양한 이벤트가 발생한다.
얀은 효율적인 이벤트를 처리하기 위해 비동기 디스패처와 스테이트 머신 모델을 제공한다.
얀은 비동기 방식으로 이벤트를 처리하며, 이를 지원하기 위한 비동기 디스패처를 제공한다.
비동기 디스패처는 싱글 스레드 기반으로 동작하여 속도가 빠르고 시스템 자원을 적게 소모한다.
다음은 비동기 디스패처의 동작 과정이다.
클라이언트 : 비동기 디스패처의 handle
메소드 호출해 이벤트 처리 요청
비동기 디스패처 : eventHandlingThread
로 이벤트 요청 처리, 싱글 스레드로 실행
eventHandlingThread : handle
메소드 호출해 이벤트 처리 클래스에게 이벤트 요청 전달
이벤트 핸들러 : 요청받은 handle
메소드에 정의된 로직 실행
리소스 매니저와 노드 매니저의 내부 컴포넌트들은 상태 정보가 다양하게 변경된다.
얀은 상태 변경을 효율적으로 처리하기 위해 스테이트 머신 모델을 제공한다.
스테이트 머신 모델은 상태 변경을 자동으로 인지하고 관련된 로직을 처리할 수 있다.
또한 잘못된 상태 전환이 발생했을 때 자동으로 장애 처리가 가능하다.
다음은 스테이트 머신 모델의 동작 과정이다.
ResourceTrackerService : 노드 매니저가 하트비트 전송하지 않으면 해당 노드 매니저 재부팅 요청
비동기 디스패처 : NodeEventDispatcher
의 handle
메소드 호출해 이벤트 처리 요청
NodeEventDispatcher : handle
메소드 호출해 이벤트 처리
RMNodeImpl : 스테이트 머신의 doTransition
메소드 호출해 상태 변경
RMNodeImpl : 리소스 매니저가 관리하는 노드 매니저 목록에서 삭제되기 위해
DeactivateNodeTransition
메소드는 NodesListManagerEventType.NODE_UNUSABLE
이벤트 요청
리소스 매니저와 노드 매니저는 다양한 내부 컴포넌트로 이루어져 있다.
이번에는 리소스 매니저와 노드 매니저의 구조에 대해 알아본다.
리소스 매니저는 전체 클러스터의 가용 리소스를 스케쥴링하고 어플리케이션들에게 리소스를 중재한다.
또한 노드 매니저와 어플리케이션 마스터를 제어하여 어플리케이션들이 정상적으로 실행될 수 있도록 한다.
아래 그림은 리소스 매니저의 컴포넌트 구성을 기능별로 분류한 그림이다.
주요 컴포넌트들만 살펴보자.
노드 매니저는 슬레이브 서버 역할을 하는 모든 서버에서 실행되어 컨테이너의 생명주기를 관리한다.
또한 노드 매니저가 실행되는 서버 자원을 모니터링하여 상태 정보를 리소스 매니저에게 전송한다.
아래 그림은 노드 매니저의 컴포넌트 구성을 기능별로 분류한 그림이다.
마찬가지로 주요 컴포넌트만 살펴보자.