摘要
本文详细描述RMAppAttempt状态机内的状态与其转换关系,分析的代码基于Apache社区Hadoop最新的2.3.0版本。
RMAppAttempt状态机
在RM中,一个RMApp可能对于一到多个RMAppAttempt,即假如RMApp的第一个RMAppAttempt失败后,RM会根据配置启动新的RMAppAttempt。
RMAppAttempt内部维护了进度,运行的机器信息,起始时间,URL等信息。其中最复杂的信息是RMAppAttempt的状态机信息。
private static final StateMachineFactory<RMAppAttemptImpl, RMAppAttemptState, RMAppAttemptEventType, RMAppAttemptEvent> stateMachineFactory = new StateMachineFactory<RMAppAttemptImpl, RMAppAttemptState, RMAppAttemptEventType, RMAppAttemptEvent>(RMAppAttemptState.NEW) // Transitions from NEW State .addTransition(RMAppAttemptState.NEW, RMAppAttemptState.SUBMITTED, RMAppAttemptEventType.START, new AttemptStartedTransition())
图1 RMAppAttempt状态机
RMAppAttempt状态与转换解释
这里讨论的重点在于用户提交App后RM正常的处理流程,时先不讨论RECOVERY部分,因为其状态转换原理是相同的,可以自行查看代码分析。
NEW,
和RMApp的状态机一样,RMAppAttempt的初始状态也是NEW。
在RMApp由NEW_SAVING转换为RMAppState.SUBMITTED时,RMApp会创建RMAppAttemptImpl对象,这时RMAppAttempt状态为NEW。
SUBMITTED,
表示RMAppAttempt已经创建,并准备给调度器。
在RMApp创建RMAppAttempt时会创建一个RMAppAttemptEventType.START事件,交给处理器,RMAppAttempt在NEW的状态下遇到RMAppAttemptEventType.START事件时,转化为SUBMITTED状态,并调用AttemptStartedTransition。
SCHEDULED,
表示该RMAppAttempt已经交给调度器,做好了调度的准备。
AttemptStartedTransition中,RMAppAttempt会创建AppAttemptAddedSchedulerEvent事件,该事件最终会传递给调度器;调度器把相应的RMAppAttempt放到待调度的组中,然后创建RMAppAttemptEventType.APP_ACCEPTED事件,这个事件会使RMAppAttempt调用ScheduleTransition,在ScheduleTransition中,根据该App是否为UnmanagedAM(AM是否被RM管理,UnmanagedAM由客户端负责启动,然后向RM注册;managedAM由RM命令NM启动,并负责该AM的生命周期)决定返回LAUNCHED_UNMANAGED_SAVING或SCHEDULED状态,如果是managedAM(大多数情况)返回SCHEDULED,否则返回LAUNCHED_UNMANAGED_SAVING状态。
ALLOCATED_SAVING,
表示正在保存RMAppAttemptImpl信息到RMStateStore中。
当某个NM(NodeManager)发送心跳到RM,RM会给改RM分配相应的container,这时候会创建RMContainerEventType.START事件,在RMContainerImpl状态机(后续将会介绍)遇到这个事件时会调用ContainerStartedTransition,在其转换方法中会创建RMAppAttemptEventType.CONTAINER_ALLOCATED事件,而RMAppAttemptImpl(SCHEDULED状态)遇到SCHEDULED事件后会调用AMContainerAllocatedTransition,这时会把RMAppAttemptImpl信息存储到制定的存储器中。RMAppAttempt状态转换为ALLOCATED_SAVING。
ALLOCATED,
表示RMAppAttempt已经完成调度到某台NM上的工作。
当RMStateStore完成RMAppAttemptImpl信息的存储后,会创建RMAppAttemptEventType.ATTEMPT_NEW_SAVED事件,RMAppAttemptImpl遇到此事件后会调用AttemptStoredTransition,检查存储是否出错,并创建AMLauncherEventType.LAUNCH事件,然后把状态转换为ALLOCATED。
LAUNCHED,
表示RM已经发送命令让某台NM启动相应的AM。
在AMLauncher中,处理AMLauncherEventType.LAUNCH事件,实际的方法lanch()方法中,AM首先连接上相应的NM,然后通过相应的协议让NM启动AM。完成后生成RMAppAttemptEventType.LAUNCHED事件。RMAppAttemptImpl处理此事件,调用AMLaunchedTransition,然后转换状态为LAUNCHED。
RUNNING,
AM成功向RM注册后的状态。
AM启动后会向RM注册,注册的时候RM会生成RMAppAttemptEventType.REGISTERED事件,RMAppAttemptImpl处理这个事件,调用AMRegisteredTransition,获取AM的host,port,URL等信息,创建RMAppEventType.ATTEMPT_REGISTERED事件,然后把RMAppAttemptImpl状态转换为RUNNING。
LAUNCHED_UNMANAGED_SAVING,
Unmanaged AM正在保存状态,见SCHEDULED状态。
FINAL_SAVING,
表示正在保存RMAppAttemptImpl的最终信息。
这个状态类似于RMApp的FINAL_SAVING状态,即为了保证存RMAppAttemptImpl信息,在转换为FINISHED,FAILED,FINISHING,KILLED前增加这个状态,在转换为FINAL_SAVING前,需要保存RMAppAttemptImpl的 targetedFinalState状态,在RMStateStore完成相应存储后根据targetedFinalState转化为后续的状态。
FINISHING,
表示RMAppAttemptImpl正在结束。
遇到RMAppAttemptEventType.EXPIRE或AM的RMAppAttemptEventType.CONTAINER_FINISHED事件时,RMAppAttemptImpl状态转换为FINISHED
FINISHED,
表示RMAppAttemptImpl已经结束。
只有AM主动汇报自己结束的RMAppAttempt才会标识为FINISHED状态。
FAILED,
表示RMAppAttemptImpl已经失败。
失败的情况比较多,这里不再一一介绍。
KILLED,
表示RMAppAttemptImpl已经被kill。
客户端发起KILL会导致RMAppAttemptImpl被KILL。