/** * sort slots, the purpose is to ensure that the tasks are assigned in balancing * * @param allSlots * @return List<WorkerSlot> */ public static List<WorkerSlot> sortSlots(Set<WorkerSlot> allSlots, int needSlotNum) { Map<String, List<WorkerSlot>> nodeMap = new HashMap<String, List<WorkerSlot>>(); // group by first for (WorkerSlot np : allSlots) { String node = np.getNodeId(); List<WorkerSlot> list = nodeMap.get(node); if (list == null) { list = new ArrayList<WorkerSlot>(); nodeMap.put(node, list); } list.add(np); } for (Entry<String, List<WorkerSlot>> entry : nodeMap.entrySet()) { List<WorkerSlot> ports = entry.getValue(); Collections.sort( ports, new Comparator<WorkerSlot>() { @Override public int compare(WorkerSlot first, WorkerSlot second) { String firstNode = first.getNodeId(); String secondNode = second.getNodeId(); if (firstNode.equals(secondNode) == false) { return firstNode.compareTo(secondNode); } else { return first.getPort() - second.getPort(); } } }); } // interleave List<List<WorkerSlot>> splitup = new ArrayList<List<WorkerSlot>>(nodeMap.values()); Collections.sort( splitup, new Comparator<List<WorkerSlot>>() { public int compare(List<WorkerSlot> o1, List<WorkerSlot> o2) { return o2.size() - o1.size(); } }); List<WorkerSlot> sortedFreeSlots = JStormUtils.interleave_all(splitup); if (sortedFreeSlots.size() <= needSlotNum) { return sortedFreeSlots; } // sortedFreeSlots > needSlotNum return sortedFreeSlots.subList(0, needSlotNum); }
/** * 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(); }
private WorkerSlot findWorkerForExec( ExecutorDetails exec, TopologyDetails td, Map<WorkerSlot, Collection<ExecutorDetails>> scheduleAssignmentMap) { WorkerSlot ws = null; // first scheduling if (this.refNode == null) { String clus = this.getBestClustering(); ws = this.getBestWorker(exec, td, clus, scheduleAssignmentMap); } else { ws = this.getBestWorker(exec, td, scheduleAssignmentMap); } if (ws != null) { this.refNode = this.idToNode(ws.getNodeId()); } LOG.debug("reference node for the resource aware scheduler is: {}", this.refNode); return ws; }
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; }