YARN的AsyncDispatcher学习

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);
        }
      }
    }
  }

}

  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值