private WorkerSlot getBestWorker(
      ExecutorDetails exec,
      TopologyDetails td,
      String clusterId,
      Map<WorkerSlot, Collection<ExecutorDetails>> scheduleAssignmentMap) {
    double taskMem = td.getTotalMemReqTask(exec);
    double taskCPU = td.getTotalCpuReqTask(exec);
    List<RAS_Node> nodes;
    if (clusterId != null) {
      nodes = this.getAvailableNodesFromCluster(clusterId);

    } else {
      nodes = this.getAvailableNodes();
    }
    // First sort nodes by distance
    TreeMap<Double, RAS_Node> nodeRankMap = new TreeMap<Double, RAS_Node>();
    for (RAS_Node n : nodes) {
      if (n.getFreeSlots().size() > 0) {
        if (n.getAvailableMemoryResources() >= taskMem && n.getAvailableCpuResources() >= taskCPU) {
          double a =
              Math.pow(
                  ((taskCPU - n.getAvailableCpuResources()) / (n.getAvailableCpuResources() + 1))
                      * this.CPU_WEIGHT,
                  2);
          double b =
              Math.pow(
                  ((taskMem - n.getAvailableMemoryResources())
                          / (n.getAvailableMemoryResources() + 1))
                      * this.MEM_WEIGHT,
                  2);
          double c = 0.0;
          if (this.refNode != null) {
            c = Math.pow(this.distToNode(this.refNode, n) * this.NETWORK_WEIGHT, 2);
          }
          double distance = Math.sqrt(a + b + c);
          nodeRankMap.put(distance, n);
        }
      }
    }
    // Then, pick worker from closest node that satisfy constraints
    for (Map.Entry<Double, RAS_Node> entry : nodeRankMap.entrySet()) {
      RAS_Node n = entry.getValue();
      for (WorkerSlot ws : n.getFreeSlots()) {
        if (checkWorkerConstraints(exec, ws, td, scheduleAssignmentMap)) {
          return ws;
        }
      }
    }
    return null;
  }
 /**
  * Get the remaining amount memory that can be assigned to a worker given the set worker max heap
  * size
  *
  * @param ws
  * @param td
  * @param scheduleAssignmentMap
  * @return The remaining amount of memory
  */
 private Double getWorkerScheduledMemoryAvailable(
     WorkerSlot ws,
     TopologyDetails td,
     Map<WorkerSlot, Collection<ExecutorDetails>> scheduleAssignmentMap) {
   Double memScheduleUsed = this.getWorkerScheduledMemoryUse(ws, td, scheduleAssignmentMap);
   return td.getTopologyWorkerMaxHeapSize() - memScheduleUsed;
 }
  /**
   * Breadth first traversal of the topology DAG
   *
   * @param topologies
   * @param td
   * @param spouts
   * @return A partial ordering of components
   */
  private Queue<Component> bfs(Topologies topologies, TopologyDetails td, List<Component> spouts) {
    // Since queue is a interface
    Queue<Component> ordered__Component_list = new LinkedList<Component>();
    HashMap<String, Component> visited = new HashMap<String, Component>();

    /* start from each spout that is not visited, each does a breadth-first traverse */
    for (Component spout : spouts) {
      if (!visited.containsKey(spout.id)) {
        Queue<Component> queue = new LinkedList<Component>();
        queue.offer(spout);
        while (!queue.isEmpty()) {
          Component comp = queue.poll();
          visited.put(comp.id, comp);
          ordered__Component_list.add(comp);
          List<String> neighbors = new ArrayList<String>();
          neighbors.addAll(comp.children);
          neighbors.addAll(comp.parents);
          for (String nbID : neighbors) {
            if (!visited.containsKey(nbID)) {
              Component child = topologies.getAllComponents().get(td.getId()).get(nbID);
              queue.offer(child);
            }
          }
        }
      }
    }
    return ordered__Component_list;
  }
 private List<Component> getSpouts(Topologies topologies, TopologyDetails td) {
   List<Component> spouts = new ArrayList<Component>();
   for (Component c : topologies.getAllComponents().get(td.getId()).values()) {
     if (c.type == Component.ComponentType.SPOUT) {
       spouts.add(c);
     }
   }
   return spouts;
 }
Beispiel #5
0
  /**
   * print scheduling for debug purposes
   *
   * @param cluster
   * @param topologies
   */
  public static String printScheduling(Cluster cluster, Topologies topologies) {
    StringBuilder str = new StringBuilder();
    Map<String, Map<String, Map<WorkerSlot, Collection<ExecutorDetails>>>> schedulingMap =
        new HashMap<String, Map<String, Map<WorkerSlot, Collection<ExecutorDetails>>>>();
    for (TopologyDetails topo : topologies.getTopologies()) {
      if (cluster.getAssignmentById(topo.getId()) != null) {
        for (Map.Entry<ExecutorDetails, WorkerSlot> entry :
            cluster.getAssignmentById(topo.getId()).getExecutorToSlot().entrySet()) {
          WorkerSlot slot = entry.getValue();
          String nodeId = slot.getNodeId();
          ExecutorDetails exec = entry.getKey();
          if (!schedulingMap.containsKey(nodeId)) {
            schedulingMap.put(
                nodeId, new HashMap<String, Map<WorkerSlot, Collection<ExecutorDetails>>>());
          }
          if (schedulingMap.get(nodeId).containsKey(topo.getId()) == false) {
            schedulingMap
                .get(nodeId)
                .put(topo.getId(), new HashMap<WorkerSlot, Collection<ExecutorDetails>>());
          }
          if (schedulingMap.get(nodeId).get(topo.getId()).containsKey(slot) == false) {
            schedulingMap
                .get(nodeId)
                .get(topo.getId())
                .put(slot, new LinkedList<ExecutorDetails>());
          }
          schedulingMap.get(nodeId).get(topo.getId()).get(slot).add(exec);
        }
      }
    }

    for (Map.Entry<String, Map<String, Map<WorkerSlot, Collection<ExecutorDetails>>>> entry :
        schedulingMap.entrySet()) {
      if (cluster.getSupervisorById(entry.getKey()) != null) {
        str.append(
            "/** Node: "
                + cluster.getSupervisorById(entry.getKey()).getHost()
                + "-"
                + entry.getKey()
                + " **/\n");
      } else {
        str.append("/** Node: Unknown may be dead -" + entry.getKey() + " **/\n");
      }
      for (Map.Entry<String, Map<WorkerSlot, Collection<ExecutorDetails>>> topo_sched :
          schedulingMap.get(entry.getKey()).entrySet()) {
        str.append("\t-->Topology: " + topo_sched.getKey() + "\n");
        for (Map.Entry<WorkerSlot, Collection<ExecutorDetails>> ws :
            topo_sched.getValue().entrySet()) {
          str.append("\t\t->Slot [" + ws.getKey().getPort() + "] -> " + ws.getValue() + "\n");
        }
      }
    }
    return str.toString();
  }
 /**
  * Checks whether we can schedule an Executor exec on the worker slot ws Only considers memory
  * currenlty. May include CPU in the future
  *
  * @param exec
  * @param ws
  * @param td
  * @param scheduleAssignmentMap
  * @return a boolean: True denoting the exec can be scheduled on ws and false if it cannot
  */
 private boolean checkWorkerConstraints(
     ExecutorDetails exec,
     WorkerSlot ws,
     TopologyDetails td,
     Map<WorkerSlot, Collection<ExecutorDetails>> scheduleAssignmentMap) {
   boolean retVal = false;
   if (this.getWorkerScheduledMemoryAvailable(ws, td, scheduleAssignmentMap)
       >= td.getTotalMemReqTask(exec)) {
     retVal = true;
   }
   return retVal;
 }
 /**
  * Get the amount of memory already assigned to a worker
  *
  * @param ws
  * @param td
  * @param scheduleAssignmentMap
  * @return the amount of memory
  */
 private Double getWorkerScheduledMemoryUse(
     WorkerSlot ws,
     TopologyDetails td,
     Map<WorkerSlot, Collection<ExecutorDetails>> scheduleAssignmentMap) {
   Double totalMem = 0.0;
   Collection<ExecutorDetails> execs = scheduleAssignmentMap.get(ws);
   if (execs != null) {
     for (ExecutorDetails exec : execs) {
       totalMem += td.getTotalMemReqTask(exec);
     }
   }
   return totalMem;
 }
  public Map<WorkerSlot, Collection<ExecutorDetails>> schedule(TopologyDetails td) {
    if (_availNodes.size() <= 0) {
      LOG.warn("No available nodes to schedule tasks on!");
      return null;
    }
    Collection<ExecutorDetails> unassignedExecutors = _cluster.getUnassignedExecutors(td);
    Map<WorkerSlot, Collection<ExecutorDetails>> schedulerAssignmentMap =
        new HashMap<WorkerSlot, Collection<ExecutorDetails>>();
    LOG.debug("ExecutorsNeedScheduling: {}", unassignedExecutors);
    Collection<ExecutorDetails> scheduledTasks = new ArrayList<ExecutorDetails>();
    List<Component> spouts = this.getSpouts(_topologies, td);

    if (spouts.size() == 0) {
      LOG.error("Cannot find a Spout!");
      return null;
    }

    Queue<Component> ordered__Component_list = bfs(_topologies, td, spouts);

    Map<Integer, List<ExecutorDetails>> priorityToExecutorMap =
        getPriorityToExecutorDetailsListMap(ordered__Component_list, unassignedExecutors);
    Collection<ExecutorDetails> executorsNotScheduled =
        new HashSet<ExecutorDetails>(unassignedExecutors);
    Integer longestPriorityListSize = this.getLongestPriorityListSize(priorityToExecutorMap);
    // Pick the first executor with priority one, then the 1st exec with priority 2, so on an so
    // forth.
    // Once we reach the last priority, we go back to priority 1 and schedule the second task with
    // priority 1.
    for (int i = 0; i < longestPriorityListSize; i++) {
      for (Entry<Integer, List<ExecutorDetails>> entry : priorityToExecutorMap.entrySet()) {
        Iterator<ExecutorDetails> it = entry.getValue().iterator();
        if (it.hasNext()) {
          ExecutorDetails exec = it.next();
          LOG.debug(
              "\n\nAttempting to schedule: {} of component {}[avail {}] with rank {}",
              new Object[] {
                exec,
                td.getExecutorToComponent().get(exec),
                td.getTaskResourceReqList(exec),
                entry.getKey()
              });
          WorkerSlot targetSlot = this.findWorkerForExec(exec, td, schedulerAssignmentMap);
          if (targetSlot != null) {
            RAS_Node targetNode = this.idToNode(targetSlot.getNodeId());
            if (!schedulerAssignmentMap.containsKey(targetSlot)) {
              schedulerAssignmentMap.put(targetSlot, new LinkedList<ExecutorDetails>());
            }

            schedulerAssignmentMap.get(targetSlot).add(exec);
            targetNode.consumeResourcesforTask(exec, td);
            scheduledTasks.add(exec);
            LOG.debug(
                "TASK {} assigned to Node: {} avail [mem: {} cpu: {}] total [mem: {} cpu: {}] on slot: {}",
                exec,
                targetNode,
                targetNode.getAvailableMemoryResources(),
                targetNode.getAvailableCpuResources(),
                targetNode.getTotalMemoryResources(),
                targetNode.getTotalCpuResources(),
                targetSlot);
          } else {
            LOG.error("Not Enough Resources to schedule Task {}", exec);
          }
          it.remove();
        }
      }
    }

    executorsNotScheduled.removeAll(scheduledTasks);
    LOG.debug("/* Scheduling left over task (most likely sys tasks) */");
    // schedule left over system tasks
    for (ExecutorDetails exec : executorsNotScheduled) {
      WorkerSlot targetSlot = this.findWorkerForExec(exec, td, schedulerAssignmentMap);
      if (targetSlot != null) {
        RAS_Node targetNode = this.idToNode(targetSlot.getNodeId());
        if (schedulerAssignmentMap.containsKey(targetSlot) == false) {
          schedulerAssignmentMap.put(targetSlot, new LinkedList<ExecutorDetails>());
        }

        schedulerAssignmentMap.get(targetSlot).add(exec);
        targetNode.consumeResourcesforTask(exec, td);
        scheduledTasks.add(exec);
        LOG.debug(
            "TASK {} assigned to Node: {} avail [mem: {} cpu: {}] total [mem: {} cpu: {}] on slot: {}",
            exec,
            targetNode,
            targetNode.getAvailableMemoryResources(),
            targetNode.getAvailableCpuResources(),
            targetNode.getTotalMemoryResources(),
            targetNode.getTotalCpuResources(),
            targetSlot);
      } else {
        LOG.error("Not Enough Resources to schedule Task {}", exec);
      }
    }
    executorsNotScheduled.removeAll(scheduledTasks);
    if (executorsNotScheduled.size() > 0) {
      LOG.error("Not all executors successfully scheduled: {}", executorsNotScheduled);
      schedulerAssignmentMap = null;
    } else {
      LOG.debug("All resources successfully scheduled!");
    }
    if (schedulerAssignmentMap == null) {
      LOG.error("Topology {} not successfully scheduled!", td.getId());
    }
    return schedulerAssignmentMap;
  }
  public void linkBasedScheduling(
      Topologies topos, Cluster cluster, GlobalState globalState, GlobalResources globalResources) {
    for (TopologyDetails td : topos.getTopologies()) {
      String topId = td.getId();
      Map<Node, Collection<ExecutorDetails>> taskToNodesMap;
      if (cluster.needsScheduling(td) && cluster.getUnassignedExecutors(td).size() > 0) {
        LOG.info("/********Scheduling topology {} ************/", topId);
        int totalTasks = td.getExecutors().size();
        int executorsNotRunning = cluster.getUnassignedExecutors(td).size();
        LOG.info(
            "Total number of executors: {} " + "Total number of Unassigned Executors: {}",
            totalTasks,
            executorsNotRunning);
        LOG.info("executors that need scheduling: {}", cluster.getUnassignedExecutors(td));

        LinkBasedStrategy rs =
            new LinkBasedStrategy(globalState, globalResources, null, td, cluster, topos);
        taskToNodesMap = rs.schedule(td, cluster.getUnassignedExecutors(td));

        if (taskToNodesMap != null) {
          try {
            for (Map.Entry<Node, Collection<ExecutorDetails>> entry : taskToNodesMap.entrySet()) {
              entry.getKey().assign(td.getId(), entry.getValue(), cluster);
              LOG.info(
                  "ASSIGNMENT    TOPOLOGY: {}  TASKS: {} To Node: "
                      + entry.getKey().getId()
                      + " Slots left: "
                      + entry.getKey().totalSlotsFree(),
                  td.getId(),
                  entry.getValue());
            }
            LOG.info(
                "Toplogy: {} assigned to {} nodes", td.getId(), taskToNodesMap.keySet().size());

            HelperFuncs.setTopoStatus(td.getId(), "Fully Scheduled");
          } catch (IllegalStateException ex) {
            LOG.error(ex.toString());
            LOG.error("Unsuccessfull in scheduling topology {}", td.getId());
            HelperFuncs.setTopoStatus(td.getId(), "Unsuccessfull in scheduling topology");
          }
        } else {
          LOG.error("Unsuccessfull in scheduling topology {}", td.getId());
          HelperFuncs.setTopoStatus(td.getId(), "Unsuccessfull in scheduling topology");
        }
      } else {
        HelperFuncs.setTopoStatus(td.getId(), "Fully Scheduled");
      }
    }
  }