Hadoop2.8.5 资源管理器(RM)

YARN调度使用状态机(StateMachine)来驱动,我们以RM(ResourceManager)为例来看状态机如何驱动其运行。作为YARN的框架核心管理者整个集群的计算资源,对 于 宿 主 机 而 言,执 行 着ResourceManager 的 Java 虚拟机是个独立的进程。用户每向这个 Hadoop 平台提交一个应用程序作业,即 App ,资源管理器就会设法在某个NM 节点上为其另起一个 Java 虚拟机以运行 App 管理者( AppMaster , AM )。

Hadoop2.8.5 资源管理器(RM)_第1张图片

RM的 “成分”
server\resourcemanager\ResourceManager.java

@SuppressWarnings("unchecked")
public class ResourceManager extends CompositeService implements Recoverable {
  //长期运行的服务,会被加入到CompositeService中,Recoverable用于系统恢复
  @VisibleForTesting
  protected RMContextImpl rmContext;
  private Dispatcher rmDispatcher; //异步消息派发
  @VisibleForTesting
  protected AdminService adminService; //管理员服务
 
  //运行在活跃状态下的RM的服务
  protected RMActiveServices activeServices;
  protected RMSecretManagerService rmSecretManagerService; //私密管理服务

  protected ResourceScheduler scheduler; //资源调度器
  protected ReservationSystem reservationSystem;//预定系统
  private ClientRMService clientRM;//Client资源服务
  protected ApplicationMasterService masterService; //服务于现有的 AM 提供服务和管理
  protected NMLivelinessMonitor nmLivelinessMonitor; //子节点运行监视器
  protected NodesListManager nodesListManager;//节点列表管理
  protected RMAppManager rmAppManager; //集群App管理
  protected ApplicationACLsManager applicationACLsManager;//应用权限控制列表管理
  protected QueueACLsManager queueACLsManager;//队列控制链管理
  private WebApp webApp;//WebApp的网站服务
  private AppReportFetcher fetcher = null; //抓取应用报告
  protected ResourceTrackerService resourceTracker;//资源跟踪统计服务
  private JvmPauseMonitor pauseMonitor;//虚拟机暂停监视器
  private boolean curatorEnabled = false;
  private CuratorFramework curator; //ZooKeeper高级管理骨架
  private Configuration conf; //运行配置
  private UserGroupInformation rmLoginUGI;//用户组权限认证管理
  
 }

RM 上“活跃服务"
server\resourcemanager\ResourceManager.java

@Private
  public class RMActiveServices extends CompositeService {
    //租约代理
    private DelegationTokenRenewer delegationTokenRenewer;
    private EventHandler<SchedulerEvent> schedulerDispatcher; //调度派发
    private ApplicationMasterLauncher applicationMasterLauncher; //AM加载器
    private ContainerAllocationExpirer containerAllocationExpirer;
    private ResourceManager rm;
    private RMActiveServiceContext activeServiceContext;
    ......
    RMStateStore rmStore = null; // 创建 RMStateStore ,以保存各种副本
      try {
        rmStore.setResourceManager(rm);
        rmStore.init(conf);
        rmStore.setRMDispatcher(rmDispatcher); //设置派发器
      } 
      rmContext.setStateStore(rmStore);
      //注册事件处理器
     // Register event handler for NodesListManager
      nodesListManager = new NodesListManager(rmContext);
      rmDispatcher.register(NodesListManagerEventType.class, nodesListManager);
      addService(nodesListManager);
      rmContext.setNodesListManager(nodesListManager);
      // 初始化调度器
      scheduler = createScheduler();
      scheduler.setRMContext(rmContext);
      addIfService(scheduler);
      rmContext.setScheduler(scheduler);
      schedulerDispatcher = createSchedulerEventDispatcher();
      addIfService(schedulerDispatcher);
      rmDispatcher.register(SchedulerEventType.class, schedulerDispatcher);
      //创建三种 Dispatch 目标对象(接受来自 RM 的事件),并向 RM 的 Dispatcher 登记
      // Register event handler for RmAppEvents
      rmDispatcher.register(RMAppEventType.class, new ApplicationEventDispatcher(rmContext));
      // Register event handler for RmAppAttemptEvents
      rmDispatcher.register(RMAppAttemptEventType.class,new ApplicationAttemptEventDispatcher(rmContext));
      // Register event handler for RmNodes
      rmDispatcher.register( RMNodeEventType.class, new NodeEventDispatcher(rmContext));
      //跟踪资源的使用
      resourceTracker = createResourceTrackerService();
      addService(resourceTracker);
      rmContext.setResourceTrackerService(resourceTracker);
      //用来为 NM 节点上的 AM 提供服务
      masterService = createApplicationMasterService();
      addService(masterService) ;
      rmContext.setApplicationMasterService(masterService);
      //用来管理 AM
      rmAppManager = createRMAppManager();
      // Register event handler for RMAppManagerEvents
      rmDispatcher.register(RMAppManagerEventType.class, rmAppManager);
      //用来为客户提供资源服务
      clientRM = createClientRMService();
      addService(clientRM);
      rmContext.setClientRMService(clientRM);
      //用来在 NM 节点上启动运行 AM
      applicationMasterLauncher = createAMLauncher();
      rmDispatcher.register(AMLauncherEventType.class,
          applicationMasterLauncher);
      addService(applicationMasterLauncher);
   ......
}

RM 顶 层 的 rmDispatcher ,用 来向 ApplicationEventDispatcher , ApplicationAttemptEventDispatcher , NodeEventDispatcher 等对象分发事件,它 们 其 实 并 非 Dispatcher ,而 是Dispatch 的 目 标;它 们 实 现 的 是 EventHandler 界 面,而 不 是 Dispatcher 界 面。这 里 在RMActiveServices 中 又 有 个 schedulerDispatcher ,这 显 然 与 调 度 器 有 关,其 类 型 是SchedulerEventDisp atcher 。但是它实现的也是 EventHandler 界面,而不是 Dispatcher 界面;从形式上看,它是用来处理 SchedulerEvent 类事件的,而不是帮助分发事件的路由器。这里 的 ApplicationEventDispatcher 和 ApplicationAttemptEventDispatcher ,前 者 有 关Application ,用来 驱 动 代 表 着 具 体 App 的 ApplicationImpl 对 象 中 的 状 态 机;后 者 有 关ApplicationAttempt ,用来驱动代表着一次具体运行尝试的 RMAppAttemptImpl 对象中的状态机。

@Private
  public static final class NodeEventDispatcher implements
      EventHandler<RMNodeEvent> {

    private final RMContext rmContext;

    public NodeEventDispatcher(RMContext rmContext) {
      this.rmContext = rmContext;
    }

    @Override
    public void handle(RMNodeEvent event) {
      NodeId nodeId = event.getNodeId(); //取出子节点ID
      RMNode node = this.rmContext.getRMNodes().get(nodeId); //获得子节点
      if (node != null) {
        try {
        //调用RMNode的handler,实际是,RMNodeImpl
          ((EventHandler<RMNodeEvent>) node).handle(event); 
        } catch (Throwable t) {
          LOG.error("Error in handling event type " + event.getType()
              + " for node " + nodeId, t);
        }
      }
    }

对于集群中的每一个节点, RM 维持着一个与之对应的 RMNodeImpl 对象,在这个对象中有一个状态机,代表着该节点的当前状态,而NodeEventDispatcher 就是这些状态机的驱动者,它根据到来的事件 event 内容中的 NodeId
确定这是要分发到哪一个节点的状态机,然后找到代表着那个节点的 RMNode 对象 node ,即RMNodeImpl ,就以 event 为 参 数 直 接 调 用 其 handle ()函 数。

public interface RMNode { } //定义了一些基本节点操作
@Private
@Unstable
@SuppressWarnings("unchecked")
public class RMNodeImpl implements RMNode, EventHandler<RMNodeEvent> {
     ......
     //合成状态机
	 private static final StateMachineFactory<RMNodeImpl,
                                           NodeState,
                                           RMNodeEventType,
                                           RMNodeEvent> stateMachineFactory 
                 = new StateMachineFactory<RMNodeImpl,
                                           NodeState,
                                           RMNodeEventType,
                                           RMNodeEvent>(NodeState.NEW)

      //Transitions from NEW state
      //添加跳变规则
      .addTransition(NodeState.NEW, NodeState.RUNNING,
          RMNodeEventType.STARTED, new AddNodeTransition())
      .addTransition(NodeState.NEW, NodeState.NEW,
          RMNodeEventType.RESOURCE_UPDATE,
          new UpdateNodeResourceWhenUnusableTransition())
       ......
      .addTransition(NodeState.SHUTDOWN, NodeState.SHUTDOWN,
          RMNodeEventType.FINISHED_CONTAINERS_PULLED_BY_AM,
          new AddContainersToBeRemovedFromNMTransition())
      // 创建拓扑表
      .installTopology();
   }
  
  //处理来自RM转发的事件
  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 (InvalidStateTransitionException e) {
        LOG.error("Can't handle this event at current state", e);
        LOG.error("Invalid event " + event.getType() + 
            " on Node  " + this.nodeId);
      }
    finally {
      writeLock.unlock();
    }
  }
}

至于 NodeEventDispatcher ,则与 ResourceTrackerService 和 RMNodeImpl 有关。 RM 为NodeEventDispatcher 登记要 接 收 的 事 件 类 型 是 RMNodeEventType ,这 种 事 件 主 要 来 自ResourceTrackerService ,反映着集群中各节点的状态变化,例如失去连接然后又恢复了,或者机器重启了,等等。

以AddNodeTransition 为例,单狐跳转

public static class AddNodeTransition implements
      SingleArcTransition<RMNodeImpl, RMNodeEvent> {

    @Override
    public void transition(RMNodeImpl rmNode, RMNodeEvent event) {
      // Inform the scheduler
      RMNodeStartedEvent startEvent = (RMNodeStartedEvent) event;
      List<NMContainerStatus> containers = null;

      NodeId nodeId = rmNode.nodeId;
      RMNode previousRMNode =
          rmNode.context.getInactiveRMNodes().remove(nodeId);
      .......
      //最后调用RMNode的Dispatcher继续派发新的事件,处理新的任务,周而复始
      rmNode.context.getDispatcher().getEventHandler()
        .handle(new NodeAddedSchedulerEvent(rmNode, containers)); //资源调度事件
      rmNode.context.getDispatcher().getEventHandler().handle(
        new NodesListManagerEvent(
            NodesListManagerEventType.NODE_USABLE, rmNode));
    }
  }

server\resourcemanager\scheduler\fair\FairScheduler.java

@Override
  public void handle(SchedulerEvent event) {
    switch (event.getType()) {
    case NODE_ADDED:
      if (!(event instanceof NodeAddedSchedulerEvent)) {
        throw new RuntimeException("Unexpected event type: " + event);
      }
      NodeAddedSchedulerEvent nodeAddedEvent = (NodeAddedSchedulerEvent)event;
      addNode(nodeAddedEvent.getContainerReports(),
          nodeAddedEvent.getAddedRMNode());
      break;
      ......
 }

ResourceTrackerService ,反映着集群中各节点的状态变化,以心跳推送的形式接收来自NM的报告
server\resourcemanager\ResourceTrackerService.java

  @SuppressWarnings("unchecked")
  @Override
  public NodeHeartbeatResponse nodeHeartbeat(NodeHeartbeatRequest request)
      throws YarnException, IOException {

    NodeStatus remoteNodeStatus = request.getNodeStatus();
    /**
     * Here is the node heartbeat sequence...
     * 1. Check if it's a valid (i.e. not excluded) node
     * 2. Check if it's a registered node
     * 3. Check if it's a 'fresh' heartbeat i.e. not duplicate heartbeat
     * 4. Send healthStatus to RMNode
     * 5. Update node's labels if distributed Node Labels configuration is enabled
     */

    NodeId nodeId = remoteNodeStatus.getNodeId();

    ......

    return nodeHeartBeatResponse;
  }

RM 中最 重 要 的 活 跃 服 务 提 供 者 应 该 是 “资 源 调 度 器 ( scheduler )”,这 是 个 实 现 了ResourceScheduler 界面的某类对象,通过 createScheduler ()创建,具体的类型则在配置文件中加以指定。调度器手里的资源只能来集群中的众多 NodeManager 节点。 ResourceManager 内部有个 ResourceTrackerService 类的对象,它跟踪管理着 NodeManager 节点所知道的资源变动。另有一个 NodesListManager 类的对象nodesListManager 则维持着一个节点清单,记录着哪些节点当前是可用的,哪些则是不可用的。而 ResourceTrackerService 和 NodesListManager 所掌握的信息,则来自众多 NodeManager 节点的心跳报告,即伴随着每次“心跳”提供的报告。这些信息,最终都要汇集到资源调度器,因为这些资源都要由资源调度器分配出去。

你可能感兴趣的:(Hadoop)