yarn3.2源码分析之FairScheduler抢占式调度

概述

FairScheduler可以通过配置yarn.scheduler.fair.preemption参数为true,开启抢占式调度,默认为false,即不开启。

 FairScheduler在计算这个队列允许抢占其它队列的资源大小时,如果这个队列使用的资源低于其minshare的时间超过了抢占超时时间,那么,应该抢占的资源量就在它当前的fair share和它的min share之间的差额。如果队列资源已经低于它的fair share的时间超过了fairSharePreemptionTimeout,那么他应该进行抢占的资源就是满足其fair share的资源总量。如果两者都发生了,则抢占两个的较多者。

抢占式调度主要由2个线程配合完成:

  • UpdateThread:计算队列和app的fairShare,然后计算app的fairshareStarvation量和app的minshareStarvation量,并记录这些处于starvation状态的app。
  • FSPreemptionThread:处理处于starvation状态的app。基于给定的app,获取一批可用于抢占的cotainer,并在必要时kill掉这些container。

 FSPreemptionThread

 FairScheduler在启动服务时,会启动FSPreemptionThread。

如果开启抢占式调度,则会创建一个后台线程FSPreemptionThread 。 

if (this.conf.getPreemptionEnabled()) {
        createPreemptionThread();
      }

FSPreemptionThread的run()方法逻辑

  1. FairScheduler的上下文FSContext的FSStarvedApps变量中维护了一个PriorityBlockingQueue<FSAppAttempt>队列,该队列中记录了处于starvation状态的app。FSPreemptedThread从队列中获取处于starvation状态的app 。
  2. 基于给定的app,抢占一定数量的container用来满足该app的需求。返回可用于抢占的container。
  3. 在时间超过waitTimeBeforeKill后,标记为待抢占的container仍没有被释放,则preemptContainers()方法主动kill掉该container。
public void run() {
    while (!Thread.interrupted()) {
      try {
//FairScheduler的上下文FSContext的FSStarvedApps变量中维护了一个PriorityBlockingQueue<FSAppAttempt>队列
//该队列中记录了处于starvation状态的app
//FSPreemptedThread从队列中获取处于starvation状态的app
        FSAppAttempt starvedApp = context.getStarvedApps().take();
        // Hold the scheduler readlock so this is not concurrent with the
        // update thread.
        schedulerReadLock.lock();
        try {
//identifyContainersToPreempt()方法:基于给定的app,抢占一定数量的container用来满足该app的需求。返回可用于抢占的container。
//preemptContainers()方法:在时间超过waitTimeBeforeKill后,标记为待抢占的container仍没有被释放,则preemptContainers()方法主动kill掉该container。
          preemptContainers(identifyContainersToPreempt(starvedApp));
        } finally {
          schedulerReadLock.unlock();
        }
        starvedApp.preemptionTriggered(delayBeforeNextStarvationCheck);
      } catch (InterruptedException e) {
        LOG.info("Preemption thread interrupted! Exiting.");
        Thread.currentThread().interrupt();
      }
    }
  }

preemptContainers()方法

 如果这个container已经被标记为待抢占,并且距离标记时间已经超过了waitTimeBeforeKill却依然没有被自己的ApplicationMaster主动释放的container,那么直接杀死这个Container。

private void preemptContainers(List<RMContainer> containers) {
    // Schedule timer task to kill containers
    preemptionTimer.schedule(
        new PreemptContainersTask(containers), warnTimeBeforeKill);
  }

PreemptContainersTask

执行kill container事件 

private class PreemptContainersTask extends TimerTask {
    private final List<RMContainer> containers;

    PreemptContainersTask(List<RMContainer> containers) {
      this.containers = containers;
    }

    @Override
    public void run() {
      for (RMContainer container : containers) {
        ContainerStatus status = SchedulerUtils.createPreemptedContainerStatus(
            container.getContainerId(), SchedulerUtils.PREEMPTED_CONTAINER);

        LOG.info("Killing container " + container);
        scheduler.completedContainer(
            container, status, RMContainerEventType.KILL);
      }
    }
  }

UpdateThread

 AbstractYarnScheduler在启动服务时,会启动UpdateThread。UpdateThread是AbstractYarnScheduler的内部类。

/**
   * Thread which calls {@link #update()} every
   * <code>updateInterval</code> milliseconds.
   */
  private class UpdateThread extends Thread {
    @Override
    public void run() {
      while (!Thread.currentThread().isInterrupted()) {
        try {
          synchronized (updateThreadMonitor) {
            updateThreadMonitor.wait(updateInterval);
          }
          update();
        } catch 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值