Search in sources :

Example 1 with SchedulingResult

use of org.apache.storm.scheduler.resource.SchedulingResult 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;
}
Also used : ExecutorDetails(org.apache.storm.scheduler.ExecutorDetails) HashMap(java.util.HashMap) WorkerSlot(org.apache.storm.scheduler.WorkerSlot) ArrayList(java.util.ArrayList) Collection(java.util.Collection) Component(org.apache.storm.scheduler.resource.Component) SchedulingResult(org.apache.storm.scheduler.resource.SchedulingResult) HashSet(java.util.HashSet)

Example 2 with SchedulingResult

use of org.apache.storm.scheduler.resource.SchedulingResult in project storm by apache.

the class BaseResourceAwareStrategy method schedule.

/**
 * Note that this method is not thread-safe.
 * Several instance variables are generated from supplied
 * parameters. In addition, the following instance variables are set to complete scheduling:
 *  <li>{@link #searcherState}</li>
 *  <li>{@link #execSorter} to sort executors</li>
 *  <li>{@link #nodeSorter} to sort nodes</li>
 * <p>
 * Scheduling consists of three main steps:
 *  <li>{@link #prepareForScheduling(Cluster, TopologyDetails)}</li>
 *  <li>{@link #checkSchedulingFeasibility()}, and</li>
 *  <li>{@link #scheduleExecutorsOnNodes(List, Iterable)}</li>
 * </p><p>
 * The executors and nodes are sorted in the order most conducive to scheduling for the strategy.
 * Those interfaces may be overridden by subclasses using mutators:
 *  <li>{@link #setExecSorter(IExecSorter)} and</li>
 *  <li>{@link #setNodeSorter(INodeSorter)}</li>
 *</p>
 *
 * @param cluster on which executors will be scheduled.
 * @param td the topology to schedule for.
 * @return result of scheduling (success, failure, or null when interrupted).
 */
@Override
public SchedulingResult schedule(Cluster cluster, TopologyDetails td) {
    prepareForScheduling(cluster, td);
    // early detection of success or failure
    SchedulingResult earlyResult = checkSchedulingFeasibility();
    if (earlyResult != null) {
        return earlyResult;
    }
    LOG.debug("Topology {} {} Number of ExecutorsNeedScheduling: {}", topoName, topologyDetails.getId(), unassignedExecutors.size());
    // order executors to be scheduled
    List<ExecutorDetails> orderedExecutors = execSorter.sortExecutors(unassignedExecutors);
    Iterable<String> sortedNodes = null;
    if (!this.sortNodesForEachExecutor) {
        nodeSorter.prepare(null);
        sortedNodes = nodeSorter.sortAllNodes();
    }
    return scheduleExecutorsOnNodes(orderedExecutors, sortedNodes);
}
Also used : ExecutorDetails(org.apache.storm.scheduler.ExecutorDetails) SchedulingResult(org.apache.storm.scheduler.resource.SchedulingResult)

Example 3 with SchedulingResult

use of org.apache.storm.scheduler.resource.SchedulingResult in project storm by apache.

the class TestConstraintSolverStrategy method basicFailureTest.

public void basicFailureTest(String confKey, Object confValue, ConstraintSolverStrategy cs) {
    Map<String, Object> config = makeTestTopoConf();
    config.put(confKey, confValue);
    cs.prepare(config);
    TopologyDetails topo = makeTopology(config, NORMAL_BOLT_PARALLEL);
    Topologies topologies = new Topologies(topo);
    Cluster cluster = makeCluster(topologies);
    LOG.info("Scheduling...");
    SchedulingResult result = cs.schedule(cluster, topo);
    LOG.info("Done scheduling {}...", result);
    Assert.assertTrue("Assert scheduling topology success " + result, !result.isSuccess());
}
Also used : Topologies(org.apache.storm.scheduler.Topologies) Cluster(org.apache.storm.scheduler.Cluster) SchedulingResult(org.apache.storm.scheduler.resource.SchedulingResult) TopologyDetails(org.apache.storm.scheduler.TopologyDetails)

Example 4 with SchedulingResult

use of org.apache.storm.scheduler.resource.SchedulingResult in project storm by apache.

the class TestConstraintSolverStrategy method basicUnitTestWithKillAndRecover.

public void basicUnitTestWithKillAndRecover(ConstraintSolverStrategy cs, int boltParallel, int coLocationCnt) {
    Map<String, Object> config = makeTestTopoConf(coLocationCnt);
    cs.prepare(config);
    TopologyDetails topo = makeTopology(config, boltParallel);
    Topologies topologies = new Topologies(topo);
    Cluster cluster = makeCluster(topologies);
    LOG.info("Scheduling...");
    SchedulingResult result = cs.schedule(cluster, topo);
    LOG.info("Done scheduling {}...", result);
    Assert.assertTrue("Assert scheduling topology success " + result, result.isSuccess());
    Assert.assertEquals("Assert no unassigned executors, found unassigned: " + cluster.getUnassignedExecutors(topo), 0, cluster.getUnassignedExecutors(topo).size());
    Assert.assertTrue("Valid Scheduling?", ConstraintSolverStrategy.validateSolution(cluster, topo));
    LOG.info("Slots Used {}", cluster.getAssignmentById(topo.getId()).getSlots());
    LOG.info("Assignment {}", cluster.getAssignmentById(topo.getId()).getSlotToExecutors());
    // simulate worker loss
    SchedulerAssignment assignment = cluster.getAssignmentById(topo.getId());
    Set<WorkerSlot> slotsToDelete = new HashSet<>();
    Set<WorkerSlot> slots = assignment.getSlots();
    int i = 0;
    for (WorkerSlot slot : slots) {
        if (i % 2 == 0) {
            slotsToDelete.add(slot);
        }
        i++;
    }
    LOG.info("KILL WORKER(s) {}", slotsToDelete);
    for (WorkerSlot slot : slotsToDelete) {
        cluster.freeSlot(slot);
    }
    cs = new ConstraintSolverStrategy();
    cs.prepare(config);
    LOG.info("Scheduling again...");
    result = cs.schedule(cluster, topo);
    LOG.info("Done scheduling {}...", result);
    Assert.assertTrue("Assert scheduling topology success " + result, result.isSuccess());
    Assert.assertEquals("topo all executors scheduled?", 0, cluster.getUnassignedExecutors(topo).size());
    Assert.assertTrue("Valid Scheduling?", ConstraintSolverStrategy.validateSolution(cluster, topo));
}
Also used : Cluster(org.apache.storm.scheduler.Cluster) SchedulingResult(org.apache.storm.scheduler.resource.SchedulingResult) TopologyDetails(org.apache.storm.scheduler.TopologyDetails) SchedulerAssignment(org.apache.storm.scheduler.SchedulerAssignment) WorkerSlot(org.apache.storm.scheduler.WorkerSlot) Topologies(org.apache.storm.scheduler.Topologies) HashSet(java.util.HashSet)

Example 5 with SchedulingResult

use of org.apache.storm.scheduler.resource.SchedulingResult in project storm by apache.

the class TestDefaultResourceAwareStrategy method testMultipleRacks.

/**
 * Test whether strategy will choose correct rack
 */
@Test
public void testMultipleRacks() {
    final Map<String, SupervisorDetails> supMap = new HashMap<>();
    final Map<String, SupervisorDetails> supMapRack0 = genSupervisors(10, 4, 0, 400, 8000);
    // generate another rack of supervisors with less resources
    final Map<String, SupervisorDetails> supMapRack1 = genSupervisors(10, 4, 10, 200, 4000);
    // generate some supervisors that are depleted of one resource
    final Map<String, SupervisorDetails> supMapRack2 = genSupervisors(10, 4, 20, 0, 8000);
    // generate some that has alot of memory but little of cpu
    final Map<String, SupervisorDetails> supMapRack3 = genSupervisors(10, 4, 30, 10, 8000 * 2 + 4000);
    // generate some that has alot of cpu but little of memory
    final Map<String, SupervisorDetails> supMapRack4 = genSupervisors(10, 4, 40, 400 + 200 + 10, 1000);
    // Generate some that have neither resource, to verify that the strategy will prioritize this last
    // Also put a generic resource with 0 value in the resources list, to verify that it doesn't affect the sorting
    final Map<String, SupervisorDetails> supMapRack5 = genSupervisors(10, 4, 50, 0.0, 0.0, Collections.singletonMap("gpu.count", 0.0));
    supMap.putAll(supMapRack0);
    supMap.putAll(supMapRack1);
    supMap.putAll(supMapRack2);
    supMap.putAll(supMapRack3);
    supMap.putAll(supMapRack4);
    supMap.putAll(supMapRack5);
    Config config = createClusterConfig(100, 500, 500, null);
    config.put(Config.TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB, Double.MAX_VALUE);
    INimbus iNimbus = new INimbusTest();
    // create test DNSToSwitchMapping plugin
    DNSToSwitchMapping TestNetworkTopographyPlugin = new TestDNSToSwitchMapping(supMapRack0, supMapRack1, supMapRack2, supMapRack3, supMapRack4, supMapRack5);
    // generate topologies
    TopologyDetails topo1 = genTopology("topo-1", config, 8, 0, 2, 0, CURRENT_TIME - 2, 10, "user");
    TopologyDetails topo2 = genTopology("topo-2", config, 8, 0, 2, 0, CURRENT_TIME - 2, 10, "user");
    Topologies topologies = new Topologies(topo1, topo2);
    Cluster cluster = new Cluster(iNimbus, new ResourceMetrics(new StormMetricsRegistry()), supMap, new HashMap<>(), topologies, config);
    List<String> supHostnames = new LinkedList<>();
    for (SupervisorDetails sup : supMap.values()) {
        supHostnames.add(sup.getHost());
    }
    Map<String, List<String>> rackToNodes = new HashMap<>();
    Map<String, String> resolvedSuperVisors = TestNetworkTopographyPlugin.resolve(supHostnames);
    for (Map.Entry<String, String> entry : resolvedSuperVisors.entrySet()) {
        String hostName = entry.getKey();
        String rack = entry.getValue();
        rackToNodes.computeIfAbsent(rack, rid -> new ArrayList<>()).add(hostName);
    }
    cluster.setNetworkTopography(rackToNodes);
    DefaultResourceAwareStrategyOld rs = new DefaultResourceAwareStrategyOld();
    rs.prepareForScheduling(cluster, topo1);
    INodeSorter nodeSorter = new NodeSorterHostProximity(cluster, topo1, BaseResourceAwareStrategy.NodeSortType.DEFAULT_RAS);
    nodeSorter.prepare(null);
    Iterable<ObjectResourcesItem> sortedRacks = nodeSorter.getSortedRacks();
    Iterator<ObjectResourcesItem> it = sortedRacks.iterator();
    // Ranked first since rack-0 has the most balanced set of resources
    Assert.assertEquals("rack-0 should be ordered first", "rack-0", it.next().id);
    // Ranked second since rack-1 has a balanced set of resources but less than rack-0
    Assert.assertEquals("rack-1 should be ordered second", "rack-1", it.next().id);
    // Ranked third since rack-4 has a lot of cpu but not a lot of memory
    Assert.assertEquals("rack-4 should be ordered third", "rack-4", it.next().id);
    // Ranked fourth since rack-3 has alot of memory but not cpu
    Assert.assertEquals("rack-3 should be ordered fourth", "rack-3", it.next().id);
    // Ranked fifth since rack-2 has not cpu resources
    Assert.assertEquals("rack-2 should be ordered fifth", "rack-2", it.next().id);
    // Ranked last since rack-5 has neither CPU nor memory available
    assertEquals("Rack-5 should be ordered sixth", "rack-5", it.next().id);
    SchedulingResult schedulingResult = rs.schedule(cluster, topo1);
    assert (schedulingResult.isSuccess());
    SchedulerAssignment assignment = cluster.getAssignmentById(topo1.getId());
    for (WorkerSlot ws : assignment.getSlotToExecutors().keySet()) {
        // make sure all workers on scheduled in rack-0
        Assert.assertEquals("assert worker scheduled on rack-0", "rack-0", resolvedSuperVisors.get(rs.idToNode(ws.getNodeId()).getHostname()));
    }
    Assert.assertEquals("All executors in topo-1 scheduled", 0, cluster.getUnassignedExecutors(topo1).size());
    // Test if topology is already partially scheduled on one rack
    Iterator<ExecutorDetails> executorIterator = topo2.getExecutors().iterator();
    List<String> nodeHostnames = rackToNodes.get("rack-1");
    for (int i = 0; i < topo2.getExecutors().size() / 2; i++) {
        String nodeHostname = nodeHostnames.get(i % nodeHostnames.size());
        RasNode node = rs.hostnameToNodes(nodeHostname).get(0);
        WorkerSlot targetSlot = node.getFreeSlots().iterator().next();
        ExecutorDetails targetExec = executorIterator.next();
        // to keep track of free slots
        node.assign(targetSlot, topo2, Arrays.asList(targetExec));
    }
    rs = new DefaultResourceAwareStrategyOld();
    // schedule topo2
    schedulingResult = rs.schedule(cluster, topo2);
    assert (schedulingResult.isSuccess());
    assignment = cluster.getAssignmentById(topo2.getId());
    for (WorkerSlot ws : assignment.getSlotToExecutors().keySet()) {
        // make sure all workers on scheduled in rack-1
        Assert.assertEquals("assert worker scheduled on rack-1", "rack-1", resolvedSuperVisors.get(rs.idToNode(ws.getNodeId()).getHostname()));
    }
    Assert.assertEquals("All executors in topo-2 scheduled", 0, cluster.getUnassignedExecutors(topo2).size());
}
Also used : Arrays(java.util.Arrays) LoggerFactory(org.slf4j.LoggerFactory) INimbus(org.apache.storm.scheduler.INimbus) SupervisorResources(org.apache.storm.scheduler.SupervisorResources) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Matchers.closeTo(org.hamcrest.Matchers.closeTo) ResourceMetrics(org.apache.storm.scheduler.resource.normalization.ResourceMetrics) WorkerSlot(org.apache.storm.scheduler.WorkerSlot) Map(java.util.Map) TopologyBuilder(org.apache.storm.topology.TopologyBuilder) NodeSorterHostProximity(org.apache.storm.scheduler.resource.strategies.scheduling.sorter.NodeSorterHostProximity) SchedulerAssignment(org.apache.storm.scheduler.SchedulerAssignment) DNSToSwitchMapping(org.apache.storm.networktopography.DNSToSwitchMapping) Collection(java.util.Collection) TopologyDetails(org.apache.storm.scheduler.TopologyDetails) Collectors(java.util.stream.Collectors) SharedOnHeap(org.apache.storm.topology.SharedOnHeap) Test(org.junit.jupiter.api.Test) WorkerResources(org.apache.storm.generated.WorkerResources) List(java.util.List) TestUtilsForResourceAwareScheduler(org.apache.storm.scheduler.resource.TestUtilsForResourceAwareScheduler) Entry(java.util.Map.Entry) Config(org.apache.storm.Config) Matchers.is(org.hamcrest.Matchers.is) InvalidTopologyException(org.apache.storm.generated.InvalidTopologyException) StormCommon(org.apache.storm.daemon.StormCommon) ExecutorDetails(org.apache.storm.scheduler.ExecutorDetails) IScheduler(org.apache.storm.scheduler.IScheduler) RasNode(org.apache.storm.scheduler.resource.RasNode) SharedOffHeapWithinNode(org.apache.storm.topology.SharedOffHeapWithinNode) NodeSorter(org.apache.storm.scheduler.resource.strategies.scheduling.sorter.NodeSorter) EnumSource(org.junit.jupiter.params.provider.EnumSource) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Topologies(org.apache.storm.scheduler.Topologies) ServerUtils(org.apache.storm.utils.ServerUtils) StormTopology(org.apache.storm.generated.StormTopology) NormalizedResourcesExtension(org.apache.storm.scheduler.resource.normalization.NormalizedResourcesExtension) LinkedList(java.util.LinkedList) StormMetricsRegistry(org.apache.storm.metric.StormMetricsRegistry) ValueSource(org.junit.jupiter.params.provider.ValueSource) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) SharedOffHeapWithinWorker(org.apache.storm.topology.SharedOffHeapWithinWorker) INodeSorter(org.apache.storm.scheduler.resource.strategies.scheduling.sorter.INodeSorter) SupervisorDetails(org.apache.storm.scheduler.SupervisorDetails) TopologyResources(org.apache.storm.daemon.nimbus.TopologyResources) Cluster(org.apache.storm.scheduler.Cluster) ResourceAwareScheduler(org.apache.storm.scheduler.resource.ResourceAwareScheduler) SchedulingResult(org.apache.storm.scheduler.resource.SchedulingResult) Nimbus(org.apache.storm.daemon.nimbus.Nimbus) AfterEach(org.junit.jupiter.api.AfterEach) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Assert(org.junit.Assert) Collections(java.util.Collections) ExecutorDetails(org.apache.storm.scheduler.ExecutorDetails) HashMap(java.util.HashMap) Config(org.apache.storm.Config) StormMetricsRegistry(org.apache.storm.metric.StormMetricsRegistry) ArrayList(java.util.ArrayList) NodeSorterHostProximity(org.apache.storm.scheduler.resource.strategies.scheduling.sorter.NodeSorterHostProximity) SchedulingResult(org.apache.storm.scheduler.resource.SchedulingResult) ResourceMetrics(org.apache.storm.scheduler.resource.normalization.ResourceMetrics) INodeSorter(org.apache.storm.scheduler.resource.strategies.scheduling.sorter.INodeSorter) WorkerSlot(org.apache.storm.scheduler.WorkerSlot) RasNode(org.apache.storm.scheduler.resource.RasNode) DNSToSwitchMapping(org.apache.storm.networktopography.DNSToSwitchMapping) Topologies(org.apache.storm.scheduler.Topologies) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) SupervisorDetails(org.apache.storm.scheduler.SupervisorDetails) Cluster(org.apache.storm.scheduler.Cluster) INimbus(org.apache.storm.scheduler.INimbus) TopologyDetails(org.apache.storm.scheduler.TopologyDetails) LinkedList(java.util.LinkedList) SchedulerAssignment(org.apache.storm.scheduler.SchedulerAssignment) Map(java.util.Map) HashMap(java.util.HashMap) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Aggregations

SchedulingResult (org.apache.storm.scheduler.resource.SchedulingResult)6 Cluster (org.apache.storm.scheduler.Cluster)4 ExecutorDetails (org.apache.storm.scheduler.ExecutorDetails)4 Topologies (org.apache.storm.scheduler.Topologies)4 TopologyDetails (org.apache.storm.scheduler.TopologyDetails)4 WorkerSlot (org.apache.storm.scheduler.WorkerSlot)4 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 SchedulerAssignment (org.apache.storm.scheduler.SchedulerAssignment)3 Collection (java.util.Collection)2 LinkedList (java.util.LinkedList)2 List (java.util.List)2 Map (java.util.Map)2 Config (org.apache.storm.Config)2 StormMetricsRegistry (org.apache.storm.metric.StormMetricsRegistry)2 DNSToSwitchMapping (org.apache.storm.networktopography.DNSToSwitchMapping)2 INimbus (org.apache.storm.scheduler.INimbus)2 SupervisorDetails (org.apache.storm.scheduler.SupervisorDetails)2 RasNode (org.apache.storm.scheduler.resource.RasNode)2