Yarn capacity scheduler

  • 首先要知道, [Attention: RM有两个组件,其中Scheduler完全就只是负责资源的分配;ApplicationsManager则负责接受application,选取ApplicationMaster,监控重启AM。]
  • CapacityScheduler的优点就是灵活,集群的利用率高;缺点也是由其灵活性造成的,因为CapacityScheduler不支持抢占式调度,必须等上一个任务主动释放资源。
  • 可以看出,只要提交的app数没有达到上限,就能够一直提交app到集群,只是这些app会处于accepted的状态,一直pending,直到ResourceManager给它分配资源。
  • 因此Scheduler实际上是会不断地schedule,然后分配资源给那些集群,在具体分配的时候,在queue内部可能会考虑优先级,然后结合FIFO。

AsyncScheduleThread

  • 在CapacityScheduler内部有个AsyncScheduleThread 这个异步Scheduler线程会不断地调schedule(cs)方法。

schedule(cs)

  • // Schedule on all nodes by starting at a random point.
  • static void schedule(CapacityScheduler cs) 
    • // first randomize the start point
    • Collection<FiCaSchedulerNode> nodes = cs.getAllNodes().values()    // get all the nodes in the cluster
    • for each node: cs.allocateContainersToNode(node)
      • // assign new containers...  1. check for reserved apps(for reservation see here and here. )   2. schedule if there are no reservations
      • if reservedContainer != null
        • get the reserved apps according to reservedContainers
        • // try to fulfill the reservation
        • LeafQueue queue = ((LeafQueue) reservedApplication.getQueue();
        • CSAssignment assignment = queue.assignContainers(clusterResource, node, false); // assignContainers(Resource clusterResource, FiCaSchedulerNode node, boolean needToUnreserve);
          • // if our queue cannot access this node, just return
          • // check for reserved resources
        • TBD...
      • // try to schedule more if there are no reservations to fulfill
      • if (node.getReservedContainer() == null)
        • if (calculator.computeAvailableContainers(node.getAvailableResource(), minimumAllocation) > 0), then  // computeAvailableContainers(Resource available, Resource required), as for DominantResourceCalculator, return the min ratio of mem & vcores.

          • assignContainers(clusterResource, node, false)   // assignContainers(Resource clusterResource, FiCaSchedulerNode node)

            • // if our queue cannot access this node, just return
            • // check for reserved resources    // TBD...
            • // try to assign containers to apps in order
            • for (FoCaSchedulerApp application: activeApplications) 
              • if (SchedulerAppUtils.isBlacklisted(application, node, LOG) // check if this resource is on blacklist, i.e. cannot run the app in this node/rack
              • // schedule in priority order, this is the priority of the resourceRequest of this app
              • for (Priority priority : application.getPriorities())
                • ResourceRequest anyRequest = application.getResourceRequest(priority, ResourceRequest.ANY)
                • Resource required = anyRequest.getCapacity()
                • Set<String> requestedNodeLabels = getRequestLabelSetByExpression(anyRequest.getNodeLabelExpression());
                • // compute user-limit & set headroom.
                • Resource userLimit = computeUserLimitAndSetHeadroom(application, clusterResource, required, requestedNodeLabels)
                  • // compute user limit respect requested labels
                  • // TODO: need consider headroom respect labels also
                  • Resource userLimit = computeUserLimit(application, clusterResource, required, queueUser, requestedLabels)
                    • // our current capacity: equal to the max(required, queue-capacity) if we're running below capacity, equal to (usedResources + required) if running over capacity.
                    • // if we have labels to request(choose to use the first one).
                    • // else if no label on request, just use absolute capacity as capacity for nodes without label.
                    • // TBD...
                • // max avail capacity needs to take into account usage by ancestor-siblings which are greater than their base
                • // calculate absoluteMaxAvailCapacity: my max avail is min(my max capacity, unused from my parent by my siblings if they are beyond their base capacity)
                • // then calculate queueMaxCap using absoluteMaxAvailCapacity
                • // check canAssignToThisQueue
                  • // consider the intersection of queue-canAccessLabels and node-labels, if any of the label beyond queue limit, we cannot allocate on this node.
                  • // check user limit
                  • application.addSchedulingOpportunity(priority);
                  • // try to schedule...
                  • TBD...
  • FYI:
    /** 
    * Headroom is:
    * min(
    * min(userLimit, queueMaxCap) - userConsumed,
    * queueMaxCap - queueUsedResources
    * )
    *
    * ( which can be expressed as,
    * min (userLimit - userConsumed, queuMaxCap - userConsumed,
    * queueMaxCap - queueUsedResources)
    * )
    *
    * given that queueUsedResources >= userConsumed, this simplifies to
    *
    * >> min (userlimit - userConsumed, queueMaxCap - queueUsedResources) <<
    *
    */

addApplication

首先在CapacityScheduler随意找了个方法

synchronized addApplication(ApplicationAttemptedId applicationAttemptId, String queueName, String user)

  • sanity check

    • queue == null
    • !queue instanceof LeafQueue
  • Represents an application from the viewpoint of the scheduler. (Each running app in the RM corresponds to one instance of the FiCaScheduler class)
    • FiCaSchedulerApp SchedulerApp = new FiCaSchedulerApp(applicationAttemptId, user, queue, queue.getActiveUserManager(), rmContext);

      • ActiveUsersManager tracks users in the system. (An active user is defined as someone with outstanding resource requests.)
      • rmContext is the context of the RM.
  • submit to the queue
    • try: queue.submitApplication(SchedulerApp, user, queueName)

      • check queue ACLs
      • synchronized(this) 
        • check if the queue is accepting jobs: if (getState() != QueueState.RUNNING) throw Exception
        • check submission limits for queues:
          • if (getNumApplications() >= getMaxApplications()) throw Exception
        • check submission limits for the user on this queue
        • addApplication(applictaion, user)
          • user.submitApplication() : pendingApp ++; // accepted
          • activateApplications():
            • for each pending apps:

              • check queue limit & user limit again (same as above)
              • activateApplication(): --pendingApp; ++activeApp;
      • metrics.submitApp(userName, attempId): // each queue has a metrics which is an instance of QueueMetrics
        • update metrics: appsSubmitted, appsFailed, appsPending
        • if (parent != null) parent.submitApp(user, attemptId)   // to inform the parents recursively

以上,可以看到在addApplication方法内主要是判断了ACL和appNum的上限,没有resource相关的分配和判断。资源(container)的分配是由相应的applicationMaster向Resourcemanager统一请求的。ResourceRequest使用protobuf。

  • 用户提交应用程序 --> ResourceManager   --> ACL等检查 -->  app accepted.
  • 一旦Scheduler有足够的资源可以满足需求  -->  app由accepted转成running  -->  RM为ApplicationMaster分配一个container,并负责在节点上拉起它。
  • AM是每个用户作业的主进程,负责管理作业生命周期,包括动态地增加or减少资源(container),管理执行流程,处理故障和计算偏差。

Yarn Queues

<Yarn> <Capacity Scheduler> <Source Code>的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. confirm提示弹出确定和取消按钮

    js----> var con = confirm('这是一个确定加取消的提示窗口') if(con==true){ document.write("点击了确定按钮") }e ...

  2. vi常用快捷键

    vi常用快捷键 1)移动光标 h :光标左移一个字符k :光标上移一个字符j :光标下移一个字符l :光标右移一个字符 0 :光标移至行首$ :光标移至行尾 H :光标移至屏幕首行M :光标移至屏幕中 ...

  3. Python基础之文件的初识函数

    初识函数函数定义:定义一个事情或者功能. 等到需要的时候直接去用就好了了. 那么这里定义的东西就是一个函数即函数: 对代码块和功能的封装和定义1.1常用形式: def 函数名(): 函数体1.2 函数 ...

  4. 6月5 Smarty自定义函数

    自定义函数:<{方法名称}> 在html页面是可以直接赋值的:(没啥作用只是知道即可) <{$a = "hello"}><div><{$a ...

  5. 字符串加密解密(Base64)

    var Base64 = { // private property _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx ...

  6. python--django-admin定制页面流程:

    django-admin定制页面流程: 1.自定义一个类:要继承 ModelAdmin class Cool(admin.ModelAdmin):    pass    2. 在注册时,表名后加 自定 ...

  7. sparklyr-R语言访问Spark的另外一种方法

    Connect to Spark from R. The sparklyr package provides a complete dplyr backend. Filter and aggregat ...

  8. Spring Cloud系列之客户端请求带“Authorization”请求头,经过zuul转发后丢失了

    先摆解决方案: 方法一: 方法二: zuul.routes.<routeName>.sensitive-headers= zuul.routes.<routeName>.cus ...

  9. 连续三月涨势明显,PostgreSQL 将崛起?

    33 分享 10 ​ DB-Engines 是全球最流行的数据库排行榜之一,在近几个月的排行榜中,PostgreSQL 都保持着非常好的势头,从最稳(10月)到一路高涨(11月),再到稳步上升(12月 ...

  10. 正则表达式test()和exec()、 search() 和 replace()用法实例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...