服务库
对于生命周期较长的对象, YARN 采用了基于服务的对象管理模型对其进行管理, 该模型主要有以下几个特点。
YARN 中关于服务模型的类图(位于包 org.apache.hadoop.service 中) 如图所示:
事件库
YARN 采用了基于事件驱动的并发模型, 该模型能够大大增强并发性, 从而提高系统整体性能。 为了构建该模型, YARN 将各种处理逻辑抽象成事件和对应事件调度器, 并将每类事件的处理过程分割成多个步骤, 用有限状态机表示。 YARN 中的事件处理模型可概括为图所示。
整个处理过程大致为:处理请求会作为事件进入系统,由中央异步调度器(AsyncDispatcher)负责传递给相应事件调度器(Event Handler)。该事件调度器可能将该事件转发给另外一个事件调度器,也可能交给一个带有有限状态机的事件处理器,其处理结果也以事件的形式输出给中央异步调度器。而新的事件会再次被中央异步调度器转发给下一个事件调度器,直至处理完成(达到终止条件)。
在 YARN 中,所有核心服务实际上都是一个中央异步调度器,包括 ResourceManager、NodeManager、 MRAppMaster(MapReduce 应用程序的 ApplicationMaster)等,它们维护了事先注册的事件与事件处理器,并根据接收的事件类型驱动服务的运行.YARN 中事件与事件处理器类的关系(位于包 org.apache.hadoop.yarn.event 中)如图所示。
YARN 服务库和事件库的使用方法
为了说明 YARN 服务库和事件库的使用方法, 本小节介绍一个简单的实例, 该实例可看做 MapReduce ApplicationMaster(MRAppMaster) 的简化版。该例子涉及任务和作业两种对象的事件以及一个中央异步调度器。 步骤如下。
1) 定义 Task 事件。
public class TaskEvent extends AbstractEvent<TaskEventType> {
private String taskID; //Task ID
public TaskEvent(String taskID, TaskEventType type) {
super(type);
this.taskID = taskID;
}
public String getTaskID() {
return taskID;
}
其中, Task 事件类型定义如下:
public enum TaskEventType {
T_KILL,
T_SCHEDULE
}
2) 定义 Job 事件。
public class JobEvent extends AbstractEvent<JobEventType> {
private String jobID;
public JobEvent(String jobID, JobEventType type) {
super(type);
this.jobID = jobID;
}
public String getJobId() {
return jobID;
}
}
其中, Job 事件类型定义如下:
public enum JobEventType {
JOB_KILL,
JOB_INIT,
JOB_START
}
3) 事件调度器。
接下来定义一个中央异步调度器, 它接收 Job 和 Task 两种类型事件, 并交给对应的事
件处理器处理, 代码如下:
@SuppressWarnings("unchecked")
public class SimpleMRAppMaster extends CompositeService {
private Dispatcher dispatcher; // 中央异步调度器
private String jobID;
private int taskNumber; // 该作业包含的任务数目
private String[] taskIDs; // 该作业内部包含的所有任务
public SimpleMRAppMaster(String name, String jobID, int taskNumber) {
super(name);
this.jobID = jobID;
this.taskNumber = taskNumber;
taskIDs = new String[taskNumber];
for(int i = 0; i < taskNumber; i++) {
taskIDs[i] = new String(jobID + "_task_" + i);
}
}
public void serviceInit(final Configuration conf) throws Exception {
dispatcher = new AsyncDispatcher();// 定义一个中央异步调度器
// 分别注册 Job 和 Task 事件调度器
dispatcher.register(JobEventType.class, new JobEventDispatcher());
dispatcher.register(TaskEventType.class, new TaskEventDispatcher());
addService((Service) dispatcher);
super.serviceInit(conf);
}
public Dispatcher getDispatcher() {
return dispatcher;
}
private class JobEventDispatcher implements EventHandler<JobEvent> {
@Override
public void handle(JobEvent event) {
if(event.getType() == JobEventType.JOB_KILL) {
System.out.println("Receive JOB_KILL event, killing all the tasks");
for(int i = 0; i < taskNumber; i++) {
dispatcher.getEventHandler().handle(new TaskEvent(taskIDs[i],
TaskEventType.T_KILL));
}
} else if(event.getType() == JobEventType.JOB_INIT) {
System.out.println("Receive JOB_INIT event, scheduling tasks");
for(int i = 0; i < taskNumber; i++) {
dispatcher.getEventHandler().handle(new TaskEvent(taskIDs[i],
TaskEventType.T_SCHEDULE));
}
}
}
}
private class TaskEventDispatcher implements EventHandler<TaskEvent> {
@Override
public void handle(TaskEvent event) {
if(event.getType() == TaskEventType.T_KILL) {
System.out.println("Receive T_KILL event of task " + event.getTaskID());
} else if(event.getType() == TaskEventType.T_SCHEDULE) {
System.out.println("Receive T_SCHEDULE event of task " + event.getTaskID());
}
}
}
}
4) 测试程序。
@SuppressWarnings("unchecked")
public class SimpleMRAppMasterTest {
public static void main(String[] args) throws Exception {
String jobID = "job_20131215_12";
SimpleMRAppMaster appMaster = new SimpleMRAppMaster("Simple MRAppMaster", jobID, 5);
YarnConfiguration conf = new YarnConfiguration(new Configuration());
appMaster.serviceInit(conf);
appMaster.serviceStart();
appMaster.getDispatcher().getEventHandler().handle(new JobEvent(jobID,
JobEventType.JOB_KILL));
appMaster.getDispatcher().getEventHandler().handle(new JobEvent(jobID,
JobEventType.JOB_INIT));
}