Yarn系列(三)——AsyncDispatcher分析

1. 前言

基于Hadoop-3.2 。

1.1. 简介

AsyncDispatcher既是服务也是事件调度器(Eventhandler),如下AsyncDispatcher的定义:

public class AsyncDispatcher extends AbstractService implements Dispatcher {...}

作为服务其具备serviceStart()、serviceStop()等能力;作为事件调度器,其可以根据事件获取对应的事件调度器和其他事件调度器可以向AsyncDispatcher注册的功能。

1.2. 重要的数据结构

AsyncDispatcher有两个重要的属性,理解了两个属性作用,就基本上可以明白其工作原理。

private final BlockingQueue<Event> eventQueue;
......
protected final Map<Class<? extends Enum>, EventHandler> eventDispatchers;

eventQueue是阻塞对列,用于存放事件;eventDispatchers的key是事件类型,value放对应的事件处理器。所以整体流程大致是:事件被放入到阻塞对列中,事件和对应的事件handler注册到AsyncDispatcher,工作时就是从阻塞对列中取出事件,然后从eventDispatchers取得对应的事件处理器,然后执行handle()方法。

2. 源码分析

2.1. AsyncDispatcher服务启动

当服务启动时,会创建一个线程不断的从阻塞对列中取出事件,然后调用该事件对应的处理方法。

@Override
protected void serviceStart() throws Exception {
  //start all the components
  super.serviceStart();
  //创建异步线程用于调度事件
  eventHandlingThread = new Thread(createThread());
  eventHandlingThread.setName(dispatcherThreadName);
  eventHandlingThread.start();
}

创建的线程就是不断从阻塞对列中取出事件然后执行,如下:

Runnable createThread() {
  return new Runnable() {
    @Override
    public void run() {
      //服务没有被停止且线程没有被中断
      while (!stopped && !Thread.currentThread().isInterrupted()) {
        drained = eventQueue.isEmpty();
        // blockNewEvents is only set when dispatcher is draining to stop,
        // adding this check is to avoid the overhead of acquiring the lock
        // and calling notify every time in the normal run of the loop.
        //服务停止时将会阻止新事件放入阻塞对列中
        if (blockNewEvents) {
          synchronized (waitForDrained) {
            if (drained) {
              waitForDrained.notify();
            }
          }
        }
        Event event;
        try {
          //从对列中获取事件
          event = eventQueue.take();
        } catch(InterruptedException ie) {
          if (!stopped) {
            LOG.warn("AsyncDispatcher thread interrupted", ie);
          }
          return;
        }
        if (event != null) {
          //不为空则调度
          dispatch(event);
        }
      }
    }
  };
}

其调度的实现逻辑就是调用每个事件的Handle方法,如下:

 protected void dispatch(Event event) {
 .......

  Class<? extends Enum> type = event.getType().getDeclaringClass();

  try{
    //获取对应的事件调度处理器
    EventHandler handler = eventDispatchers.get(type);
    if(handler != null) {
      //执行事件调度handle的handle方法
      handler.handle(event);
    } else {
      throw new Exception("No handler for registered for " + type);
    }
  } catch (Throwable t) {
    .....
  }

2.2. 例子

RMAppImpl是EventHandle,其handle方法主要是根据接收的事件类型去改变RMAppImpl的状态,同时触发一种行为,其具体过程可以参考Yarn系列(二)

public void handle(RMAppEvent event) {

  this.writeLock.lock();

  try {
    ApplicationId appID = event.getApplicationId();
    LOG.debug("Processing event for " + appID + " of type "
        + event.getType());
    final RMAppState oldState = getState();
    try {
      /* keep the master in sync with the state machine */
      //具体转变可以参考Yarn系列(二)
      this.stateMachine.doTransition(event.getType(), event);
    } catch (InvalidStateTransitionException e) {
      LOG.error("App: " + appID
          + " can't handle this event at current state", e);
      onInvalidStateTransition(event.getType(), oldState);
    }

   ......
  } finally {
    this.writeLock.unlock();
  }
}
posted @ 2020-11-04 23:09  王大咩的图书馆  阅读(272)  评论(0编辑  收藏  举报