Cloudism3.0.3学习与使用(二)

Cloudism3.0.3学习与使用(二)

Posted by sunlianglong on June 27, 2018

三、Example1 和VmAllocationPolicySimple源码分析

  在接着上一篇博客分析之前,我们先来了解一些可能会需要注意的地方。

  MIPS是虚拟机的cpu处理速度。假设同一机器下的所有PE具有相同的MIPS评级。Pe(处理单元)表示CPU单元,即可以理解为CPU的核数,按照每秒百万指令(MIPS)评级定义。

  mips是虚拟机的cpu处理速度,cloudlet的length / 虚拟机mips = 任务执行所需时间,所有虚拟机的mips之和不能超过datacenter中定义的主机的物理cpu的mips之和,而虚拟cpu的mips的最大值也不能超过物理cpu的最大值,否则虚拟机将创建失败。

CloudSimExample1

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import org.cloudbus.cloudsim.Cloudlet;
import org.cloudbus.cloudsim.CloudletSchedulerTimeShared;
import org.cloudbus.cloudsim.Datacenter;
import org.cloudbus.cloudsim.DatacenterBroker;
import org.cloudbus.cloudsim.DatacenterCharacteristics;
import org.cloudbus.cloudsim.Host;
import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.Pe;
import org.cloudbus.cloudsim.Storage;
import org.cloudbus.cloudsim.UtilizationModel;
import org.cloudbus.cloudsim.UtilizationModelFull;
import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.VmAllocationPolicySimple;
import org.cloudbus.cloudsim.examples.VmAllocationPolicyFirstIn;
import org.cloudbus.cloudsim.examples.VmAllocationPolicy_BestFit;
import org.cloudbus.cloudsim.VmSchedulerTimeShared;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.provisioners.BwProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.RamProvisionerSimple;
/**
 * A simple example showing how to create a datacenter with one host and run one
 * cloudlet on it.
 */
public class CloudSimExample1 {

	/** The cloudlet list. */
	private static List<Cloudlet> cloudletList;
	/** The vmlist. */
	private static List<Vm> vmlist;
	int algorithm_flag=0;
	static List<Host> hostList = new ArrayList<Host>();
	/**
	 * Creates main() to run this example.
	 *
	 * @param args the args
	 */

	@SuppressWarnings("unused")
	public static void main(String[] args) {

		Log.printLine("Starting CloudSimExample1...");

		try {
			// First step: Initialize the CloudSim package. It should be called
			// before creating any entities.
			int num_user = 1; // number of cloud users
			Calendar calendar = Calendar.getInstance();
			boolean trace_flag = false; // mean trace events

			// Initialize the CloudSim library 初始化CloudSim包
			CloudSim.init(num_user, calendar, trace_flag);

			// Second step: Create Datacenters
			// Datacenters are the resource providers in CloudSim. We need at
			// list one of them to run a CloudSim simulation
			Datacenter datacenter0 = createDatacenter("Datacenter_0");

			// Third step: Create Broker 数据中心代理
			//DatacenterBroker模拟SaaS提供商代理,根据QoS的需求协商资源和服务的分配策略
			DatacenterBroker broker = createBroker();
			int brokerId = broker.getId();

			// Fourth step: Create one virtual machine
			vmlist = new ArrayList<Vm>();

			// VM description
			int vmid = 0;
			int mips = 3000;
			long size = 10000; // image size (MB)
			int ram = 1024; // vm memory (MB)
			long bw = 1000;
			int pesNumber1 = 2; // number of cpus
			int pesNumber2 = 3; // number of cpus
			int pesNumber3 = 3; // number of cpus
			int pesNumber4 = 1; // number of cpus
			String vmm = "Xen"; // VMM name

        	//create two VMs
        	Vm vm1 = new Vm(vmid, brokerId, mips, pesNumber1, ram, bw, size, vmm, new CloudletSchedulerTimeShared());
        	vmid++;
        	Vm vm2 = new Vm(vmid, brokerId, mips, pesNumber2, ram, bw, size, vmm, new CloudletSchedulerTimeShared());
        	vmid++;
        	Vm vm3 = new Vm(vmid, brokerId, mips, pesNumber3, ram, bw, size, vmm, new CloudletSchedulerTimeShared());
        	vmid++;
        	Vm vm4 = new Vm(vmid, brokerId, mips, pesNumber4, ram, bw, size, vmm, new CloudletSchedulerTimeShared());
        	// add the VM to the vmList
			vmlist.add(vm1);
			vmlist.add(vm2);
			vmlist.add(vm3);
			vmlist.add(vm4);
			// submit vm list to the broker 提交虚拟机列表
			broker.submitVmList(vmlist);

			// Fifth step: Create one Cloudlet  云服务
			cloudletList = new ArrayList<Cloudlet>();

			// Cloudlet properties
			int id = 0;
			long length = 400000;
			long fileSize = 300;
			long outputSize = 300;
			int pesNumber = 1; // number of cpus
			UtilizationModel utilizationModel = new UtilizationModelFull(); //类:根据时间返回百分比利用率。

			Cloudlet cloudlet = new Cloudlet(id, length, pesNumber, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel);
			cloudlet.setUserId(brokerId);
			cloudlet.setVmId(vmid);

			// add the cloudlet to the list
			cloudletList.add(cloudlet);

			// submit cloudlet list to the broker 向代理提交任务列表
			broker.submitCloudletList(cloudletList);

			// Sixth step: Starts the simulation(模拟)
			CloudSim.startSimulation();

			CloudSim.stopSimulation();

			//Final step: Print results when simulation is over
			List<Cloudlet> newList = broker.getCloudletReceivedList();
			printCloudletList(newList);

			Log.printLine("CloudSimExample1 finished!");
		} catch (Exception e) {
			e.printStackTrace();
			Log.printLine("Unwanted errors happen");
		}
	}

	/**
	 * Creates the datacenter.
	 *
	 * @param name the name
	 *
	 * @return the datacenter
	 */
	private static Datacenter createDatacenter(String name) {

		// Here are the steps needed to create a PowerDatacenter:
		// 1. We need to create a list to store our machine

		// 2. A Machine contains one or more PEs or CPUs/Cores.
		// In this example, it will have only one core.
		List<Pe> peList = new ArrayList<Pe>();
		int mips = 5000;
		// 3. Create PEs and add these into a list.
		//创建处理器,并添加到Pe列表中:为每个主机配置4核CPU 写入Pe id 和 cpu处理速度
		peList.add(new Pe(0, new PeProvisionerSimple(mips))); // need to store Pe id and MIPS Rating
		peList.add(new Pe(1, new PeProvisionerSimple(mips)));
		peList.add(new Pe(2, new PeProvisionerSimple(mips)));
		peList.add(new Pe(3, new PeProvisionerSimple(mips)));
		// 4. Create Host with its id and list of PEs and add them to the list
		// of machines 创建主机,并将其添加至主机列表
		int hostId = 0;
		int ram = 2048; // host memory (MB)
		long storage = 1000000; // host storage
		int bw = 10000;

		hostList.add(
			new Host(
				hostId,
				new RamProvisionerSimple(ram),
				new BwProvisionerSimple(bw),
				storage,
				peList,
				new VmSchedulerTimeShared(peList)
			)
		); // This is our machine

		hostId++;
		hostList.add(
				new Host(
					hostId,
					new RamProvisionerSimple(ram),
					new BwProvisionerSimple(bw),
					storage,
					peList,
					new VmSchedulerTimeShared(peList)
				)
			); // This is second machine
		hostId++;
		hostList.add(
				new Host(
					hostId,
					new RamProvisionerSimple(ram),
					new BwProvisionerSimple(bw),
					storage,
					peList,
					new VmSchedulerTimeShared(peList)
				)
			); // This is second machine
		hostId++;
		hostList.add(
				new Host(
					hostId,
					new RamProvisionerSimple(ram),
					new BwProvisionerSimple(bw),
					storage,
					peList,
					new VmSchedulerTimeShared(peList)
				)
			); // This is second machine

		//创建数据中心特征,它表示了数据中心的资源的静态属性,
		//比如:体系结构,操作系统,主机列表,分配策略,时间或空间共享,时区,价格
		String arch = "x86"; // system architecture
		String os = "Linux"; // operating system
		String vmm = "Xen";
		double time_zone = 10.0; // time zone this resource located
		double cost = 3.0; // the cost of using processing in this resource
		double costPerMem = 0.05; // the cost of using memory in this resource
		double costPerStorage = 0.001; // the cost of using storage in this
										// resource
		double costPerBw = 0.0; // the cost of using bw in this resource
		LinkedList<Storage> storageList = new LinkedList<Storage>(); // we are not adding SAN
													// devices by now

		DatacenterCharacteristics characteristics = new DatacenterCharacteristics(
				arch, os, vmm, hostList, time_zone, cost, costPerMem,
				costPerStorage, costPerBw);

		// 6. Finally, we need to create a PowerDatacenter object.
		Datacenter datacenter = null;
		try {

			//默认算法:VmAllocationPolicySimple 选择最大剩余PEs的主机分配
			//首次适应算法:VmAllocationPolicyFirstIn 选择最先适配的主机分配
			datacenter = new Datacenter(name, characteristics, new VmAllocationPolicySimple(hostList), storageList, 0);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return datacenter;
	}

	// We strongly encourage users to develop their own broker policies, to
	// submit vms and cloudlets according
	// to the specific rules of the simulated scenario
	/**
	 * Creates the broker.
	 *
	 * @return the datacenter broker
	 */
	private static DatacenterBroker createBroker() {
		DatacenterBroker broker = null;
		try {
			broker = new DatacenterBroker("Broker");
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return broker;
	}

	/**
	 * Prints the Cloudlet objects.
	 *
	 * @param list list of Cloudlets
	 */
	private static void printCloudletList(List<Cloudlet> list) {
		int size = list.size();
		Cloudlet cloudlet;

		String indent = "    ";
		Log.printLine();
		Log.printLine("========== OUTPUT ==========");
		Log.printLine("Cloudlet ID" + indent + "STATUS" + indent
				+ "Data center ID" + indent + "VM ID" + indent + "Time" + indent
				+ "Start Time" + indent + "Finish Time");

		DecimalFormat dft = new DecimalFormat("###.##");
		for (int i = 0; i < size; i++) {
			cloudlet = list.get(i);
			Log.print(indent + cloudlet.getCloudletId() + indent + indent);

			if (cloudlet.getCloudletStatus() == Cloudlet.SUCCESS) {
				Log.print("SUCCESS");

				Log.printLine(indent + indent + cloudlet.getResourceId()
						+ indent + indent + indent + cloudlet.getVmId()
						+ indent + indent
						+ dft.format(cloudlet.getActualCPUTime()) + indent
						+ indent + dft.format(cloudlet.getExecStartTime())
						+ indent + indent
						+ dft.format(cloudlet.getFinishTime()));
			}
		}
	}

}

  开始仿真模拟时,首先需要创建一个数据中心,然后再数据中心中创建CPU、内存等资源,此时只需要向代理中心注册资源信息,用户就可以使用数据中心的资源进行仿真模拟。在仿真资源分配试验中,其步骤及其各个步骤中的代码如下:

  (1) 初始化Cloudsim包,代码如下:

Int num_user= 1 ; //定义用户数量
Calendar calendar=Calendar.getInstance();
boolean trace_flag=false;
CloudSim.init(num_user calendar trace_flag); //初始化CloudSim包

  (2)创建数据中心(Datacenter),如果多次创建那就生成多个数据中心,代码如下所示:

DataCenter datacenter()=createDatacenter("Datacenter_0");

  (3) 创建数据中心代理(Broker),代码如下所示。注:任务到虚拟机的映射是由DatacenterBroker类中的bindCloudletsToVms()函数实现。该函数根据不同的策略来实现任务的映射。

DatacenterBroker broker=createBroker();
Int brokerId=broker.get_id();

  (4) 创建虚拟机,只有提交了虚拟机列表,broker才会发挥作用。代码如下所示:

vmlist=new VirtualMachineList(); //创建虚拟机列表
Vmvm=new Vm(vmid brokerld mips PesNumber ram bw size
vmmnew CloudletSchedulerTimeShared()); //创建虚拟机
vmlist.add(vm); //加入虚拟机列表
broker.submitVMList(vmlist);//提交虚拟机列表

  (5) 创建云任务,代码如下所示:

cloudletList = new CloudletList();//创建云任务列表
Cloudlet cloudlet=new Cloudlet(id length file_size output_size);
cloudlet.setUserlD(brokerld);
……
cloudletList.add(cloudlet); //将任务加入任务列表
……
broker.submitCloudletList(cloudletList);//向代理提交任务列表

  (6) 执行资源调度算法,完成任务到虚拟机的映射,代码如下所示:

broker. bindCloudletsToVms();

  (7) 启动仿真程序,代码如下所示:

CloudSim.startSimulation();

  (8) 打印仿真结果,代码如下所示:

List<Cloudlet> newList = broker.getCloudletReceivedList();
CloudSim.stopSimulation();
printCloudletList(newList);

  在createDatacenter函数中,我设定了4个主机,为每个主机配置4核CPU。首先写入PEs 的id 和 cpu处理速度。

List<Pe> peList = new ArrayList<Pe>();
int mips = 5000;
//为每个主机配置4核CPU 写入Pe id 和 cpu处理速度
peList.add(new Pe(0, new PeProvisionerSimple(mips)));
peList.add(new Pe(1, new PeProvisionerSimple(mips)));
peList.add(new Pe(2, new PeProvisionerSimple(mips)));
peList.add(new Pe(3, new PeProvisionerSimple(mips)));

  随后,创建四个主机,写入id和PEs列表到主机中。

int hostId = 0;
int ram = 2048; // host memory (MB)
long storage = 1000000; // host storage
int bw = 10000;
hostList.add(
	new Host(
		hostId,
		new RamProvisionerSimple(ram),
		new BwProvisionerSimple(bw),
		storage,
		peList,
		new VmSchedulerTimeShared(peList)
	)
); // This is frist machine
hostId++;
hostList.add(
				new Host(
					hostId,
					new RamProvisionerSimple(ram),
					new BwProvisionerSimple(bw),
					storage,
					peList,
					new VmSchedulerTimeShared(peList)
				)
			); // This is second machine
hostId++;
...

  创建数据中心的的仓库和属性,这部分的源码我没有修改,具体参见源代码。

VmAllocationPolicySimple

package org.cloudbus.cloudsim.examples;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.cloudbus.cloudsim.Host;
import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.VmAllocationPolicy;
import org.cloudbus.cloudsim.core.CloudSim;
/**
 * VmAllocationPolicySimple is an VmAllocationPolicy that chooses, as the host for a VM, the host
 * with less PEs in use.
 */
//VmAllocationPolicy 抽象类 代表了数据中心主机到虚拟机的供应协议
public class VmAllocationPolicyFirstIn extends VmAllocationPolicy {
	/** The vm table.记录虚拟机被分配到哪台主机 */  
	private Map<String, Host> vmTable;
	/** The used pes.记录虚拟机占用了几个处理器核心 */  
	private Map<String, Integer> usedPes;
	/** The free pes.记录每台主机可用的处理器核心数 */  
	private List<Integer> freePes;
	/**
	 * Creates the new VmAllocationPolicySimple object.
	 * @param list the list
	 * @pre $none
	 * @post $none
	 */
	public VmAllocationPolicyFirstIn(List<? extends Host> list) {
		//初始化主机列表hostList(继承自父类的成员)  
		super(list);
		//初始化每台主机可用的处理器核心数freePes  
		setFreePes(new ArrayList<Integer>());
		for (Host host : getHostList()) {
			getFreePes().add(host.getNumberOfPes());
		}
		//初始化vmTable和usedPes  
		setVmTable(new HashMap<String, Host>());
		setUsedPes(new HashMap<String, Integer>());
	}
	/**
	 * Allocates a host for a given VM.
	 * @param vm VM specification
	 * @return $true if the host could be allocated; $false otherwise
	 * @pre $none
	 * @post $none
	 */
	@Override
	public boolean allocateHostForVm(Vm vm) {
		int requiredPes = vm.getNumberOfPes();//创建vm所需的处理器核心数
		boolean result = false;
		int tries = 0; //尝试次数
		List<Integer> freePesTmp = new ArrayList<Integer>();
		for (Integer freePes : getFreePes()) {
			freePesTmp.add(freePes);
		}
		//如果当前虚拟机还未创建
		if (!getVmTable().containsKey(vm.getUid())) { // if this vm was not created
			do {// we still trying until we find a host or until we try all of them
				//尝试创建虚拟机直到创建成功或所有的主机都已经尝试过
				int moreFree = Integer.MIN_VALUE;//当前最大可用核心数
				int idx = -1; //当前最大可用核心数对应主机的下标

				//默认算法;找到可用处理器核心数最大的第一台主机
				//TestData:VM所需核数分别为 2 3 3 1
				//正确结果:   剩余资源:2 1 1 3        主机分配ID:0 1 2 3
				for (int i = 0; i < freePesTmp.size(); i++) {
					if (freePesTmp.get(i) > moreFree) {
						moreFree = freePesTmp.get(i);
						idx = i;
					}
				}
				
				Host host = getHostList().get(idx);
				result = host.vmCreate(vm);//尝试创建虚拟机
				if (result) { // if vm were succesfully created in the host
					//更新映射关系及主机可用的处理器核心数
					getVmTable().put(vm.getUid(), host);
					getUsedPes().put(vm.getUid(), requiredPes);
					getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
					result = true;
					break;
				} else {//如果创建失败
					//将当前主机的可用处理器核心数暂时设成最小值,从而排除该主机
					freePesTmp.set(idx, Integer.MIN_VALUE);
				}
				tries++;
			} while (!result && tries < getFreePes().size());
		}
		System.out.println("配置完成后PEs的剩余情况");
		System.out.println(getFreePes().get(0)+" "+getFreePes().get(1)+" "+getFreePes().get(2)+" "+getFreePes().get(3));

		return result;
	}
	/**
	 * Releases the host used by a VM.
	 * 
	 * @param vm the vm
	 * @pre $none
	 * @post none
	 */
	@Override
	public void deallocateHostForVm(Vm vm) {

		//删除虚拟机相应的映射关系,通过主机销毁虚拟机并更新可用的处理器核心数
		Host host = getVmTable().remove(vm.getUid());
		int idx = getHostList().indexOf(host);
		int pes = getUsedPes().remove(vm.getUid());
		if (host != null) {
			host.vmDestroy(vm);
			getFreePes().set(idx, getFreePes().get(idx) + pes);
		}
	}

...

	//将虚拟机分配给指定的主机
	@Override
	public boolean allocateHostForVm(Vm vm, Host host) {
		if (host.vmCreate(vm)) { //如果虚拟机创建成功,更新vmTable,并返回true  
			getVmTable().put(vm.getUid(), host);
			int requiredPes = vm.getNumberOfPes();
			int idx = getHostList().indexOf(host);
			getUsedPes().put(vm.getUid(), requiredPes);
			getFreePes().set(idx, getFreePes().get(idx) - requiredPes);
			Log.formatLine(
					"%.2f: VM #" + vm.getId() + " has been allocated to the host #" + host.getId(),
					CloudSim.clock());
			return true;
		}
		return false;
	}
}

  VmAllocationPolicy类代表了数据中心主机到虚拟机的供应协议。在类刚开始便定义了vm table(记录虚拟机被分配到哪台主机)、used pes(记录虚拟机占用了几个处理器核心)、free pes(记录每台主机可用的处理器核心数),VmAllocationPolicy就是通过PEs处理器核心的个数进行单资源的调度,所以在这里我们只需关心这几个参数。传入Host列表,初始化这几个参数之后,我们便可以开始调度。

  判断当前传入的vm是否已经创建,在逻辑上就是判断VmTable中有没有写入该vm的ID,未创建的话,进行资源分配,并创建虚拟机,以及更新映射关系及主机可用的处理器核心数。如果创建失败,则将当前主机的可用处理器核心数暂时设成最小值,从而排除该主机。具体代码以及详细介绍见上。

四、虚拟机分配

  虚拟机分配指的是,选择满足特定条件(内存、软件环境配置等)的主机创建虚拟机的过程,这个过程由Datacenter对象负责。在云数据中心,将特定应用的虚拟机分配给主机由虚拟机分配控制器VmAllocationPolicy完成,Cloudsim在主机层和虚拟机层都实现了基于时间共享和空间共享的调度策略。用户可以通过继承该类实现自己的分配策略,CloudSim中,作者实现了一种简单的分配策略——VmAllocationPolicySimple。方法allocateHostForVm(Vm vm)是该类的核心,它实现了从主机列表中选择一台主机,并在其上创建虚拟机vm。

  主要实现过程的描述如下:

  1. 记录下所有主机可用的处理器核心数。

  2. 从中选出可用处理器核心数最多的第一台主机,并尝试在其上创建虚拟机。

  3. 如果 2 失败了且还有主机没有尝试过,就排除当前选择的这台主机,重做 2。

  4. 根据虚拟机是否创建成功,返回true或false。

  我们自己写相关算法,执行调度该如何修改代码呢?下面接着叙述。

  虚拟机的初始放置实际上是一个多维向量的装箱问题,装箱问题均是NP-Hard问题,目前针对装箱问题的解法主要为基于贪心算法的启发式算法,例如首次适应算法(First Fit,FF),降序首次适应算法(First Fit Descending,FFD),最佳适应算法(Best Fit,BF)和降序最佳适应启发式算法(Best Fit Descending,BFD)等。

  • (1)首次适应算法:为物品寻找目的箱子时,首先从第一个箱子寻找,如果不满足条件(不能放在箱子),则继续寻找直到找到合适的箱子。在目的箱子中为物品分配所需空间,剩余空间可以继续放置新的物品。如果不能找到合适的箱子,则物品放置失败。
  • (2)降序首次适应算法:首先将箱子按照某种资源(如CPU等)的大小进行降序排序,然后按照首次适应算法查找合适的箱子。如果能找到合适的箱子,则放置物品,更新箱子大小,放置成功,否则放置失败。
  • (3)最佳适应算法:将物品装入箱子时,在所有箱子中查找大于且最接近物品大小的箱子,然后再从该箱子中分配物品所需的空间,余下的空间作为新箱子继续放置其他物品,此时物品放置成功。如果任何箱子都不能放置物品,则放置失败。
  • (4)降序最佳适应算法:在最佳适应算法的基础上进行改进,首先将箱子按照某种资源(如CPU等)的大小进行降序排序,然后执行最佳适应算法查找箱子。若找到合适的箱子,则放置物品并更新箱子的大小,放置成功,否则失败。

    默认调度方法

    int moreFree = Integer.MIN_VALUE;//当前最大可用核心数
    int idx = -1; //当前最大可用核心数对应主机的下标
    for (int i = 0; i < freePesTmp.size(); i++) {
      if (freePesTmp.get(i) > moreFree) {
          moreFree = freePesTmp.get(i);
          idx = i;
      }
    }
    

      上面是VmAllocationPolicySimple中的默认算法。即找到可用处理器核心数最大的第一台主机。

  在这里,测试数据为:VM所需核数分别为 2 3 3 1,按照在Example1中定义的VM和Host列表的资源规配置,那么运行出来的正确结果应该是:

  • 0-3号主机中剩余PEs资源:2 1 1 3
  • 0-3号虚拟机的主机分配ID:0 1 2 3

  结果截图:

首次适应算法

int moreFree = Integer.MIN_VALUE;//当前最大可用核心数
int idx = -1; //当前最大可用核心数对应主机的下标
for (int i = 0; i < freePesTmp.size(); i++) {
	if (freePesTmp.get(i) >= requiredPes) {
		idx = i;
		break;
	}
}

  上面是首次适应算法的代码。即按照次序找到符合条件的第一个主机。

  在这里,测试数据为:VM所需核数分别为 2 3 3 1,按照在Example1中定义的VM和Host列表的资源规配置,那么运行出来的正确结果应该是:

  • 0-3号主机中剩余PEs资源:1 1 1 4
  • 0-3号虚拟机的主机分配ID:0 1 2 0

  结果截图:

最佳适应算法

int resource_diff = Integer.MAX_VALUE;//所需资源与目前资源的差值
int idx = -1; //当前最大可用核心数对应主机的下标
for (int i = 0; i < freePesTmp.size(); i++) {
	if (freePesTmp.get(i) >= requiredPes) {
		int r = (freePesTmp.get(i) - requiredPes);//所需资源与目前资源的差值,找出最小的一个
		if(r < resource_diff) {
			resource_diff = r;
			idx = i;
		}
	}
}

  上面是最佳适应算法的代码。即查找出大于且最接近所需PEs大小的主机。   在这里,测试数据为:VM所需核数分别为 2 3 3 1,按照在Example1中定义的VM和Host列表的资源规配置,那么运行出来的正确结果应该是:

  • 0-3号主机中剩余PEs资源:2 0 1 4
  • 0-3号虚拟机的主机分配ID:0 1 2 1

  结果截图:

五、部分博客参考