Эффективный способ выделения следующей доступной виртуальной машины
Метод 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 у вас будет несколько очередей и только передача определенных очередей машинам, которые могут обрабатывать эти очереди.