Эффективный способ выделения следующей доступной виртуальной машины

Метод getNextAvailableVm() автоматически распределяет виртуальные машины для конкретного центра обработки данных. (Целое число, возвращаемое этим методом, определяется машиной)

В дата-центре могут быть виртуальные машины с различным набором конфигураций. Например:

5 VMs with 1024 memory
4 VMs with 512 memory

Total : 9 VMs

Для этого центра обработки данных машина с памятью 1024 получит задачу в 2 раза по сравнению с машиной с 512 памятью.

Поэтому машины для этого дата-центра возвращаются getNextAvailableVm() следующим образом:

0 0 1 1 2 2 3 3 4 4 5 6 7 8

Это текущий способ, машины возвращаются. Но есть проблема.

Могут быть случаи, когда конкретная машина занята и не может быть выделена задача. Вместо следующей машины, доступной с наивысшей памятью, должна быть выделена задача. Я не смог реализовать это.

Например:

0 (allotted first time)
0 (to be allotted the second time)
but if 0 is busy..
allot 1 if 1 is not busy
next circle check if 0 is busy
if not busy allot 0  (only when machine numbered 0 has not handled the requests it is entitled to handle)
if busy, allot the next

cloudSimEventFired метод в следующем классе вызывается, когда машина освобождается или выделяется.

    public class TempAlgo extends VmLoadBalancer implements CloudSimEventListener {

    /**
     * Key : Name of the data center
     * Value : List of objects of class 'VmAllocationUIElement'.
     */
    private  Map<String,LinkedList<DepConfAttr>> confMap = new HashMap<String,LinkedList<DepConfAttr>>();
    private Iterator<Integer> availableVms = null;
    private DatacenterController dcc;
    private boolean sorted = false;
    private int currentVM;
    private boolean calledOnce = false;
    private boolean indexChanged = false;
    private LinkedList<Integer> busyList = new LinkedList<Integer>();

    private Map<String,LinkedList<AlgoAttr>> algoMap = new HashMap<String, LinkedList<AlgoAttr>>();
    private Map<String,AlgoHelper> map = new HashMap<String,AlgoHelper>();  
    private Map<String,Integer> vmCountMap = new HashMap<String,Integer>();

    public TempAlgo(DatacenterController dcb) {
        confMap = DepConfList.dcConfMap;
        this.dcc = dcb;
        dcc.addCloudSimEventListener(this);
        if(!this.calledOnce) {
            this.calledOnce = true;
            // Make a new map using dcConfMap that lists 'DataCenter' as a 'key' and 'LinkedList<AlgoAttr>' as 'value'.
            Set<String> keyst =DepConfList.dcConfMap.keySet();
            for(String dataCenter : keyst) {
                LinkedList<AlgoAttr> tmpList = new LinkedList<AlgoAttr>();
                LinkedList<DepConfAttr> list = dcConfMap.get(dataCenter);
                int totalVms = 0;
                for(DepConfAttr o : list) {
                    tmpList.add(new AlgoAttr(o.getVmCount(), o.getMemory()/512, 0));
                    totalVms = totalVms + o.getVmCount();
                }
                Temp_Algo_Static_Var.algoMap.put(dataCenter, tmpList);
                Temp_Algo_Static_Var.vmCountMap.put(dataCenter, totalVms);
            }
            this.algoMap = new HashMap<String, LinkedList<AlgoAttr>>(Temp_Algo_Static_Var.algoMap);
            this.vmCountMap = new HashMap<String,Integer>(Temp_Algo_Static_Var.vmCountMap);
            this.map = new HashMap<String,AlgoHelper>(Temp_Algo_Static_Var.map);
        }
    }

    @Override
    public int getNextAvailableVm() {
        synchronized(this) {
            String dataCenter = this.dcc.getDataCenterName();
            int totalVMs = this.vmCountMap.get(dataCenter);
            AlgoHelper ah = (AlgoHelper)this.map.get(dataCenter);
            int lastIndex = ah.getIndex();
            int lastCount = ah.getLastCount();
            LinkedList<AlgoAttr> list = this.algoMap.get(dataCenter);
            AlgoAttr aAtr = (AlgoAttr)list.get(lastIndex);
            indexChanged = false;
            if(lastCount < totalVMs)  {
                if(aAtr.getRequestAllocated() % aAtr.getWeightCount() == 0) {
                    lastCount = lastCount + 1;
                    this.currentVM = lastCount;
                    if(aAtr.getRequestAllocated() == aAtr.getVmCount() * aAtr.getWeightCount()) {
                        lastIndex++;
                        if(lastIndex != list.size()) {
                            AlgoAttr aAtr_N = (AlgoAttr)list.get(lastIndex);
                            aAtr_N.setRequestAllocated(1);
                            this.indexChanged = true;
                        }
                        if(lastIndex == list.size()) {
                            lastIndex = 0;
                            lastCount = 0;
                            this.currentVM = lastCount;
                            AlgoAttr aAtr_N = (AlgoAttr)list.get(lastIndex);
                            aAtr_N.setRequestAllocated(1);
                            this.indexChanged = true;

                        }
                    }
                }
                if(!this.indexChanged) {
                    aAtr.setRequestAllocated(aAtr.getRequestAllocated() + 1);
                }

                this.map.put(dataCenter, new AlgoHelper(lastIndex, lastCount)); 

                //System.out.println("Current VM : " + this.currentVM + " for data center : " + dataCenter);
                return this.currentVM;
            }}

            System.out.println("--------Before final return statement---------");
            return 0;

    }   

    @Override
    public void cloudSimEventFired(CloudSimEvent e) {
        if(e.getId() == CloudSimEvents.EVENT_CLOUDLET_ALLOCATED_TO_VM) {
            int vmId = (Integer) e.getParameter(Constants.PARAM_VM_ID);
                    busyList.add(vmId);

            System.out.println("+++++++++++++++++++Machine with vmID : " + vmId + " attached");
        }else if(e.getId() == CloudSimEvents.EVENT_VM_FINISHED_CLOUDLET) {
            int vmId = (Integer) e.getParameter(Constants.PARAM_VM_ID);
                            busyList.remove(vmId);
            //System.out.println("+++++++++++++++++++Machine with vmID : " + vmId + " freed");
        }
    }
}

В приведенном выше коде все списки сначала отсортированы с наивысшей памятью. Вся идея состоит в том, чтобы сбалансировать память, выделив больше задач на машину с более высокой памятью.

Каждый раз, когда выделенный выделенный ресурс присваивается, увеличивается на единицу. Каждый набор машин имеет прикрепленное к нему количество весов, которое рассчитывается путем деления memory_allotted на 512.

Метод getNextAvailableVm() вызывается несколькими потоками за раз. Для 3 центров данных 3 потока будут одновременно вызывать getNextAva...(), но на разных объектах класса. Центр данных, возвращаемый оператором this.dcc.getDataCenterName() в том же методе, возвращается в соответствии с политикой брокера центра обработки данных, выбранной ранее.

Как я могу убедиться, что машина, которую я сейчас возвращаю, является бесплатной, и если машина не является свободной, я выделяю следующий компьютер с максимальной доступной памятью. Я также должен убедиться, что машина, которая имеет право на process X, выполняет процессы X даже в том случае, когда машина занята.

Это общее описание используемой здесь структуры данных:

enter image description here

Код этого класса размещен здесь, на github.

Это ссылка для полного проекта на github.

Большинство структур данных/классов, используемых здесь, находятся внутри этого пакета

Ответы

Ответ 1

Возможно, вы уже задумались над этой проблемой. Простая стратегия заключается в том, чтобы иметь брокера, который знает обо всех ожидающих решения задачах. Каждый рабочий или рабочий поток задает броузеру новое сообщение/задачу. Брокер выдает работу в том порядке, в котором ее просили. Так работают очереди JMS. Для JVM, которые могут обрабатывать две задачи, вы можете запустить два потока.

Существует много стандартных JMS, которые делают это, но я предлагаю посмотреть ActiveMQ, поскольку с ним легко начать.

Обратите внимание, что в вашем случае более простым решением является наличие одной машины с 8 ГБ памяти. Вы можете купить 8 ГБ для сервера очень мало (40 - 150 долларов США в зависимости от поставщика), и он будет использоваться более эффективно в одном случае путем совместного использования ресурсов. Я предполагаю, что вы смотрите на гораздо более крупные экземпляры. Экземпляры размером менее 8 ГБ лучше просто обновляют его.

Как я могу убедиться, что машина, которую я сейчас возвращаю, бесплатна.

Это ваш сценарий, если вы не знаете, как определить, свободна ли машина, я не вижу, как кто-то будет иметь больше знаний о вашем приложении.

и если машина не является свободной, я выделяю следующую машину с максимальной доступной памятью.

Вам нужно посмотреть бесплатные машины и выбрать тот, у которого самая доступная память. Я не понимаю, что здесь происходит, кроме того, что вы заявили.

Я также должен убедиться, что машина, которая имеет право обрабатывать X-задачи, обрабатывает X-задачи, даже если эта машина в данный момент занята.

Для этой информации необходим источник данных или хранилище. Что можно запускать где. В JMS у вас будет несколько очередей и только передача определенных очередей машинам, которые могут обрабатывать эти очереди.