Hadoop源码解析之YARN的服务库与事件库
参考:
http://www.cnblogs.com/smartloli/p/4669968.html
1. YARN服务库
对于生命周期较长的对象,YARN使用基于服务的对象模型进行管理,主要特点如下:
1. 用于被服务化的对象包含4个状态,他们分别是:被创建、已初始化、已启动和已停止。
2. 任何服务状态变化都可以触发另外一些动作。
3. 通过组合方式对任意服务进行组合,以便进行统一管理。
YARN中的所有对象,如果是组合服务,需要继承CompositeService类,比如ResourceManager和NodeManager。
非组合服务,直接继承AbstractService类即可。
2. 事件库
YARN采用基于事件驱动的并发模型,其核心服务其本质就是一个中央异步调度器,包含有ResourceManager、 NodeManager、MRAppMaster等内容,YARN 事件与事件处理器的关系在 org.apache.hadoop.yarn.event 中。
在使用YARN 事件库的时候,需要先定义一个中央异步调度器AsyncDispatcher,它负责事件的处理与转发,然后我们根据实际业务需求定义一系列事件Event 与事件处理器EventHandler,并将事件注册到中央异步调度器中用于完成事件统一管理和应用调度。流程如下图所示:
图1 事件与事件处理器
3.YARN服务库和事件库的使用方法
为了说明YARN服务库和事件库的使用方法,举例如下,该例子可以看做是ApplicationMaster的简化版。
3.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
}
3.2 定义Job事件
public class JobEvent extends AbstractEvent<JobEventType> {
private String jobID ;
public JobEvent(String jobID , JobEventTypetype){
super(type) ;
this.jobID = jobID ;
}
public String getJobID(){
return this.jobID ;
}
}
其中,Job事件类型定义如下:
public enum JobEventType {
JOB_KILL ,
JOB_INIT ,
JOB_START
}
3.3事件调度器。
接下来定义一个中央异步调度器,它接收Job和Task两种类型事件,并交给对应的事件处理器处理。
public class SimpleMRAppMaster extends CompositeService{
//注意,继承的CompositeService类是protected,需要修改为Public或者放在同一个包里。
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 allthe tasks");
for(int i=0;i<taskNumber;i++){
dispatcher.getEventHandler().handle(newTaskEvent(taskIDs[i],TaskEventType.T_KILL)) ;
}
}else if(event.getType() == JobEventType.JOB_INIT){
System.out.println("Receive JOB_INIT event, schedulingtasks") ;
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());
}
}
}
}
3.4 测试程序
public class SimpleMRAppMasterTest {
public static void main(Stringargs[]) throws Exception{
String jobID = "job_20170112_11 " ;
SimpleMRAppMaster appMaster= new SimpleMRAppMaster("Simple MRAppMaster" , jobID , 5) ;
YarnConfiguration conf = new YarnConfiguration(new Configuration()) ;
appMaster.serviceInit(conf) ;
appMaster.init(conf) ;
appMaster.start() ;
appMaster.getDispatcher().getEventHandler().handle(new JobEvent(jobID,JobEventType.JOB_KILL)) ;
appMaster.getDispatcher().getEventHandler().handle(new JobEvent(jobID,JobEventType.JOB_INIT)) ;
}
}
解释一下程序:
主函数中
appMaster.getDispatcher().getEventHandler().handle(new JobEvent(jobID,JobEventType.JOB_KILL)) ;
appMaster.getDispatcher().getEventHandler().handle(new JobEvent(jobID,JobEventType.JOB_INIT)) ;
表示往中央异步处理器放入了两个JobEventType类型的事件JobEventType.JOB_KILL和JobEventType.JOB_INIT。
中央异步处理器根据注册情况即可知晓什么类型的事件发往什么类型的调度器
//分别注册Job和Task事件调度器
dispatcher.register(JobEventType.class, new JobEventDispatcher());//JobEventType类型的事件发往JobEventDispatcher调度器
dispatcher.register(TaskEventType.class, new TaskEventDispatcher());//TaskEventType类型的事件发往TaskEventDispatcher调度器
JobEventType.JOB_KILL和JobEventType.JOB_INIT都是JobEventType类型的事件,调用JobEventDispatcher的handler方法,该方法根据事件类型,往中央异步调度器添加类型为TaskEventType类型的事件TaskEventType.T_KILL和TaskEventType.T_SCHEDULE。
中央异步处理器将事件TaskEventType.T_KILL和TaskEventType.T_SCHEDULE发往 TaskEventDispatcher,调用该调度器的handler方法进行处理。