package org.cloudbus.cloudsim.examples; /* 程序说明:整个项目利用Cloudsim3.0的云计算仿真框架进行云任务的仿真。 该程序总共有两个类,一个为fuxian5.java,一个为Bee.java,其中在fuxian5.java中创建了多个实验需要用到的全局变量,方便在下边的云任务输出函数中进行调用。 由于vm列表和云任务列表都设置为全局变量,因此,赋值时,需要单独创建对应的函数进行传参,并返回一个值,否则在其他函数中调用该值时将为0。 我们先在主函数中调用虚拟机和云任务列表的创建函数,并赋值,以此来方便其他函数中对这两个列表进行调用。为了使实验更好的进行,我们还对一些虚拟机和云任务的参数进行随机数的产生,进而会生成不同的虚拟机序列和云任务序列,并上传至数据中心。 我们在CreateVmholdIndex()函数中调用Bee类中求出来的最优解以及相关系数,并利用这些值经过计算来返回特定虚拟机的序列号,方便之后的调用。 在createDatacenter()函数中,在进行主机列表,数据中心列表的创建后,调用了costs数组,用来计算云任务的成本值。 在printCloudletList()函数中,先定义了信用值,云任务长度,信用度优先级,存放负载等数组,通过设置各种循环并调用其它函数进行赋值。 通过相应的credit值的设置,通过相关公式来计算实验需要得出的分配任务的长度、任务的优先级、成本和任务的截止日期等参数,并利用这些参数 进而实现将蜜蜂优化算法用于负载平衡,并利用蜂蜜算法的负载对可信任务进行调度的目的。 这里只给出fuxian5.java类,至于蜜蜂优化算法这里不做描述。 */ import java.text.DecimalFormat; import java.util.*; 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.VmSchedulerTimeShared; import org.cloudbus.cloudsim.core.CloudSim; import org.cloudbus.cloudsim.lists.CloudletList; import org.cloudbus.cloudsim.lists.PeList; 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 fuxian5 { //创建云任务列表 public static List<Cloudlet> cloudletList; //创建虚拟机列表 public static List<Vm> vmlist; //定义信任值 public static int credit; //每个云任务的总成本 public static double costtotal; //创建Bee类的对象,方便下面的调用 static Bee b2=new Bee(); //用来存储特定虚拟机的序列号 public static int VmholdIndex; //用来存储特定虚拟机的存储容量 public static double Vmhold; //特定虚拟机的处理时间 public static double processtime; /** * @param userId the args * 创建虚拟机的函数,方便全局传参 */ private static List<Vm> createVM(int userId, int vms) { //创建一个容器用于存储虚拟机,放入列表中 LinkedList<Vm> list = new LinkedList<Vm>(); //设置虚拟机的mips为随机数 int [] mips1=new int[vms]; for(int j=0;j<vms;j++){ mips1[j]=(int)(Math.random()*999+500); } //VM 参数 //设置大小 long size = 10000; //设置虚拟机内存 int ram = 512; long bw = 1000; //cpu数量 int pesNumber = 1; //虚拟机的名字 String vmm = "Xen"; //创建Vms Vm[] vm = new Vm[vms]; for(int i=0;i<vms;i++){ vm[i] = new Vm(i, userId, mips1[i], pesNumber, ram, bw, size, vmm, new CloudletSchedulerTimeShared()); //为云任务创建一个空间的时间策略 list.add(vm[i]); } return list; } //创建云任务序列的函数 private static List<Cloudlet> createCloudlet(int userId, int cloudlets){ // 创建一个容器用来存储云任务列表 LinkedList<Cloudlet> list = new LinkedList<Cloudlet>(); //设置循环用于创建云任务长度的随机数 int [] length1=new int[cloudlets]; for(int j=0;j<cloudlets;j++){ length1[j]=(int)(Math.random()*999+1); } long fileSize = 300; long outputSize = 300; int pesNumber = 1; UtilizationModel utilizationModel = new UtilizationModelFull(); Cloudlet[] cloudlet = new Cloudlet[cloudlets]; for(int i=0;i<cloudlets;i++){ cloudlet[i] = new Cloudlet(i, length1[i], pesNumber, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel); cloudlet[i].setUserId(userId); list.add(cloudlet[i]); } return list; } public static void main(String[] args) { // Bee1 x=new Bee1(); Log.printLine("Starting 云计算仿真实验..."); try { //初始化Cloudsim的包 //云任务使用者的数量 int num_user = 1; Calendar calendar = Calendar.getInstance(); // mean trace events boolean trace_flag = false; // 初始化Cloudsim CloudSim.init(num_user, calendar, trace_flag); //创建数据中心的对象,用于仿真 Datacenter datacenter0 = createDatacenter("Datacenter_0"); Datacenter datacenter1 = createDatacenter("Datacenter_1"); // 创建 Broker DatacenterBroker broker = createBroker(); int brokerId = broker.getId(); //创建20台虚拟机 vmlist = createVM(brokerId,20); // 创建40个云任务 cloudletList = createCloudlet(brokerId,40); broker.submitVmList(vmlist); //递交云任务到broker中 broker.submitCloudletList(cloudletList); // Starts the simulation CloudSim.startSimulation(); List<Cloudlet> newList = broker.getCloudletReceivedList(); CloudSim.stopSimulation(); printCloudletList(newList); datacenter0.printDebts(); datacenter1.printDebts(); Log.printLine("CloudSimExample1 finished!"); } catch (Exception e) { e.printStackTrace(); Log.printLine("Unwanted errors happen"); } } public static int CreateVmholdIndex(int vmholdIndex){ int iter=0; int j=0; b2.initial(); /*初始化所有食物源 ,这里为云任务的参数*/ b2.MemorizeBestSource(); /*记录最优解*/ for (iter=0;iter<b2.maxCycle;iter++) { b2.SendEmployedBees(); /*雇佣蜂阶段*/ b2.CalculateProbabilities(); /*计算食物源适应度*/ b2.SendOnlookerBees(); /*观察蜂阶段*/ //bee.MemorizeBestSource(); /*记录最优解*/ b2.SendScoutBees(); /*侦查蜂阶段*/ } for(j=0;j<b2.D;j++) /*循环打印4个最优解的参数*/ { System.out.println("利用蜜蜂优化算法得出的影响最优解计算的参数["+(j+1)+"]:"+b2.GlobalParams[j]); } VmholdIndex=(int)b2.GlobalMin; if(VmholdIndex>20){ VmholdIndex= VmholdIndex%20; //由于虚拟机数量为20,所以这里我们必须取余,不然会超出虚拟机列表的长度 }//这里利用人工蜂群算法算出的最优解来求解特定的虚拟机的下角标 return VmholdIndex; } //创建数据中心函数 public static Datacenter createDatacenter(String name) { DatacenterBroker broker = createBroker(); int brokerId = broker.getId(); //创建一个主机列表进行存储 List<Host> hostList = new ArrayList<Host>(); //创建一个云任务列表 List<Cloudlet>cloudletList=new ArrayList<Cloudlet>(); //创建虚拟机列表 List<Vm>vmList=new ArrayList<Vm>(); //这些为创建上述列表的过程中将会用到的参数 int mips = 1000; long size = 10000; int ram = 512; long bw = 1000; String vmm = "Xen"; int id = 0; int vmid = 0; long length = 400000; long fileSize = 300; long outputSize = 300; int pesNumber = 1; UtilizationModel utilizationModel = new UtilizationModelFull(); //给云任务列表传参 Cloudlet cloudlet = new Cloudlet(id, length, pesNumber, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel); cloudlet.setVmId(vmid); // 添加云任务到云任务列表中 cloudletList.add(cloudlet); //创建用于存放每个任务成本的数组 double [] costs=new double[cloudletList.size()]; Vm vm = new Vm(vmid, brokerId, mips, pesNumber, ram, bw, size, vmm, new CloudletSchedulerTimeShared()); // 添加虚拟机到虚拟机列表中 vmList.add(vm); //创建PE列表 List<Pe> peList1 = new ArrayList<Pe>(); //创建PE并放入列表中 //需要一个存储pe的id和MIPS比率 peList1.add(new Pe(0, new PeProvisionerSimple(mips))); peList1.add(new Pe(1, new PeProvisionerSimple(mips))); peList1.add(new Pe(2, new PeProvisionerSimple(mips))); peList1.add(new Pe(3, new PeProvisionerSimple(mips))); List<Pe> peList2 = new ArrayList<Pe>(); peList2.add(new Pe(0, new PeProvisionerSimple(mips))); peList2.add(new Pe(1, new PeProvisionerSimple(mips))); //创建主机时,给相关参数赋值 int hostId = 0; //主机内存 int ram1 = 2048; //主机的存储空间 long storage = 1000000; int bw1 = 10000; hostList.add( new Host( hostId, new RamProvisionerSimple(ram1), new BwProvisionerSimple(bw1), storage, peList1, new VmSchedulerTimeShared(peList1) ) );//第一台主机 hostId++; hostList.add( new Host( hostId, new RamProvisionerSimple(ram), new BwProvisionerSimple(bw), storage, peList2, new VmSchedulerTimeShared(peList2) ) ); // 第二台主机 //系统框架 String arch = "x86"; //操作系统名称 String os = "Linux"; double time_zone = 10.0; //在这个资源中进程在使用时的消耗 double cost = 3.0; //在这个资源中使用内存的消耗 double costPerMem = 0.05; //存储空间的消耗 double costPerStorage = 0.001; // 在这个资源中Bw的消耗 double costPerBw = 0.0; LinkedList<Storage> storageList = new LinkedList<Storage>(); DatacenterCharacteristics characteristics = new DatacenterCharacteristics( arch, os, vmm, hostList, time_zone, cost, costPerMem, costPerStorage, costPerBw); //该循环用于获取云任务的成本 for(int o=0;o<cloudletList.size();o++){ costs[o]=characteristics.getCostPerMem()*vmList.get(o).getRam()+ characteristics.getCostPerStorage()*vmList.get(o).getSize(); } //创建一个Power数据中心 Datacenter datacenter = null; try { datacenter = new Datacenter(name, characteristics, new VmAllocationPolicySimple(hostList), storageList, 0); } catch (Exception e) { e.printStackTrace(); } return datacenter; } //创建broker public static DatacenterBroker createBroker() { DatacenterBroker broker = null; try { broker = new DatacenterBroker("Broker"); } catch (Exception e) { e.printStackTrace(); return null; } return broker; } //创建云任务列表的函数 public 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("###.##"); int k;//g为MIPS最大值的虚拟机编码,k为中间替换参数,这里和上边一样用冒泡排序 int [] b =new int[size];//b数组用于存放每个任务的长度 int [] c =new int[size];//最终存放每个任务的信用值 int [] q =new int[size];//q数组为经过计算后的每个任务的长度 double [] d =new double[size]; //创建信用度优先级的数组 int [] e =new int[vmlist.size()];//创建vm的数组,用来存放数组列表中所有的mips长度 double [] deadline=new double[size]; //创建用来放置Deadline_task的数组 double [] Load=new double[size];//用来存放虚拟机中负载的数组 double cost=0.8;//确定成本系数 double [] vmholds=new double[vmlist.size()];//创建用来存储各个虚拟机总容量的数组 double vmaverrage;//虚拟机的标准差 int [] a=new int[vmlist.size()];//该数组用于存放存储过载虚拟机的序列号,等价于将过载的虚拟机放入过载序列中 for (int i = 0; i < size; i++) { cloudlet = list.get(i); //用于存放每个任务的长度 b[i]= (int) list.get(i).getCloudletLength(); //int [] c =new int[size];//用于存放每个调度任务的credit值 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())); } } for (int f=0;f< vmlist.size();f++){ e[f]=(int) vmlist.get(f).getMips(); //该循环用于获取虚拟机列表中各个元素的MIPS长度 } //通过冒泡法将MIPS最大的虚拟机置换到最前边,即MIPS长度最大的虚拟机的数组编码为0 for (int h=0;h< vmlist.size();h++){ if(e[h]<e[h++]){ k=e[h]; e[h]=e[h++]; e[h++]=k; } } double total=0.0; for(int j=0;j<size;j++){ int t;//作为下边交换的中间值 int m=0,n;//m为任务列表中每个任务的长度,n为平均值 m=(int) (m+b[j]); n=m/(j+1); q[j]=(int)Math.abs(n-b[j]+1);//这里调用Math里面的绝对值函数 //均为实验中计算信用值的参数 int a1,a2,a3,a4; //该循环用来求出所有任务的长度的最大值 for(int y=1;y<size;y++){ if (b[y]>b[j]){ t=b[y]; b[y]=b[j]; b[j]=t; }//这块需要注意,要放在大循环的外边,因为必须等待云任务列表中所有的云任务被分配完毕后,才能调用 } a1=b[0]/5; a2=b[0]/4; a3=a2+a1; a4=a3+a2; //设置if语句用来设置信用值 if (q[j] <= a1 || a1 == 1) { credit = 5; } else if (a1 < q[j] && q[j] <= a2) { credit = 4; } else if (a2 < q[j] && q[j] <= a3) { credit = 3; } else if (a3 < q[j] && q[j] <= a4) { credit = 2; } else { credit = 1; } //最终存放每个任务的信用值 c[j]=credit; //d[j]为每个任务的优先级的权重,方便之后的调用 d[j]=c[j]*1000/q[j];//这里的可分除因素我们选用上边的q[i] //用来放置Deadline_task deadline[j]= (c[j]*d[j]/e[0]); //计算出所有云任务的总成本costs[i] costtotal=c[j]*d[j]*deadline[j]*cost; //设置if语句,由于虚拟机在创建时的个数为20,云任务为40,则输出20个虚拟机中的负载的大小 if(j<20) { Load[j] = vmlist.get(j).getSize() * b[j] / (vmlist.get(j).getMips()*10); Log.printLine(" "); Log.printLine("虚拟机"+j+"负载量为:"+Load[j]); } //这里创建Bee类的对象,获取Bee类的参数 b2.NP= vmlist.size(); b2.FoodNumber= list.size(); for (int i=0;i< b2.FoodNumber;i++){ b2.Credit[i]=c[i]; b2.Cost[i]=cost; b2.deadline[i]=deadline[i]; b2.length[i]=list.size(); } Log.printLine(""); Log.printLine("云任务"+j+"的长度为:"+q[j]); Log.printLine("云任务"+j+"的优先级权重为:"+d[j]); Log.printLine("云任务"+j+"的成本为:"+costtotal); total=total+costtotal; } Log.printLine("云任务的总成本数:"+total); //计算特定虚拟机的序列号 VmholdIndex=CreateVmholdIndex((int)b2.GlobalMin); Log.printLine("特定虚拟机的序列号为:"+VmholdIndex); //计算特定虚拟机的总容量 Vmhold=vmlist.size()*vmlist.get(VmholdIndex).getMips()+vmlist.get(VmholdIndex).getBw(); Log.printLine("特定虚拟机的总容量为:"+Vmhold); Log.printLine("特定虚拟机的负荷为:"+Load[VmholdIndex]); //计算该虚拟机处理的时间 processtime=Load[VmholdIndex]/Vmhold; Log.printLine("处理时间:"+processtime+"ms"); double o=0; double y; //设置循环,用来存储所有虚拟机的容量,方便计算虚拟机的标准差 for(int p=0;p<vmlist.size();p++){ vmholds[p]=vmlist.size()*vmlist.get(p).getMips()+vmlist.get(p).getBw(); //o用来存放所有虚拟机的总容量 o=o+vmholds[p]; } //虚拟机容量的平均值 y=o/vmlist.size(); double fangcha=0; for(int n=0;n<vmlist.size();n++){ fangcha=fangcha+(vmholds[n]-y)*(vmholds[n]-y); } //这里获取虚拟机的标准差 vmaverrage=Math.sqrt(fangcha); Log.printLine("虚拟机容量的标准差"+vmaverrage); //这里设置循环,存放超载的虚拟机的序列号 for(int f=0;f<vmlist.size();f++){ if(vmholds[f]<vmaverrage){ a[f]=f; } } List l=new java.util.ArrayList(); //该循环进行数组中相同数的过滤 for(int t=0;t<a.length;t++){ if(!l.contains(a[t])) l.add(a[t]); } Log.printLine("20台虚拟机中超负载虚拟机的序号:(注意:这里由于输出的为过载的虚拟机序列号,根据实验要求将会停止仿真)"); //设置循环,将上述数组中过滤后的数值给输出出来 for(Iterator ll = l.iterator(); ll.hasNext();){ Log.printLine(ll.next()); CloudSim.stopSimulation(); } Log.printLine(" "); Log.printLine("仿真完毕!!!"); } }
云计算框架下基于信用的调度算法分析
于 2022-02-09 15:11:33 首次发布