Search in sources :

Example 6 with ProportionalCapacityPreemptionPolicy

use of org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy in project hadoop by apache.

the class TestCapacitySchedulerSurgicalPreemption method testPriorityPreemptionOnlyTriggeredWhenDemandingQueueUnsatisfied.

@Test(timeout = 60000)
public void testPriorityPreemptionOnlyTriggeredWhenDemandingQueueUnsatisfied() throws Exception {
    /**
     * Test case: Submit two application (app1/app2) to different queues, queue
     * structure:
     *
     * <pre>
     *             Root
     *            /  |  \
     *           a   b   c
     *          10   20  70
     * </pre>
     *
     * 1) 10 nodes (n0-n9) in the cluster, each of them has 10G.
     *
     * 2) app1 submit to queue-b first, it asked 8 * 1G containers
     * We will allocate 1 container on each of n0-n10
     *
     * 3) app2 submit to queue-c, ask for 10 * 10G containers (including AM)
     *
     * After preemption, we should expect:
     * Preempt 7 containers from app1 and usage of app2 is 70%
     */
    conf.setPUOrderingPolicyUnderUtilizedPreemptionEnabled(true);
    conf.setPUOrderingPolicyUnderUtilizedPreemptionDelay(1000);
    conf.setQueueOrderingPolicy(CapacitySchedulerConfiguration.ROOT, CapacitySchedulerConfiguration.QUEUE_PRIORITY_UTILIZATION_ORDERING_POLICY);
    // Queue c has higher priority than a/b
    conf.setQueuePriority(CapacitySchedulerConfiguration.ROOT + ".c", 1);
    MockRM rm1 = new MockRM(conf);
    rm1.getRMContext().setNodeLabelManager(mgr);
    rm1.start();
    MockNM[] mockNMs = new MockNM[10];
    for (int i = 0; i < 10; i++) {
        mockNMs[i] = rm1.registerNode("h" + i + ":1234", 10 * GB);
    }
    CapacityScheduler cs = (CapacityScheduler) rm1.getResourceScheduler();
    RMNode[] rmNodes = new RMNode[10];
    for (int i = 0; i < 10; i++) {
        rmNodes[i] = rm1.getRMContext().getRMNodes().get(mockNMs[i].getNodeId());
    }
    // launch an app to queue, AM container should be launched in nm1
    RMApp app1 = rm1.submitApp(1 * GB, "app", "user", null, "b");
    MockAM am1 = MockRM.launchAndRegisterAM(app1, rm1, mockNMs[0]);
    am1.allocate("*", 1 * GB, 8, new ArrayList<>());
    // Do allocation for nm1-nm8
    for (int i = 1; i < 9; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    // App1 should have 9 containers now, so the abs-used-cap of b is 9%
    FiCaSchedulerApp schedulerApp1 = cs.getApplicationAttempt(am1.getApplicationAttemptId());
    Assert.assertEquals(9, schedulerApp1.getLiveContainers().size());
    for (int i = 0; i < 9; i++) {
        waitNumberOfLiveContainersOnNodeFromApp(cs.getNode(rmNodes[i].getNodeID()), am1.getApplicationAttemptId(), 1);
    }
    // Submit app2 to queue-c and asks for a 10G container for AM
    // Launch AM in NM9
    RMApp app2 = rm1.submitApp(10 * GB, "app", "user", null, "c");
    MockAM am2 = MockRM.launchAndRegisterAM(app2, rm1, mockNMs[9]);
    FiCaSchedulerApp schedulerApp2 = cs.getApplicationAttempt(ApplicationAttemptId.newInstance(app2.getApplicationId(), 1));
    // Ask 10 * 10GB containers
    am2.allocate("*", 10 * GB, 10, new ArrayList<>());
    // Do allocation for all nms
    for (int i = 1; i < 10; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    // Check am2 reserved resource from nm1-nm9
    for (int i = 1; i < 9; i++) {
        Assert.assertNotNull("Should reserve on nm-" + i, cs.getNode(rmNodes[i].getNodeID()).getReservedContainer());
    }
    // Sleep the timeout interval, we should be able to see 6 containers selected
    // 6 (selected) + 1 (allocated) which makes target capacity to 70%
    Thread.sleep(1000);
    ProportionalCapacityPreemptionPolicy editPolicy = (ProportionalCapacityPreemptionPolicy) getSchedulingEditPolicy(rm1);
    editPolicy.editSchedule();
    checkNumberOfPreemptionCandidateFromApp(editPolicy, 6, am1.getApplicationAttemptId());
    // Call editSchedule again: selected containers are killed
    editPolicy.editSchedule();
    waitNumberOfLiveContainersFromApp(schedulerApp1, 3);
    // Do allocation for all nms
    for (int i = 1; i < 10; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    waitNumberOfLiveContainersFromApp(schedulerApp2, 7);
    waitNumberOfLiveContainersFromApp(schedulerApp1, 3);
    rm1.close();
}
Also used : RMApp(org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp) NodeUpdateSchedulerEvent(org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.NodeUpdateSchedulerEvent) MockNM(org.apache.hadoop.yarn.server.resourcemanager.MockNM) MockRM(org.apache.hadoop.yarn.server.resourcemanager.MockRM) ProportionalCapacityPreemptionPolicy(org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy) RMNode(org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode) FiCaSchedulerApp(org.apache.hadoop.yarn.server.resourcemanager.scheduler.common.fica.FiCaSchedulerApp) MockAM(org.apache.hadoop.yarn.server.resourcemanager.MockAM) Test(org.junit.Test)

Example 7 with ProportionalCapacityPreemptionPolicy

use of org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy in project hadoop by apache.

the class TestCapacitySchedulerSurgicalPreemption method testPriorityPreemptionFromHighestPriorityQueueAndOldestContainer.

@Test(timeout = 600000)
public void testPriorityPreemptionFromHighestPriorityQueueAndOldestContainer() throws Exception {
    /**
     * Test case: Submit two application (app1/app2) to different queues, queue
     * structure:
     *
     * <pre>
     *             Root
     *            /  |  \
     *           a   b   c
     *          45  45  10
     * </pre>
     *
     * Priority of queue_a = 1
     * Priority of queue_b = 2
     *
     * 1) 5 nodes (n0-n4) in the cluster, each of them has 4G.
     *
     * 2) app1 submit to queue-c first (AM=1G), it asked 4 * 1G containers
     *    We will allocate 1 container on each of n0-n4. AM on n4.
     *
     * 3) app2 submit to queue-a, AM container=0.5G, allocated on n0
     *    Ask for 2 * 3.5G containers. (Reserved on n0/n1)
     *
     * 4) app2 submit to queue-b, AM container=0.5G, allocated on n2
     *    Ask for 2 * 3.5G containers. (Reserved on n2/n3)
     *
     * First we will preempt container on n2 since it is the oldest container of
     * Highest priority queue (b)
     */
    // Total preemption = 1G per round, which is 5% of cluster resource (20G)
    conf.setFloat(CapacitySchedulerConfiguration.TOTAL_PREEMPTION_PER_ROUND, 0.05f);
    conf.setInt(YarnConfiguration.RM_SCHEDULER_MINIMUM_ALLOCATION_MB, 512);
    conf.setPUOrderingPolicyUnderUtilizedPreemptionEnabled(true);
    conf.setPUOrderingPolicyUnderUtilizedPreemptionDelay(1000);
    conf.setQueueOrderingPolicy(CapacitySchedulerConfiguration.ROOT, CapacitySchedulerConfiguration.QUEUE_PRIORITY_UTILIZATION_ORDERING_POLICY);
    // A/B has higher priority
    conf.setQueuePriority(CapacitySchedulerConfiguration.ROOT + ".a", 1);
    conf.setQueuePriority(CapacitySchedulerConfiguration.ROOT + ".b", 2);
    conf.setCapacity(CapacitySchedulerConfiguration.ROOT + ".a", 45f);
    conf.setCapacity(CapacitySchedulerConfiguration.ROOT + ".b", 45f);
    conf.setCapacity(CapacitySchedulerConfiguration.ROOT + ".c", 10f);
    MockRM rm1 = new MockRM(conf);
    rm1.getRMContext().setNodeLabelManager(mgr);
    rm1.start();
    MockNM[] mockNMs = new MockNM[5];
    for (int i = 0; i < 5; i++) {
        mockNMs[i] = rm1.registerNode("h" + i + ":1234", 4 * GB);
    }
    CapacityScheduler cs = (CapacityScheduler) rm1.getResourceScheduler();
    RMNode[] rmNodes = new RMNode[5];
    for (int i = 0; i < 5; i++) {
        rmNodes[i] = rm1.getRMContext().getRMNodes().get(mockNMs[i].getNodeId());
    }
    // launch an app to queue, AM container should be launched in nm1
    RMApp app1 = rm1.submitApp(1 * GB, "app", "user", null, "c");
    MockAM am1 = MockRM.launchAndRegisterAM(app1, rm1, mockNMs[4]);
    am1.allocate("*", 1 * GB, 4, new ArrayList<>());
    // Do allocation for nm1-nm8
    for (int i = 0; i < 4; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    // App1 should have 5 containers now, one for each node
    FiCaSchedulerApp schedulerApp1 = cs.getApplicationAttempt(am1.getApplicationAttemptId());
    Assert.assertEquals(5, schedulerApp1.getLiveContainers().size());
    for (int i = 0; i < 5; i++) {
        waitNumberOfLiveContainersOnNodeFromApp(cs.getNode(rmNodes[i].getNodeID()), am1.getApplicationAttemptId(), 1);
    }
    // Submit app2 to queue-a and asks for a 0.5G container for AM (on n0)
    RMApp app2 = rm1.submitApp(512, "app", "user", null, "a");
    MockAM am2 = MockRM.launchAndRegisterAM(app2, rm1, mockNMs[0]);
    FiCaSchedulerApp schedulerApp2 = cs.getApplicationAttempt(ApplicationAttemptId.newInstance(app2.getApplicationId(), 1));
    // Ask 2 * 3.5GB containers
    am2.allocate("*", 3 * GB + 512, 2, new ArrayList<>());
    // Do allocation for n0-n1
    for (int i = 0; i < 2; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    // Check am2 reserved resource from nm0-nm1
    for (int i = 0; i < 2; i++) {
        Assert.assertNotNull("Should reserve on nm-" + i, cs.getNode(rmNodes[i].getNodeID()).getReservedContainer());
        Assert.assertEquals(cs.getNode(rmNodes[i].getNodeID()).getReservedContainer().getQueueName(), "a");
    }
    // Submit app3 to queue-b and asks for a 0.5G container for AM (on n2)
    RMApp app3 = rm1.submitApp(512, "app", "user", null, "b");
    MockAM am3 = MockRM.launchAndRegisterAM(app3, rm1, mockNMs[2]);
    FiCaSchedulerApp schedulerApp3 = cs.getApplicationAttempt(ApplicationAttemptId.newInstance(app3.getApplicationId(), 1));
    // Ask 2 * 3.5GB containers
    am3.allocate("*", 3 * GB + 512, 2, new ArrayList<>());
    // Do allocation for n2-n3
    for (int i = 2; i < 4; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    // Check am2 reserved resource from nm2-nm3
    for (int i = 2; i < 4; i++) {
        Assert.assertNotNull("Should reserve on nm-" + i, cs.getNode(rmNodes[i].getNodeID()).getReservedContainer());
        Assert.assertEquals(cs.getNode(rmNodes[i].getNodeID()).getReservedContainer().getQueueName(), "b");
    }
    // Sleep the timeout interval, we should be able to see 1 container selected
    Thread.sleep(1000);
    /* 1st container preempted is on n2 */
    ProportionalCapacityPreemptionPolicy editPolicy = (ProportionalCapacityPreemptionPolicy) getSchedulingEditPolicy(rm1);
    editPolicy.editSchedule();
    // We should have one to-preempt container, on node[2]
    Set<RMContainer> selectedToPreempt = editPolicy.getToPreemptContainers().keySet();
    Assert.assertEquals(1, selectedToPreempt.size());
    Assert.assertEquals(mockNMs[2].getNodeId(), selectedToPreempt.iterator().next().getAllocatedNode());
    // Call editSchedule again: selected containers are killed
    editPolicy.editSchedule();
    waitNumberOfLiveContainersFromApp(schedulerApp1, 4);
    // Make sure the container killed, then do allocation for all nms
    for (int i = 0; i < 4; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    waitNumberOfLiveContainersFromApp(schedulerApp1, 4);
    waitNumberOfLiveContainersFromApp(schedulerApp2, 1);
    waitNumberOfLiveContainersFromApp(schedulerApp3, 2);
    /* 2nd container preempted is on n3 */
    editPolicy.editSchedule();
    // We should have one to-preempt container, on node[3]
    selectedToPreempt = editPolicy.getToPreemptContainers().keySet();
    Assert.assertEquals(1, selectedToPreempt.size());
    Assert.assertEquals(mockNMs[3].getNodeId(), selectedToPreempt.iterator().next().getAllocatedNode());
    // Call editSchedule again: selected containers are killed
    editPolicy.editSchedule();
    waitNumberOfLiveContainersFromApp(schedulerApp1, 3);
    // Do allocation for all nms
    for (int i = 0; i < 4; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    waitNumberOfLiveContainersFromApp(schedulerApp1, 3);
    waitNumberOfLiveContainersFromApp(schedulerApp2, 1);
    waitNumberOfLiveContainersFromApp(schedulerApp3, 3);
    /* 3rd container preempted is on n0 */
    editPolicy.editSchedule();
    // We should have one to-preempt container, on node[0]
    selectedToPreempt = editPolicy.getToPreemptContainers().keySet();
    Assert.assertEquals(1, selectedToPreempt.size());
    Assert.assertEquals(mockNMs[0].getNodeId(), selectedToPreempt.iterator().next().getAllocatedNode());
    // Call editSchedule again: selected containers are killed
    editPolicy.editSchedule();
    waitNumberOfLiveContainersFromApp(schedulerApp1, 2);
    // Do allocation for all nms
    for (int i = 0; i < 4; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    waitNumberOfLiveContainersFromApp(schedulerApp1, 2);
    waitNumberOfLiveContainersFromApp(schedulerApp2, 2);
    waitNumberOfLiveContainersFromApp(schedulerApp3, 3);
    /* 4th container preempted is on n1 */
    editPolicy.editSchedule();
    // We should have one to-preempt container, on node[0]
    selectedToPreempt = editPolicy.getToPreemptContainers().keySet();
    Assert.assertEquals(1, selectedToPreempt.size());
    Assert.assertEquals(mockNMs[1].getNodeId(), selectedToPreempt.iterator().next().getAllocatedNode());
    // Call editSchedule again: selected containers are killed
    editPolicy.editSchedule();
    waitNumberOfLiveContainersFromApp(schedulerApp1, 1);
    // Do allocation for all nms
    for (int i = 0; i < 4; i++) {
        cs.handle(new NodeUpdateSchedulerEvent(rmNodes[i]));
    }
    waitNumberOfLiveContainersFromApp(schedulerApp1, 1);
    waitNumberOfLiveContainersFromApp(schedulerApp2, 3);
    waitNumberOfLiveContainersFromApp(schedulerApp3, 3);
    rm1.close();
}
Also used : RMApp(org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp) NodeUpdateSchedulerEvent(org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.NodeUpdateSchedulerEvent) MockNM(org.apache.hadoop.yarn.server.resourcemanager.MockNM) MockRM(org.apache.hadoop.yarn.server.resourcemanager.MockRM) ProportionalCapacityPreemptionPolicy(org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy) RMContainer(org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainer) RMNode(org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode) FiCaSchedulerApp(org.apache.hadoop.yarn.server.resourcemanager.scheduler.common.fica.FiCaSchedulerApp) MockAM(org.apache.hadoop.yarn.server.resourcemanager.MockAM) Test(org.junit.Test)

Aggregations

MockAM (org.apache.hadoop.yarn.server.resourcemanager.MockAM)7 MockNM (org.apache.hadoop.yarn.server.resourcemanager.MockNM)7 MockRM (org.apache.hadoop.yarn.server.resourcemanager.MockRM)7 ProportionalCapacityPreemptionPolicy (org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy)7 RMApp (org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp)7 RMNode (org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode)7 FiCaSchedulerApp (org.apache.hadoop.yarn.server.resourcemanager.scheduler.common.fica.FiCaSchedulerApp)7 NodeUpdateSchedulerEvent (org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.NodeUpdateSchedulerEvent)7 Test (org.junit.Test)7 ContainerId (org.apache.hadoop.yarn.api.records.ContainerId)3 RMContainer (org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainer)2 PreemptionManager (org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.preemption.PreemptionManager)2 HashSet (java.util.HashSet)1 Ignore (org.junit.Ignore)1