use of org.apache.storm.scheduler.WorkerSlot in project storm by apache.
the class ResourceUtils method printScheduling.
/**
* 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();
}
use of org.apache.storm.scheduler.WorkerSlot in project storm by apache.
the class DefaultResourceAwareStrategy method schedule.
public SchedulingResult schedule(TopologyDetails td) {
if (_nodes.getNodes().size() <= 0) {
LOG.warn("No available nodes to schedule tasks on!");
return SchedulingResult.failure(SchedulingStatus.FAIL_NOT_ENOUGH_RESOURCES, "No available nodes to schedule tasks on!");
}
Collection<ExecutorDetails> unassignedExecutors = new HashSet<ExecutorDetails>(_cluster.getUnassignedExecutors(td));
Map<WorkerSlot, Collection<ExecutorDetails>> schedulerAssignmentMap = new HashMap<>();
LOG.debug("ExecutorsNeedScheduling: {}", unassignedExecutors);
Collection<ExecutorDetails> scheduledTasks = new ArrayList<>();
List<Component> spouts = this.getSpouts(td);
if (spouts.size() == 0) {
LOG.error("Cannot find a Spout!");
return SchedulingResult.failure(SchedulingStatus.FAIL_INVALID_TOPOLOGY, "Cannot find a Spout!");
}
//order executors to be scheduled
List<ExecutorDetails> orderedExecutors = orderExecutors(td, unassignedExecutors);
Collection<ExecutorDetails> executorsNotScheduled = new HashSet<>(unassignedExecutors);
for (ExecutorDetails exec : orderedExecutors) {
LOG.debug("\n\nAttempting to schedule: {} of component {}[ REQ {} ]", exec, td.getExecutorToComponent().get(exec), td.getTaskResourceReqList(exec));
scheduleExecutor(exec, td, schedulerAssignmentMap, scheduledTasks);
}
executorsNotScheduled.removeAll(scheduledTasks);
LOG.debug("/* Scheduling left over task (most likely sys tasks) */");
// schedule left over system tasks
for (ExecutorDetails exec : executorsNotScheduled) {
scheduleExecutor(exec, td, schedulerAssignmentMap, scheduledTasks);
}
SchedulingResult result;
executorsNotScheduled.removeAll(scheduledTasks);
if (executorsNotScheduled.size() > 0) {
LOG.error("Not all executors successfully scheduled: {}", executorsNotScheduled);
schedulerAssignmentMap = null;
result = SchedulingResult.failure(SchedulingStatus.FAIL_NOT_ENOUGH_RESOURCES, (td.getExecutors().size() - unassignedExecutors.size()) + "/" + td.getExecutors().size() + " executors scheduled");
} else {
LOG.debug("All resources successfully scheduled!");
result = SchedulingResult.successWithMsg(schedulerAssignmentMap, "Fully Scheduled by DefaultResourceAwareStrategy");
}
if (schedulerAssignmentMap == null) {
LOG.error("Topology {} not successfully scheduled!", td.getId());
}
return result;
}
use of org.apache.storm.scheduler.WorkerSlot in project storm by apache.
the class DefaultResourceAwareStrategy method getBestWorker.
/**
* Get the best worker to assign executor exec on a rack
*
* @param exec the executor to schedule
* @param td the topology that the executor is a part of
* @param rackId the rack id of the rack to find a worker on
* @param scheduleAssignmentMap already calculated assignments
* @return a worker to assign executor exec to. Returns null if a worker cannot be successfully found on rack with rackId
*/
private WorkerSlot getBestWorker(ExecutorDetails exec, TopologyDetails td, String rackId, Map<WorkerSlot, Collection<ExecutorDetails>> scheduleAssignmentMap) {
if (!_rackIdToSortedNodes.containsKey(rackId)) {
_rackIdToSortedNodes.put(rackId, sortNodes(this.getAvailableNodesFromRack(rackId), rackId, td.getId(), scheduleAssignmentMap));
}
TreeSet<ObjectResources> sortedNodes = _rackIdToSortedNodes.get(rackId);
double taskMem = td.getTotalMemReqTask(exec);
double taskCPU = td.getTotalCpuReqTask(exec);
for (ObjectResources nodeResources : sortedNodes) {
RAS_Node n = _nodes.getNodeById(nodeResources.id);
if (n.getAvailableCpuResources() >= taskCPU && n.getAvailableMemoryResources() >= taskMem && n.getFreeSlots().size() > 0) {
for (WorkerSlot ws : n.getFreeSlots()) {
if (checkWorkerConstraints(exec, ws, td, scheduleAssignmentMap)) {
return ws;
}
}
}
}
return null;
}
use of org.apache.storm.scheduler.WorkerSlot in project storm by apache.
the class DefaultResourceAwareStrategy method sortNodes.
/**
* Sorted Nodes
*
* @param availNodes a list of all the nodes we want to sort
* @param rackId the rack id availNodes are a part of
* @param topoId the topology that we are trying to schedule
* @param scheduleAssignmentMap calculated assignments so far
* @return a sorted list of nodes
* <p>
* Nodes are sorted by two criteria. 1) the number executors of the topology that needs to be scheduled is already on the node in descending order.
* The reasoning to sort based on criterion 1 is so we schedule the rest of a topology on the same node as the existing executors of the topology.
* 2) the subordinate/subservient resource availability percentage of a node in descending order
* We calculate the resource availability percentage by dividing the resource availability on the node by the resource availability of the entire rack
* By doing this calculation, nodes that have exhausted or little of one of the resources mentioned above will be ranked after nodes that have more balanced resource availability.
* So we will be less likely to pick a node that have a lot of one resource but a low amount of another.
*/
private TreeSet<ObjectResources> sortNodes(List<RAS_Node> availNodes, String rackId, final String topoId, final Map<WorkerSlot, Collection<ExecutorDetails>> scheduleAssignmentMap) {
AllResources allResources = new AllResources("RACK");
List<ObjectResources> nodes = allResources.objectResources;
final Map<String, String> nodeIdToRackId = new HashMap<String, String>();
for (RAS_Node ras_node : availNodes) {
String nodeId = ras_node.getId();
ObjectResources node = new ObjectResources(nodeId);
double availMem = ras_node.getAvailableMemoryResources();
double availCpu = ras_node.getAvailableCpuResources();
int freeSlots = ras_node.totalSlotsFree();
double totalMem = ras_node.getTotalMemoryResources();
double totalCpu = ras_node.getTotalCpuResources();
int totalSlots = ras_node.totalSlots();
node.availMem = availMem;
node.totalMem = totalMem;
node.availCpu = availCpu;
node.totalCpu = totalCpu;
nodes.add(node);
allResources.availMemResourcesOverall += availMem;
allResources.availCpuResourcesOverall += availCpu;
allResources.totalMemResourcesOverall += totalMem;
allResources.totalCpuResourcesOverall += totalCpu;
}
LOG.debug("Rack {}: Overall Avail [ CPU {} MEM {} ] Total [ CPU {} MEM {} ]", rackId, allResources.availCpuResourcesOverall, allResources.availMemResourcesOverall, allResources.totalCpuResourcesOverall, allResources.totalMemResourcesOverall);
return sortObjectResources(allResources, new ExistingScheduleFunc() {
@Override
public int getNumExistingSchedule(String objectId) {
//Get execs already assigned in rack
Collection<ExecutorDetails> execs = new LinkedList<ExecutorDetails>();
if (_cluster.getAssignmentById(topoId) != null) {
for (Map.Entry<ExecutorDetails, WorkerSlot> entry : _cluster.getAssignmentById(topoId).getExecutorToSlot().entrySet()) {
WorkerSlot workerSlot = entry.getValue();
ExecutorDetails exec = entry.getKey();
if (workerSlot.getNodeId().equals(objectId)) {
execs.add(exec);
}
}
}
// get execs already scheduled in the current scheduling
for (Map.Entry<WorkerSlot, Collection<ExecutorDetails>> entry : scheduleAssignmentMap.entrySet()) {
WorkerSlot workerSlot = entry.getKey();
if (workerSlot.getNodeId().equals(objectId)) {
execs.addAll(entry.getValue());
}
}
return execs.size();
}
});
}
use of org.apache.storm.scheduler.WorkerSlot in project storm by apache.
the class DefaultResourceAwareStrategy method scheduleExecutor.
/**
* Schedule executor exec from topology td
*
* @param exec the executor to schedule
* @param td the topology executor exec is a part of
* @param schedulerAssignmentMap the assignments already calculated
* @param scheduledTasks executors that have been scheduled
*/
private void scheduleExecutor(ExecutorDetails exec, TopologyDetails td, Map<WorkerSlot, Collection<ExecutorDetails>> schedulerAssignmentMap, Collection<ExecutorDetails> scheduledTasks) {
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: {} on Rack: {}", exec, targetNode.getHostname(), targetNode.getAvailableMemoryResources(), targetNode.getAvailableCpuResources(), targetNode.getTotalMemoryResources(), targetNode.getTotalCpuResources(), targetSlot, nodeToRack(targetNode));
} else {
LOG.error("Not Enough Resources to schedule Task {}", exec);
}
}
Aggregations