云计算中虚拟机分配策略有诸多方法,现内置于cloudsim工程包里自带随机分配(Random)、首次适应(FirstFit)、最佳适应(BestFit)、轮盘(RoundRobin)等调度方法。虚拟机调度问题这种寻优过程也可引用多属性决策的思想,本文笔者尝试利用数学建模中经典的综合评价指标模型--TOPSIS来解决云计算中虚拟机分配策略的问题。

        TOPSIS (Technique for Order Preference by Similarity to an Ideal Solution )模型中文叫做“逼近理想解排序方法”,是根据评价对象与理想化目标的接近程度进行排序的方法,是一种距离综合评价方法。基本思路是通过假定正、负理想解,测算各样本与正、负理想解的距离,得到其与理想方案的相对贴近度(即距离正理想解越近同时距离负理想解越远),进行各评价对象的优劣排序。本文选取三个指标作为选取最佳主机的标准,分别为:

(1) 可用性availability:定义为主机剩余可用资源最多的,即将 VM 放置到剩余资源最多的机。
(2) 负载均衡load_balance:定义为单个主机负载(考虑 CPU,内存,带宽)距离数据中心中所有主机负载均值的距离或者方差。
(3) 相似性similarity:计算待迁移虚拟机和主机上虚拟机的资源请求相似度,设定一个阈值,过于相似的就放弃选择该主机。
        通过上述指标给主机综合打分,讲得分最高的资源给Vm,并输出使用该算法找到资源的时间与主机消耗能耗表。
以下为利用TOPSIS实现虚拟机分配策略的实例代码:
VmAllocationPolicyTOPSISandPOWERExample_sherry.java
package org.cloudsimplus.examples;
import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicy;
import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicyAbstract;
import org.cloudbus.cloudsim.brokers.DatacenterBroker;
import org.cloudbus.cloudsim.brokers.DatacenterBrokerSimple;
import org.cloudbus.cloudsim.cloudlets.Cloudlet;
import org.cloudbus.cloudsim.cloudlets.CloudletSimple;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.datacenters.Datacenter;
import org.cloudbus.cloudsim.datacenters.DatacenterSimple;
import org.cloudbus.cloudsim.hosts.Host;
import org.cloudbus.cloudsim.hosts.HostSimple;
import org.cloudbus.cloudsim.power.models.PowerModelHost;
import org.cloudbus.cloudsim.power.models.PowerModelHostSimple;
import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.ResourceProvisioner;
import org.cloudbus.cloudsim.provisioners.ResourceProvisionerSimple;
import org.cloudbus.cloudsim.resources.Pe;
import org.cloudbus.cloudsim.resources.PeSimple;
import org.cloudbus.cloudsim.schedulers.cloudlet.CloudletSchedulerTimeShared;
import org.cloudbus.cloudsim.schedulers.vm.VmScheduler;
import org.cloudbus.cloudsim.schedulers.vm.VmSchedulerTimeShared;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModel;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelDynamic;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelFull;
import org.cloudbus.cloudsim.vms.HostResourceStats;
import org.cloudbus.cloudsim.vms.Vm;
import org.cloudbus.cloudsim.vms.VmSimple;
import org.cloudsimplus.builders.tables.CloudletsTableBuilder;

import java.util.*;

import static java.util.Comparator.comparingLong;
import java.util.List;

public class VmAllocationPolicyTOPSISandPOWERExample_sherry {
    private static final int SCHEDULING_INTERVAL = 10;

    private static final int  HOSTS = 30;
    private static final int  HOST_PES =10;
    private static final int  HOST_MIPS = 1000;

    private static final int VMS = 15;

//    设置虚拟机Pe核为4或5
//    private static final int VM_PES = [4,5];

    private static final int CLOUDLETS = 30;
    private static final int CLOUDLET_PES = 4;
    private static final int CLOUDLET_LENGTH = 50000;


    /**
     * Defines the power a Host uses, even if it's idle (in Watts).
     */
    private static final double STATIC_POWER = 35;

    /**
     * The max power a Host uses (in Watts).
     */
    private static final int MAX_POWER = 50;

    private final CloudSim simulation;
    private DatacenterBroker broker0;
    private List<Vm> vmList;
    private List<Cloudlet> cloudletList;
    private Datacenter datacenter0;
    private List<Host> hostList;
    public static void main(String[] args) {
        new VmAllocationPolicyTOPSISandPOWERExample_sherry();
    }
    private VmAllocationPolicyTOPSISandPOWERExample_sherry(){
        //Log.setLevel(Level.WARN);

        simulation = new CloudSim();
        hostList = new ArrayList<>(HOSTS);
        datacenter0 = createDatacenterSimple();
        //Creates a broker that is a software acting on behalf of a cloud customer to manage his/her VMs and Cloudlets
        broker0 = new DatacenterBrokerSimple(simulation);

        vmList = createVms();
        cloudletList = createCloudlets();
        broker0.submitVmList(vmList);



        broker0.submitCloudletList(cloudletList);

        simulation.start();

        System.out.println("------------------------------- SIMULATION FOR SCHEDULING INTERVAL = " + SCHEDULING_INTERVAL+" -------------------------------");
        final List<Cloudlet> finishedCloudlets = broker0.getCloudletFinishedList();
        final Comparator<Cloudlet> hostComparator = comparingLong(cl -> cl.getVm().getHost().getId());
        finishedCloudlets.sort(hostComparator.thenComparing(cl -> cl.getVm().getId()));

        new CloudletsTableBuilder(finishedCloudlets).build();
        printHostsCpuUtilizationAndPowerConsumption();
    }
    /**
     * The Host CPU Utilization History is only computed
     * if VMs utilization history is enabled by calling
     * {@code vm.getUtilizationHistory().enable()}.
     */
    private void printHostsCpuUtilizationAndPowerConsumption() {
        System.out.println();
        for (final Host host : hostList) {
            printHostCpuUtilizationAndPowerConsumption(host);
        }
        System.out.println();
    }

    private void printHostCpuUtilizationAndPowerConsumption(final Host host) {
        final HostResourceStats cpuStats = host.getCpuUtilizationStats();

        //The total Host's CPU utilization for the time specified by the map key
        final double utilizationPercentMean = cpuStats.getMean();
        final double watts = host.getPowerModel().getPower(utilizationPercentMean);
        System.out.printf(
            "Host %2d CPU Usage mean: %6.1f%% | Power Consumption mean: %8.0f W%n",
            host.getId(), utilizationPercentMean * 100, watts);
    }

    /**
     * Creates a {@link Datacenter} and its {@link Host}s.
     */
    private Datacenter createDatacenterSimple() {
        for(int i = 0; i < HOSTS; i++) {
            Host host = createPowerHost(i);
            hostList.add(host);
        }

        final Datacenter dc = new DatacenterSimple(simulation, hostList, new VmAllocationPolicyTOPSIS_sherry());
        dc.setSchedulingInterval(SCHEDULING_INTERVAL);
        return dc;
    }

    private Host createPowerHost(final int id) {
        final List<Pe> peList = new ArrayList<>(HOST_PES);
        //List of Host's CPUs (Processing Elements, PEs)
        for (int i = 0; i < HOST_PES; i++) {
            peList.add(new PeSimple(1000, new PeProvisionerSimple()));
        }

        final long ram = 2048; //in Megabytes
        final long bw = 10000; //in Megabits/s
        final long storage = 1000000; //in Megabytes
        final ResourceProvisioner ramProvisioner = new ResourceProvisionerSimple();
        final ResourceProvisioner bwProvisioner = new ResourceProvisionerSimple();
        final VmScheduler vmScheduler = new VmSchedulerTimeShared();

        final Host host = new HostSimple(ram, bw, storage, peList);

        final PowerModelHost powerModel = new PowerModelHostSimple(MAX_POWER, STATIC_POWER);
        host
            .setRamProvisioner(ramProvisioner)
            .setBwProvisioner(bwProvisioner)
            .setVmScheduler(vmScheduler)
            .setPowerModel(powerModel);
        host.setId(id);
        host.enableUtilizationStats();

        return host;
    }

    /**
     * Creates a list of VMs.
     */
    private List<Vm> createVms() {
        final List<Vm> list = new ArrayList<>(VMS);
        int VM_PES= getRandomVmPe(5);
        for (int i = 0; i < VMS; i++) {
            Vm vm = new VmSimple(i, 1000, VM_PES);
            vm.setRam(512).setBw(1000).setSize(10000)
                .setCloudletScheduler(new CloudletSchedulerTimeShared());
            vm.enableUtilizationStats();
            list.add(vm);
        }

        return list;
    }
    public int getRandomVmPe(final int maxValue){
        Random rand=new Random();
        //设Vm的Pe取值范围为[4,maxValue]间的随机数
        int vm_pe=rand.nextInt(maxValue-4+1)+4;
        return vm_pe;
    }

    /**
     * Creates a list of Cloudlets.
     */
    private List<Cloudlet> createCloudlets() {
        final List<Cloudlet> list = new ArrayList<>(CLOUDLETS);
        final UtilizationModel utilization = new UtilizationModelDynamic(0.2);
        for (int i = 0; i < CLOUDLETS; i++) {
            //Sets half of the cloudlets with the defined length and the other half with the double of it
            final long length = i < CLOUDLETS / 2 ? CLOUDLET_LENGTH : CLOUDLET_LENGTH * 2;
            Cloudlet cloudlet =
                new CloudletSimple(i, length, CLOUDLET_PES)
                    .setFileSize(1024)
                    .setOutputSize(1024)
                    .setUtilizationModelCpu(new UtilizationModelFull())
                    .setUtilizationModelRam(utilization)
                    .setUtilizationModelBw(utilization);
            list.add(cloudlet);
        }

        return list;
    }

    //=========================================form here is TOPSIS================================================================
    public static class VmAllocationPolicyTOPSIS_sherry extends VmAllocationPolicyAbstract implements VmAllocationPolicy {
        long startTime = 0;   //记录开始时间
        long endTime = 0;      //记录终止时间
        long allTime = 0;      //记录总时间


        @Override
        protected Optional<Host> defaultFindHostForVm(final Vm vm) {

            final List<Host> hostList = getHostList();
            Host temp = null;

            for (Host host : hostList) {
                HostResourceStats cpuUtilizationStats = host.getCpuUtilizationStats();
                host.getBwUtilization();
                host.getRamUtilization();
            }

            startTime = System.currentTimeMillis();
            //   创建host的数据矩阵,作为TOPSIS的输入.共4列,第一列为hostid,其余为3个评判指标
            //   hostData矩阵的存储形为:
            //   host_id | availability | load_balance | similarity
            HostMatrix hostMatrix=createData(hostList,vm);

            //    start TOPSIS,get result matrix
            double result[]=TOPSIS(hostMatrix);

            //     选出得分最高的主机
            int bestHostId= getBestHostId(result);
            Host host=hostList.get(bestHostId);

            endTime=System.currentTimeMillis();
            allTime=endTime-startTime;
            if (host.isSuitableForVm(vm)){
                temp=host;
            }
            return temp == null ? Optional.empty() :Optional.of(temp);
        }
    }



        private static int getBestHostId(double[] result){
            double max=result[0];
            int best=0;
            for (int i=1;i<result.length;i++){
                if (result[i]>max){
                    max=result[i];
                    best=i;
                }
            }
            return best;
        }

        private static double[] TOPSIS(HostMatrix hostData){

            //第一步:消除纲量,数据标准化处理
            HostMatrix standardMatrix=standard(hostData);

            //加权需求由客户提出
            //只需提供weight[target_nums]的一维数组即可

            //第二步:确定正理想解和负理想解,再根据公式获得每个主机的综合得分
            double result[]=getScore(standardMatrix);


            return result;
        }

        private static HostMatrix standard(HostMatrix hostData){
            int row,column;
            int num=hostData.getHostnum(hostData);
            int target=hostData.getTargetnum(hostData);
            double standard[][] = new double[num][target];
            HostMatrix standardMatrix = new HostMatrix(num,target,standard);

            //消除纲量,数据标准化处理
            double down[] = new double[target];
            double value,value2,value_sum;
            for (column=1;column<target;column++){
                value_sum=0;
                for (row=0;row<num;row++){
                    value=hostData.getMatrix(row,column);
                    value2=Math.pow(value,2);
                    value_sum+=value2;
                }
                down[column]=Math.sqrt(value_sum);
            }
            for (row=0;row<num;row++){
                for (column=0;column<target;column++){
                    if (column==0){
                        standardMatrix.setMatrix(row,column,row);//hostid
                        System.out.print(row+" ");
                    }
                    else{
                        value=hostData.getMatrix(row,column)/down[column];
                        standardMatrix.setMatrix(row,column,value);
                        System.out.print(value+" ");
                    }
                }
                System.out.println();

            }
            return standardMatrix;
        }

        private static double[] getScore(HostMatrix standardMaxtrix){
            int num=standardMaxtrix.getHostnum(standardMaxtrix);
            int col=standardMaxtrix.getTargetnum(standardMaxtrix);
            int row,column;


            //Step1:确定正、负理想解(获取每个指标的最大值和最小值)
            double max_targets[]=new double[col];
            double min_targets[]=new double[col];
            double max,min,value;
            for (column=1;column<col;column++){
                max=standardMaxtrix.getMatrix(0,column);
                min=standardMaxtrix.getMatrix(0,column);
                for (row=1;row<num;num++){
                    value=standardMaxtrix.getMatrix(row,column);
                    if (value>max) max=value;
                    if (value<min) min=value;
                }
                max_targets[column]=max;
                min_targets[column]=min;
            }

            //Step2:计算得分
            double DistanceToMax;
            double DistanceToMin;
            double host_score;
            double score[] =new double[num]; //存放第i个评价对象的得分
            double distance_max,distance_min,value_max,value_min;
            for (row=0;row<num;row++){
                distance_max=0;
                distance_min=0;
                for (column=1;column<num;column++){
                    value_max=standardMaxtrix.getMatrix(row,column)-max_targets[column];
                    distance_max+=Math.pow(value_max,2);
                    value_min=standardMaxtrix.getMatrix(row,column)-min_targets[column];
                    distance_min+=Math.pow(value_min,2);
                }
                //计算所有host的data到正、负理想解的距离
                DistanceToMax=Math.sqrt(distance_max);
                DistanceToMin=Math.sqrt(distance_min);
                host_score=DistanceToMin/(DistanceToMax+DistanceToMin);
                score[row]=host_score;
            }
            return score;
        }

        private static HostMatrix createData(List<Host> hostList, Vm vm){
            int PeSum = 0;
            long BwSum = 0;
            long RamSum = 0;
            for (int i = 0; i < hostList.size(); i++) {
                PeSum += hostList.get(i).getBusyPesNumber();
                BwSum += hostList.get(i).getBw().getAllocatedResource();
                RamSum += hostList.get(i).getRam().getAllocatedResource();
            }
            //记录数据中心 Pe、Bw、Ram均值
            double PeAver = PeSum / hostList.size();
            double BwAver = BwSum / hostList.size();
            double RamAver = RamSum / hostList.size();
            System.out.println(BwAver);

            int Matrix_row=hostList.size();
            int Matrix_column=4;   //矩阵共4列,第一列为hostid,其余为3个评判指标
            double hostData[][] = new double[Matrix_row][Matrix_column];
            HostMatrix hostMatrix = new HostMatrix(Matrix_row,Matrix_column,hostData);

            //   hostData矩阵的存储形为:
            //   host_id | availability | load_balance | similarity
            for (int row=0;row < Matrix_row; row++){
                hostMatrix.setMatrix(row,0,row);
                hostMatrix.setMatrix(row,1,availability(hostList,row,vm));
                hostMatrix.setMatrix(row,2,load_balance(hostList,row,PeAver,BwAver,RamAver));
                hostMatrix.setMatrix(row,3,similarity(hostList,row,vm));
            }
            return hostMatrix;
        }

        //以下为评价指标:
        //可用性
        private static double availability(List<Host> hostList,int id,Vm vm){
            long vmBw = vm.getBw().getCapacity();
            long vmRam = vm.getRam().getCapacity();
            long vmSize = vm.getStorage().getCapacity();
            long bw = hostList.get(id).getBw().getAvailableResource();
            long ram = hostList.get(id).getRam().getAvailableResource();
            long storage = hostList.get(id).getStorage().getAvailableResource();
            double distence = Math.sqrt(Math.pow(vmBw-bw,2) + Math.pow(vmRam-ram,2) + Math.pow(vmSize-storage,2));
            return distence;
        }

        //负载均衡
        private static double load_balance(List<Host> hostList,int id,double PeAver,double BwAver,double RamAver){
            long bw = hostList.get(id).getBw().getAvailableResource();
            long ram = hostList.get(id).getRam().getAvailableResource();
            long  pe = hostList.get(id).getBusyPesNumber();
            double load = Math.sqrt(Math.pow(ram-RamAver,2) + Math.pow(bw-BwAver,2) + Math.pow(pe-PeAver,2));
            return load;
        }

        //相似性
        //极小型指标
        private static double similarity(List<Host> hostList,int id,Vm vm){
            long vmBw = vm.getBw().getCapacity();
            long vmRam = vm.getRam().getCapacity();
            long vmPe = vm.getNumberOfPes();
            Host host = hostList.get(id);
            double similarity = 0;
            System.out.println(hostList.get(id).getRam().getAllocatedResource());
            if(host.getRam().getAllocatedResource()!= 0 && host.getBw().getAllocatedResource() != 0&& host.getBusyPesNumber() != 0){
                similarity = (vmRam / host.getRam().getAllocatedResource()) + (vmBw / host.getBw().getAllocatedResource()) + (vmPe / host.getBusyPesNumber());
                if (similarity > 0.7)  similarity = 1;              //若太相似则放弃改主机;
            }
            //由于相似性是极小型指标,即值越小越好
            //需对极小型指标做正向化处理,此处用取反的方法
            System.out.println(similarity);
            return -similarity;
        }
    }

    //定义host矩阵类存放3个指标的值
    class HostMatrix{

        private int row;//行
        private int col;//列
        double [][]Data;

        public HostMatrix(int row, int col,double [][]Data) {
            this.row = row;
            this.col = col;
            this.Data = Data;
        }

        public void setMatrix(int row , int col, double value) {
            this.Data[row][col] = value;
        }

        public double getMatrix(int row, int col) {
            return Data[row][col] ;
        }

        public int getHostnum(HostMatrix hostMatrix){
            return hostMatrix.Data.length;
        }

        public int getTargetnum(HostMatrix hostMatrix){
            return hostMatrix.Data[0].length;
        }
    }

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐