首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Hadoop YARN架构设计要点(5)

Hadoop YARN架构设计要点(5)

状态机
我们以RM端管理的RMAppImpl对象为例,它表示一个Application运行过程中,在RM端的所维护的Application的状态,该对象对应的所有状态及其状态转移路径,如下图所示:


在上图中如果加上触发状态转移的事件及其类型,可能整个图会显得很乱,所以这里,我详细画了一个分图,用来说明,每一个状态的变化都是有哪种类型的事件触发的,根据这个图,可以方便地阅读源码,如下图所示:


NMLivelinessMonitor源码分析实例
YARN主要采用了Dispatcher+EventHandler+Service这样的抽象,将所有的内部/外部组件采用这种机制来实现,由于存在很多的Service和EventHandler,而且有的组件可能既是一个Service,同时还是一个EventHandler,所以在阅读代码的时候可能会感觉迷茫,这里我给出了一个阅读NMLivelinessMonitor服务的实例,仅供想研究源码的人参考。
NMLivelinessMonitor是ResourceManager端的一个监控服务实现,它主要是用来监控注册的节点的Liveliness状态,这里是监控NodeManager的状态。该服务会周期性地检查NodeManager的心跳信息来确保注册到ResourceManager的NodeManager当前处于活跃状态,可以执行资源分配以及处理计算任务,在NMLivelinessMonitor类继承的抽象泛型类AbstractLivelinessMonitor中有一个Map,如下所示:
private Map<O, Long> running = new HashMap<O, Long>();

这里面O被替换成了NodeId,而值类型Long表示时间戳,也就是表达了一个NodeManager向ResourceManager最后发送心跳信息时间戳,通过检测running中的时间戳;来判断NodeManager是否可以正常使用。


在ResourceManager中可以看到,NMLivelinessMonitor的实例是其一个成员:
protected NMLivelinessMonitor nmLivelinessMonitor;



看一下NMLivelinessMonitor类的实现,它继承自抽象泛型类AbstractLivelinessMonitor,看NMLivelinessMonitor类的声明:
View Code

在类实现中,有一个重写(@Override)的protected的方法expire,如下所示:


View Code



我们可以通过该类NMLivelinessMonitor抽象基类中看到调用expire方法的逻辑,是在一个内部线程类PingChecker中,代码如下所示:
View Code



这里面的泛型O在NMLivelinessMonitor类中就是NodeId,所以最关心的逻辑就是前面提到的NMLivelinessMonitor中的expire方法的实现。在expire方法中,调用了dispatcher的handle方法来处理,所以dispatcher应该是一个EventHandler对象,后面我们会看到,它其实是通过ResourceManager中的dispatcher成员,也就是AsyncDispatcher来获取到的(AsyncDispatcher内部有一个组合而成的EventHandler)。
下面,我们接着看NMLivelinessMonitor是如何创建的,在ResourceManager.RMActiveServices类的serviceInit()方法中,代码如下所示:
View Code



跟踪代码继续看createNMLivelinessMonitor方法,如下所示:
View Code



上面通过rmContext的getDispatcher获取到一个Dispatcher对象,来作为NMLivelinessMonitor构造方法的参数,我们需要看一下这个Dispatcher是如何创建的,查看ResourceManager.serviceInit方法,代码如下所示:
View Code



继续跟踪代码,setupDispatcher()方法实现如下所示:
View Code



继续看createDispatcher()方法代码实现:
View Code



可以看到,在这里创建了一个AsyncDispatcher对象在创建的NMLivelinessMonitor实例中包含一个AsyncDispatcher实例。回到前面,我们需要知道这个AsyncDispatcher调用getEventHandler()返回的EventHandler的处理逻辑是如何的,NMLivelinessMonitor的代码实现如下所示:
View Code
查看AsyncDispatcher类的getEventHandler()方法,代码如下所示:
View Code



可见,这里面无论是第一次调用还是其他对象已经调用过该方法,这里面最终只有一个GenericEventHandler实例作为这个dispatcher的内部EventHandler实例,所以继续跟踪代码,看GenericEventHandler实现,如下所示:
View Code



将传入handle方法的Event丢进了eventQueue队列,也就是说GenericEventHandler是基于eventQueue的一个生产者,那么消费者是AsyncDispatcher内部的另一个线程,如下所示:
View Code

查看createThread()方法,如下所示:
View Code
可以看到,从eventQueue队列中取出Event,然后调用dispatch(event);来处理事件,看dispatch(event)方法,如下所示:



View Code
可以看到,根据已经注册的Map<Class, EventHandler> eventDispatchers表,选择对应的EventHandler来执行实际的事件处理逻辑。这里,再看看这个EventHandler是在哪里住的。前面已经看到,NMLivelinessMonitor类的expire方法中,传入的是new RMNodeEvent(id, RMNodeEventType.EXPIRE),我们再查看ResourceManager.RMActiveServices.serviceInit()方法:
View Code



可见RMNodeEventType类型的事件是使用ResourceManager.NodeEventDispatcher这个EventHandler来处理的,同时它也是一个Dispatcher,现在再看NodeEventDispatcher的实现:
View Code
这个里面还没有真正地去处理,而是基于RMNode状态机对象来进行转移处理,所以我们继续看RMNode的实现RMNodeImpl,因为前面事件类型RMNodeEventType.EXPIRE,我们看状态机创建时对该事件类型的转移动作是如何注册的:



View Code



在ResourceManager端维护的NodeManager的信息使用RMNodeImpl来表示(在内存中保存ConcurrentMap),所以当前如果expire方法被调用,RMNodeImpl会根据状态机对象中已经注册的前置转移状态(pre-transition state)、后置转移状态(post-transition state)、事件类型(event type)、转移Hook程序,来对事件进行处理,并使当前RMNodeImpl的状态由前置转移状态更新为后置转移状态。
对于上面代码,如果当前RMNodeImpl状态是NodeState.RUNNING,事件为RMNodeEventType.EXPIRE类型,则会调用Hook程序实现DeactivateNodeTransition,状态更新为NodeState.LOST;如果当前RMNodeImpl状态是NodeState.UNHEALTHY,事件为RMNodeEventType.EXPIRE类型,则会调用Hook程序实现DeactivateNodeTransition,状态更新为NodeState.LOST。具体地,每个Transition的处理逻辑如何,可以查看对应的Transition实现代码。
返回列表