All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.fenzo.samples.SampleQbasedScheduling Maven / Gradle / Ivy

There is a newer version: 1.0.1
Show newest version
/*
 * Copyright 2016 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.netflix.fenzo.samples;

import com.netflix.fenzo.*;
import com.netflix.fenzo.functions.Action0;
import com.netflix.fenzo.functions.Action1;
import com.netflix.fenzo.plugins.BinPackingFitnessCalculators;
import com.netflix.fenzo.plugins.VMLeaseObject;
import com.netflix.fenzo.queues.*;
import org.apache.mesos.MesosSchedulerDriver;
import org.apache.mesos.Protos;
import org.apache.mesos.Scheduler;
import org.apache.mesos.SchedulerDriver;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

public class SampleQbasedScheduling {

    private static class MesosScheduler implements Scheduler {

        private final AtomicInteger numTasksCompleted;
        private final AtomicReference schedSvcGetter;
        private Action1> leaseAction = null;

        MesosScheduler(AtomicInteger numTasksCompleted, AtomicReference schedSvcGetter) {
            this.numTasksCompleted = numTasksCompleted;
            this.schedSvcGetter = schedSvcGetter;
        }

        @Override
        public void registered(SchedulerDriver driver, Protos.FrameworkID frameworkId, Protos.MasterInfo masterInfo) {
            System.out.println("Mesos scheduler registered");
        }

        @Override
        public void reregistered(SchedulerDriver driver, Protos.MasterInfo masterInfo) {
            System.out.println("Mesos scheduler re-registered");
        }

        @Override
        public void resourceOffers(SchedulerDriver driver, List offers) {
            leaseAction.call(offers);
        }

        @Override
        public void offerRescinded(SchedulerDriver driver, Protos.OfferID offerId) {
            System.out.println("Unexpected offers Rescinded");
        }

        @Override
        public void statusUpdate(SchedulerDriver driver, Protos.TaskStatus status) {
            switch (status.getState()) {
                case TASK_FAILED:
                case TASK_LOST:
                case TASK_FINISHED:
                    System.out.println("Task status for " + status.getTaskId().getValue() + ": " + status.getState());
                    schedSvcGetter.get().removeTask(status.getTaskId().getValue(),
                            allTasks.get(status.getTaskId().getValue()).getQAttributes(),
                            tasksToHostnameMap.get(status.getTaskId().getValue()));
                    numTasksCompleted.incrementAndGet();
            }
        }

        @Override
        public void frameworkMessage(SchedulerDriver driver, Protos.ExecutorID executorId, Protos.SlaveID slaveId, byte[] data) {

        }

        @Override
        public void disconnected(SchedulerDriver driver) {
            System.out.println("Mesos driver disconnected");
        }

        @Override
        public void slaveLost(SchedulerDriver driver, Protos.SlaveID slaveId) {
            System.out.println("Mesos agent lost");
        }

        @Override
        public void executorLost(SchedulerDriver driver, Protos.ExecutorID executorId, Protos.SlaveID slaveId, int status) {
            System.out.println("Mesos executor lost");
        }

        @Override
        public void error(SchedulerDriver driver, String message) {
            System.out.println("Unexpected mesos scheduler error: " + message);
        }
    }

    private final static QAttributes qAttribs = new QAttributes.QAttributesAdaptor(0, "onlyBucket");

    private final static ConcurrentMap allTasks = new ConcurrentHashMap<>();
    private final static ConcurrentMap tasksToHostnameMap = new ConcurrentHashMap<>();

    /**
     * This is the main method of this sample framework. It showcases how to use Fenzo queues for scheduling. It creates
     * some number of tasks and launches them into Mesos using the Mesos built-in command executor. The tasks launched
     * are simple sleep commands that sleep for 3 seconds each.
     * @param args Requires one argument for the location of Mesos master to connect to.
     * @throws Exception Upon catching any exceptions within the program.
     */
    public static void main(String[] args) throws Exception {
        if(args.length!=1) {
            System.err.println("Must provide one argument - Mesos master location string");
            System.exit(1);
        }
        int numTasks=10;
        final AtomicInteger numTasksCompleted = new AtomicInteger();

        // create Fenzo TaskScheduler object.
        final TaskScheduler taskScheduler = new TaskScheduler.Builder()
                .withFitnessCalculator(BinPackingFitnessCalculators.cpuMemBinPacker)
                .withLeaseOfferExpirySecs(1000000)
                .withLeaseRejectAction(new Action1() {
                    @Override
                    public void call(VirtualMachineLease v) {
                        System.out.println("Unexpected to reject lease on " + v.hostname());
                    }
                })
                .build();

        // Create a queue from Fenzo provided queue implementations.
        final TaskQueue queue = TaskQueues.createTieredQueue(2);

        // Create our Mesos scheduler callback implementation
        AtomicReference schedSvcGetter = new AtomicReference<>();
        final MesosScheduler mesosSchedulerCallback = new MesosScheduler(numTasksCompleted, schedSvcGetter);

        // create Mesos driver
        Protos.FrameworkInfo framework = Protos.FrameworkInfo.newBuilder()
                .setName("Sample Fenzo Framework")
                .setUser("")
                .build();
        final MesosSchedulerDriver driver = new MesosSchedulerDriver(mesosSchedulerCallback, framework, args[0]);

        // Build Fenzo task scheduling service using the TaskScheduler and TaskQueue objects created above
        final AtomicInteger schedCounter = new AtomicInteger();
        final TaskSchedulingService schedulingService = new TaskSchedulingService.Builder()
                .withLoopIntervalMillis(1000)
                .withMaxDelayMillis(1500)
                .withPreSchedulingLoopHook(new Action0() {
                    @Override
                    public void call() {
                        System.out.println("Starting scheduling iteration " + schedCounter.incrementAndGet());
                    }
                })
                .withTaskQueue(queue)
                .withTaskScheduler(taskScheduler)
                // TaskSchedulingService will call us back when there are task assignments. Handle them by launching
                // tasks using MesosDriver
                .withSchedulingResultCallback(new Action1() {
                    @Override
                    public void call(SchedulingResult schedulingResult) {
                        final List exceptions = schedulingResult.getExceptions();
                        if (exceptions != null && !exceptions.isEmpty()) {
                            System.out.println("Exceptions from scheduling iteration:");
                            for (Exception e: exceptions)
                                e.printStackTrace();
                        }
                        else {
                            for (Map.Entry e: schedulingResult.getResultMap().entrySet()) {
                                List offers = new ArrayList();
                                for (VirtualMachineLease l: e.getValue().getLeasesUsed())
                                    offers.add(l.getOffer().getId());
                                List taskInfos = new ArrayList();
                                for (TaskAssignmentResult r: e.getValue().getTasksAssigned()) {
                                    taskInfos.add(SampleFramework.getTaskInfo(
                                            e.getValue().getLeasesUsed().iterator().next().getOffer().getSlaveId(),
                                            r.getTaskId(),
                                            "sleep 2"
                                    ));
                                    tasksToHostnameMap.put(r.getTaskId(), r.getHostname());
                                }
                                driver.launchTasks(
                                        offers,
                                        taskInfos
                                );
                            }
                        }
                    }
                })
                .build();
        schedSvcGetter.set(schedulingService);

        // set up action in our scheduler callback to send resource offers into our scheduling service
        mesosSchedulerCallback.leaseAction = new Action1>() {
            @Override
            public void call(List offers) {
                List leases = new ArrayList<>();
                for (Protos.Offer o: offers)
                    leases.add(new VMLeaseObject(o)); // Fenzo lease object adapter for Mesos Offer object
                schedulingService.addLeases(leases);
            }
        };
        schedulingService.start();

        // start Mesos driver
        new Thread() {
            @Override
            public void run() {
                driver.run();
            }
        }.start();

        // submit some tasks
        for (int i=0; i>>() {
            @Override
            public void call(Map> taskStateCollectionMap) {
                System.out.println("Fenzo queue has " + taskStateCollectionMap.size() + " items");
                latch.countDown();
            }
        });
        if (!latch.await(5, TimeUnit.SECONDS))
            System.err.println("Timeout waiting for listing all tasks in Fenzo queues");

        System.out.println("ALL DONE");
        System.exit(0);
    }

    private static QueuableTask getTask(final int i) {
        return new QueuableTask() {
            @Override
            public QAttributes getQAttributes() {
                return qAttribs;
            }

            @Override
            public String getId() {
                return "Task-" + i;
            }

            @Override
            public String taskGroupName() {
                return "groupA";
            }

            @Override
            public double getCPUs() {
                return 1;
            }

            @Override
            public double getMemory() {
                return 100;
            }

            @Override
            public double getNetworkMbps() {
                return 0;
            }

            @Override
            public double getDisk() {
                return 0;
            }

            @Override
            public int getPorts() {
                return 0;
            }

            @Override
            public Map getScalarRequests() {
                return null;
            }

            @Override
            public Map getCustomNamedResources() {
                return null;
            }

            @Override
            public List getHardConstraints() {
                return null;
            }

            @Override
            public List getSoftConstraints() {
                return null;
            }

            @Override
            public void setAssignedResources(AssignedResources assignedResources) {
                // no-op, unexpected for this sample
            }

            @Override
            public AssignedResources getAssignedResources() {
                return null;
            }
        };
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy