YARN采用了基于事件驱动的并发模型,该模型能极大的提高应用程序并发性,在RM中,几乎所有的事件都通过AsyncDispatcher进行事件的派发.
YARN中AsyncDispatcher的基本架构图如下:
从架构图可以看出,AsyncDispatcher负责event的接受并存在队列中,还可以根据event的类型将event分发给事件对应的handler。
从架构图还可以看出,该架构需要3个基本的要素:事件(Event),事件类型(EventType)和处理事件对应的处理器(Handler)。
在YARN common中,
事件类型(EventType)就是枚举类,例如RMNodeEventType:
public enum RMNodeEventType {
STARTED,
// Source: AdminService
DECOMMISSION,
// ResourceTrackerService
STATUS_UPDATE,
REBOOTING,
RECONNECTED,
// Source: Application
CLEANUP_APP,
// Source: Container
CONTAINER_ALLOCATED,
CLEANUP_CONTAINER,
// Source: NMLivelinessMonitor
EXPIRE
}
事件(Event)被定义如下:
public interface Event<TYPE extends Enum<TYPE>> {
TYPE getType();
long getTimestamp();
String toString();
}
其中,TYPE就是事件类型。
例如RMNodeEvent事件,继承了事件类型RMNodeEventType:
public class RMNodeEvent extends AbstractEvent<RMNodeEventType> {
private final NodeId nodeId;
public RMNodeEvent(NodeId nodeId, RMNodeEventType type) {
super(type);
this.nodeId = nodeId;
}
public NodeId getNodeId() {
return this.nodeId;
}
}
事件处理器(Handler)
处理事件类型T的EventHandler接口:
public interface EventHandler<T extends Event> {
void handle(T event);
}
例如RMNodeImpl实现了EventHandler接口,并实现其handle方法:
public class RMNodeImpl implements RMNode, EventHandler<RMNodeEvent> {
...
public void handle(RMNodeEvent event) {
LOG.debug("Processing " + event.getNodeId() + " of type " + event.getType());
try {
writeLock.lock();
NodeState oldState = getState();
try {
stateMachine.doTransition(event.getType(), event);
} catch (InvalidStateTransitonException e) {
LOG.error("Can't handle this event at current state", e);
LOG.error("Invalid event " + event.getType() + " on Node " + this.nodeId);
}
if (oldState != getState()) {
LOG.info(nodeId + " Node Transitioned from " + oldState + " to " + getState());
}
} finally {
writeLock.unlock();
}
}
...
}
handle方法根据RM Node的某种(event.getType())事件,修改Node的状态。
接下来,学习Dispatcher和event的联系。
Dispatcher通过不同的事件类型(EventType)找到相应的handler对事件(event)进行处理。
Dispatcher接口作为event分发接口,它根据event的类型将不同event分发给已经注册的event处理器handler,其代码如下:
public interface Dispatcher {
EventHandler getEventHandler();
void register(Class<? extends Enum> eventType, EventHandler handler);
}
其中,dispatcher有两个基本的方法:register()和getEventHandler()。
register() 用于在AsyncDispatcher使用之前就需要先注册eventType和对应的EventHandler
getEventHandler()方法主要则是把事件(event)放入eventQueue中。
接下来看看这两个方法是如何在AsyncDispatcher类中实现的,Dispatcher接口只有一个实现类,就是AsyncDispatcher类:
public class AsyncDispatcher extends AbstractService implements Dispatcher {
// 阻塞队列, 用于存放所有的事件event
private final BlockingQueue<Event> eventQueue;
private volatile boolean stopped = false;
// 事件处理线程
private Thread eventHandlingThread;
// 事件->事件处理器Map:
// 记录了事件event和事件处理器handler之间的关系
// 在调用register()方法的时候,会将事件event和事件处理器handler存入map
protected final Map<Class<? extends Enum>, EventHandler> eventDispatchers;
private boolean exitOnDispatchException;
public AsyncDispatcher() {
this(new LinkedBlockingQueue<Event>());
}
public AsyncDispatcher(BlockingQueue<Event> eventQueue) {
super("Dispatcher");
this.eventQueue = eventQueue;
this.eventDispatchers = new HashMap<Class<? extends Enum>, EventHandler>();
}
// 启动service
@Override
protected void serviceStart() throws Exception {
//start all the components
super.serviceStart();
// 调用createThread(), 创建一个新的线程,
// 该线程从事件队列中取事件,然后分发事件
eventHandlingThread = new Thread(createThread());
eventHandlingThread.setName("AsyncDispatcher event handler");
eventHandlingThread.start();
}
// 事件分发线程
// 该线程从事件队列中取事件,然后分发事件
Runnable createThread() {
return new Runnable() {
@Override
public void run() {
while (!stopped && !Thread.currentThread().isInterrupted()) {
Event event;
try {
// 取事件
event = eventQueue.take();
} catch(InterruptedException ie) {
if (!stopped) {
LOG.warn("AsyncDispatcher thread interrupted", ie);
}
return;
}
if (event != null) {
// 调用dispatch(),分发事件event
dispatch(event);
}
}
}
};
}
@SuppressWarnings("unchecked")
protected void dispatch(Event event) {
//all events go thru this loop
Class<? extends Enum> type = event.getType().getDeclaringClass();
try{
// 根据事件类型从register注册的信息中获取处理器handler
EventHandler handler = eventDispatchers.get(type);
if(handler != null) {
// 调用handle()方法
handler.handle(event);
} else {
throw new Exception("No handler for registered for " + type);
}
}
catch (Throwable t) {
...
}
}
@SuppressWarnings("unchecked")
@Override
public void register(Class<? extends Enum> eventType,
EventHandler handler) {
// 检查事件是否已经注册过
EventHandler<Event> registeredHandler = (EventHandler<Event>) eventDispatchers.get(eventType);
LOG.info("Registering " + eventType + " for " + handler.getClass());
// 如果事件没有注册过,直接放入"事件->事件处理器Map"
// 如果已经注册过,按照其他逻辑处理
if (registeredHandler == null) {
eventDispatchers.put(eventType, handler);
} else if (!(registeredHandler instanceof MultiListenerHandler)){
/* for multiple listeners of an event add the multiple listener handler */
MultiListenerHandler multiHandler = new MultiListenerHandler();
multiHandler.addHandler(registeredHandler);
multiHandler.addHandler(handler);
eventDispatchers.put(eventType, multiHandler);
} else {
/* already a multilistener, just add to it */
MultiListenerHandler multiHandler
= (MultiListenerHandler) registeredHandler;
multiHandler.addHandler(handler);
}
}
// 该方法主要是将事件event放入事件队列eventQueue中,
// 具体实现在GenericEventHandler类中。
@Override
public EventHandler getEventHandler() {
return new GenericEventHandler();
}
// 将事件event放入事件队列eventQueue中
class GenericEventHandler implements EventHandler<Event> {
public void handle(Event event) {
/* all this method does is enqueue all the events onto the queue */
try {
// 将事件event放入事件队列eventQueue中
eventQueue.put(event);
} catch (InterruptedException e) {
...
}
};
}
/**
* Multiplexing an event. Sending it to different handlers that
* are interested in the event.
* @param <T> the type of event these multiple handlers are interested in.
*/
static class MultiListenerHandler implements EventHandler<Event> {
List<EventHandler<Event>> listofHandlers;
public MultiListenerHandler() {
listofHandlers = new ArrayList<EventHandler<Event>>();
}
@Override
public void handle(Event event) {
for (EventHandler<Event> handler: listofHandlers) {
handler.handle(event);
}
}
void addHandler(EventHandler<Event> handler) {
listofHandlers.add(handler);
}
}
}
需要仔细阅读上述代码,注释还算清晰。
接下来,针对RMNodeEvent事件,分析是如何注册register、分发dispatcher、处理handle的。
在ResourceManager类
public class ResourceManager extends CompositeService implements Recoverable {
// 1.定义分发器变量
private Dispatcher rmDispatcher;
@Override
protected void serviceInit(Configuration conf) throws Exception {
// 2.创建分发器,即AsyncDispatcher
this.rmDispatcher = new AsyncDispatcher();
addIfService(this.rmDispatcher);
// 3. 注册RMNodeEventType类型的事件到事件分发器NodeEventDispatcher
this.rmDispatcher.register(RMNodeEventType.class, new NodeEventDispatcher(this.rmContext));
}
// 4. 事件分发器NodeEventDispatcher实现了EventHandler接口,
// 并实现其handle()方法
public static final class NodeEventDispatcher implements EventHandler<RMNodeEvent> {
private final RMContext rmContext;
@Override
public void handle(RMNodeEvent event) {
NodeId nodeId = event.getNodeId();
RMNode node = this.rmContext.getRMNodes().get(nodeId);
if (node != null) {
try {
// 调用真实的handle()来处理, 这里就是RMNodeImpl的handle()方法
((EventHandler<RMNodeEvent>) node).handle(event);
} catch (Throwable t) {
LOG.error("Error in handling event type " + event.getType() + " for node " + nodeId, t);
}
}
}
}
}