You are on page 1of 19

CloudSim 学习

2009年4月8日,澳大利亚墨尔本大学的网格实验室和Gridbus项目宣布推出
云计算仿真软件,称为CloudSim。它是在离散事件模拟包SimJava上开发的函
数库,可在Windows和Linux系统上跨平台运行,CloudSim继承了GridSim的编
程模型,支持云计算的研究和开发,并提供了以下新的特点:
⑴支持大规模的云计算环境的模拟与仿真,包括数据中心,单一物理计算节
点;
⑵为模拟云、服务代理、供应、分配策略提供独立的平台;
⑶支持在模拟系统元素间仿真网络连接;
⑷具有在联合的云环境下仿真的功能,私有和公共领域的混合网络资源,对
有关 Cloud-Bursts 和自动应用伸缩的关键功能的研究。
CloudSim 是在 GridSim 模型基础上发展而来,提供了云计算的特性,支持
云计算的资源管理和调度模拟。云计算与网格计算的一个显著区别是云计算采用
了成熟的虚拟化技术,将数据中心的资源虚拟化为资源池,打包对外向用户提供
服务,CloudSim 体现了此特点,扩展部分实现了一系列接口,提供基于数据中
心的虚拟化技术、虚拟化云的建模和仿真功能。通常,数据中心的一台主机的资
源可以根据用户的需求映射到多台虚拟机上,因此,虚拟机之间存在对主机资源
的竞争关系。CloudSim 提供了资源的监测、主机到虚拟机的映射功能。CloudSim
的 CIS(Cloud Information Service)和 DataCenterBroker 实现资源发现和信息
交互,是模拟调度的核心。用户自行开发的调度算法可在 DataCenterBroker 的
方法中实现,从而实现调度算法的模拟。

1、CloudSim 的几个核心类
(1)Cloudlet 类:构建云环境下的任务。
(2)DataCenter 类:数据中心,提供虚拟化的网格资源,处理虚拟机信息的
查询,包含虚拟机对资源的分配策略,云计算采用 VMProvisioner 处理虚拟机。
(3)DataCenterBroker 类:隐藏了虚拟机的管理,如创建、任务提交、虚拟机
的销毁等。
(4)Host 类:扩展了机器对虚拟机除处理单元(PE)之外的参数分配策略,如带
宽、存储空间、内存等,一台 Host 可对应多台虚拟机。
(5)VirtualMachine 类:虚拟机类,运行在 Host 上,与其它虚拟机共享资源,
每台虚拟机由一个拥有者所有,可提交任务,并由 VMScheduler 类定制该虚拟
机的调度策略。
(6)VMScheduler 类:虚拟机的调度策略,用来管理执行任务,实现了任务接
口。
(7)VMCharacteristics 类:提供虚拟机描述。
(8)VMMAllocationPolicy 类:虚拟机监视器策略类,描述同一 Host 上的多台
虚拟机共享资源的策略。
(9)VMProvisioner 类:实现数据中心的主机到虚拟机的映射。

jar.xml 所在目录),在命令行下键入命令 D:/CloudSim>ant, 批量编译 CloudSim 源文件,生成的文件按照 build.7.0_02,CloudSim 需要运行在 JDK1.7.0_02/bin.3, 设置环境变量,在 PATH 中加入:D:/apache-ant-1. 新建 ClassPath 并加入路径:C:/Program Files/Java/jdk1.project name :cloudsim 3.0_02/lib/tools.jar。扩展的 CloudSim 平台生成成功。 重设环境变量,在 ClassPath 中增加路径: D:/CloudSim/jars/new_cloudsim.0 及以上 (3.然后点击完成就可以运行了。 (4)在 Netbeans 中使用 Cloudsim 见第 6 节。 3、CloudSim 的扩展 CloudSim 是开源的,可以在 windows Xp 和 linux 上运行,用户可以根据自己 的研究内容自行扩展 CloudSim,加入自己的代码后,需要重新编译并发布平台。 下面给出编译和生成平台的方法: 从 http://ant.2)版本,下载的是一个 Zip 包或者 tar.jar.com/technetwork/java/javase/downloads/index.8.在目录中选择 cloudsim 包的路 径。 4.google.,下一步在新的平台下编写自己的仿真 验证程序。 4、使用 CloudSim 仿真的一般步骤 (1) 初始化 CloudSim 库 CloudSim.org/ 下载 Ant 工具,解压到目录 D:/apache-ant-1.选中 create project from exiting source.7.3.com/p/cloudsim/downloads/list 下载 CloudSim 3.7.xml 的设置存储到指定位置, 编译成功后在命令行下键入 D:/CloudSim>ant makejar 命令打包生成 new_cloudsim. 。 (2)CloudSim 配置 从 http://code.D:/CloudSim/jars/cloudsim.jar. D:/CloudSim/jars/simjava2.0_02/lib/dt. trace_flag).apache.Eclipse->File->new->java project-> 2.3/bin.6 版本以上。安装下载的 JDK, 设置环境变量。在 Path 中加入路径:C:/Program Files/Java/jdk1.0.2、CloudSim 环境配置 (1)JDK 安装和配置 从 http://www.oracle. (2) 创建数据中心,在 CloudSim 仿真平台中,一个数据中心由一个或多个 .jar.jar. calendar.gz 包,解压压缩包即可得到源 代码。 (3)在 Eclipse 中使用 Cloudsim 1.init(num_user.8.html 下载 JDK 最 新版本 jdk1.。将命令行切换到扩展 的 CloudSim 路径(build.jar.1.D:/CloudSim/jars/ g-ridsim.0. C:/Program Files/Java/jdk1.

(5) 创建云任务 cloudletList = new ArrayList<Cloudlet>(). long outputSize = 300. int pesNumber = 1. int mips = 250. mips. bw. pesNumber=1. String vmm = "Xen". (4) 创建虚拟机 vmlist = new ArrayList<Vm>().getId().add(vm1). //VM 描述参数 int vmid = 0.submitVmList(vmlist). int ram = 512. vmm. size.BrokerID //Cloudlet 描述参数 int id = 0. long length = 250000. //创建时为虚拟机指定 Broker Vm vm1 = new Vm(vmid. long fileSize = 300. //创建时指定任务的用户 ID. long bw = 1000.Machine 组成,一个 Machine 是由一个或多个 PEs 或 CPUs 组成。 Datacenter datacenter0 = createDatacenter("Datacenter_0"). long size = 10000. //将虚拟机加入虚拟机列表 vmlist. //向相应代理 Broker 提交虚拟机列表 broker. int brokerId = broker. new CloudletSchedulerTimeShared()). (3) 创建代理 Broker DatacenterBroker broker = createBroker(). ram. pesNumber. . brokerId.

5、调度策略的扩展实现 根据自己研究需要对平台进行了扩展,调度算法可以在 DatacenterBroker 中实现.printDebts(). cloudlet1. Cloudlet cloudlet1 = new Cloudlet(id.new UtilizationModel utilizationModel =new UtilizationModelFull(). fileSize. utilizationModel.getCloudletReceivedList(). datacenter0. outputSize.submitCloudletList(cloudletList). …… //将任务加入任务列表 cloudletList. printCloudletList(newList). CloudSim. (6) 启动仿真 CloudSim.startSimulation().add(cloudlet1). utilizationModel. length. pesNumber. …… //向代理Broker提交任务列表 broker.stopSimulation().setUserId(brokerId). utilizationModel).从而达到自定义调度算法的扩展。 Cloudsim 里面的任务执行时间等于任务的指令长度(MI)除以运行该任务 的虚拟机的执行速度(MIPS),即 T=MI / MIPS。现在仅考虑任务的执行时间 只与 MI 和 MIPS 有关,则有以下结论: a、如果一个虚拟机上同时运行多个任务,不论使用空间共享还是时间共享, 这些任务的执行时间是一定的。(任务的总指令长度和虚拟机的执行速度是一定 的)。 b、如果一个任务在某个虚拟机上执行的时间最短,那么它在其他虚拟机上 的执行时间也是最短的。 c、如果一个虚拟机的执行速度最快,那么它不论执行哪个任务都是最快的。 . (7) 在仿真结束后统计结果 List<Cloudlet> newList = broker.

idx = (idx+1)%vmNum.sort(cloudletList.getId()).new new VmComparator()). //cloudletList按MI降序排列. int vmNum=vmList. Collections.setVmId(vmList. int idx = 0.i<cloudletNum.get(idx).size(). for int i=0.get(i).size(). int vmId) 函数后面添加: public void bindCloudletsToVmsSimple(){ int vmNum = vmList.new //////////For test////////////////////////////////// System.size(). //time[i][j] 表示任务i在虚拟机j上的执行时间 new double double double[][] time=new double[cloudletNum][vmNum].1、顺序分配策略 在 DatacenterBroker 类中实现方法 bindCloudletsToVmsSimple():用于把 一组任务顺序分配给一组虚拟机,当所有的虚拟机都运行有任务后,再从第一个 虚拟机开始重头分配任务。 2、贪心策略 在 DatacenterBroker 类中实现方法 bindCloudletsToVmsTimeAwared(): 定义一个矩阵 time[i][j],表示任务 i 在虚拟机 j 上所需的执行时间。在初始化 矩阵 time 前,首先将任务按 MI 的大小降序排序,将虚拟机按 MIPS 的大小升序 排列。 从矩阵中行号为 0 的任务开始,每次都尝试分配给最后一列对应的虚拟机, 如果该选择相对于其他选择是最优的,就完成分配,否则将任务分配给使当前结 果最优的虚拟机。同时,如果有多种分配方法都能使当前结果最优,则将任务分 配给运行任务最少的虚拟机。 代码如下: 在 DatacenterBroker 中 bindCloudletToVm(int cloudletId. . int cloudletNum = cloudletList. vm按MIPS升序排列 new CloudletComparator()). } } public void bindCloudletsToVmsTimeAwared(){ int cloudletNum=cloudletList.println("///////////For test///////////////").size().out.i++){ for(int cloudletList. Collections.sort(vmList.

out.println(). //在某个Vm上运行的任务数量 double minLoad=0.getCloudletId()+":"+cloudletList.getCloudletLength()+" "). vmTasks[vmNum-1]=1.//在某个虚拟机上任务的总执行时间 new int int int[] vmTasks=new int[vmNum].get(0). cloudletList.print("time["+i+"]["+j+"]="+time[i][j]+" //For test } System. int i=1.getId()+":"+vmList. ").getMips()+" "). System. } System.i++){ for for(int System.println().getId()).get(i).i++){ for(int int j=0.setVmId(vmList.print(vmList.get (i).getMips(). //For test } double new double double[] vmLoad=new double[vmNum].getCloudletLength()/vmList.println().out. ////////////////////////////////////////////////////////////////////// for int i=0.get(i). } System.out.i<cloudletNum.//记录当前任务最优分配方式对应的虚拟机列号 //第一个cloudlet分配给最快的vm vmLoad[vmNum-1]=time[0][vmNum-1]. int i=0.out.int i=0.j++){ for for(int time[i][j]= double (double double)cloudletList. int j=vmNum-2. System.get(i). idx=vmNum-1.i++){ for for(int minLoad=vmLoad[vmNum-1]+time[i][vmNum-1].get(i).out.j>=0.out.i++){ for for(int System.//记录当前任务分配方式的最优值 int idx=0.get(vmNum-1).i<cloudletNum.println("//////////////////////////////////").out.j<vmNum.get(j).i<vmNum. .i<cloudletNum.j--){ for for(int //如果当前虚拟机未分配任务,则比较完当前任务分配给该虚拟机是否最优 if if(vmLoad[j]==0){ if if(minLoad>=time[i][j])idx=j.print(cloudletList.

} if if(minLoad>vmLoad[j]+time[i][j]){ minLoad=vmLoad[j]+time[i][j]. } } //Cloudlet根据MI降序排列 private class CloudletComparator implements Comparator<Cloudlet>{ public int compare(Cloudlet cl1.out.DecimalFormat.println().examples 目录下新建 MyAllocationTes MyAllocationTest 类,添加代码: package org. vmTasks[idx]++.get(idx). System.getCloudletLength()-cl1.cloudbus. } //简单的负载均衡 else if if(minLoad==vmLoad[j]+time[i][j]&&vmTasks[j]<vmTasks[idx]) idx=j.cloudsim.getMips()).cloudbus.getId()). } vmLoad[idx]+=time[i][idx].Cloudlet cl2){ int return (int int)(cl2. cloudletList. } } ///////////////////////////////////////////////////////////////////////// t 在 org.examples.getMips()-vm2.break break.out. idx=j. .getCloudletLength()). import java.Vm vm2){ int return (int int)(vm1.cloudsim.setVmId(vmList. System.text. } } //Vm根据MIPS升序排列 private class VmComparator implements Comparator<Vm>{ public int compare(Vm vm1.get(i).print(i+"th "+"vmLoad["+idx+"]="+vmLoad[idx]+" minLoad="+minLoad).

Calendar.cloudsim.cloudsim.Host.PeProvisionerSimple. org. org.UtilizationModel.cloudbus.cloudbus.VmAllocationPolicySimple.BwProvisionerSimple.cloudbus.DatacenterCharacteristics.cloudbus.cloudsim.Cloudlet.cloudsim.DatacenterBroker. private static int cloudletNum = 10. org.cloudsim.Storage. java.List.cloudbus.import import import import java. /** * Creates main() to run this example */ public static void main(String[] args) { Log. org. java.cloudbus.printLine("Starting TestAllocation. org.cloudbus.cloudsim.. */ private static List<Cloudlet> cloudletList.VmSchedulerTimeShared.cloudsim.cloudsim. org.CloudSim.LinkedList.cloudbus.util. /** The vmlist.cloudsim.cloudsim.Datacenter.Vm.Log. org. org. java.provisioners. private static int vmNum = 5.cloudsim.cloudbus. org. org. import import import import import import import import import import import import import import import import import import import org.util.cloudsim. try { // First step: Initialize the CloudSim package.core.cloudsim.util.cloudsim.cloudbus.cloudbus.RamProvisionerSimple. org.cloudsim. */ private static List<Vm> vmlist.cloudsim.cloudbus.util. org.cloudbus. org. public class MyAllocationTest { /** The cloudlet list.").cloudsim.cloudsim. org.cloudbus.ArrayList.CloudletSchedulerSpaceShared.CloudletSchedulerTimeShared.cloudbus.cloudbus.provisioners.provisioners.cloudbus.Pe. org. org.cloudsim.UtilizationModelFull. org..cloudbus.cloudbus. org. It should be called .

brokerId. calendar.size.132. int pesNumber = 1. //Datacenter createDatacenter("Datacenter_1").new CloudletSchedulerSpaceShared())).pesNumber. int brokerId = broker.getId(). String vmm = "Xen". // 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"). = .ram. //VM description int vmid = 0. datacenter1 //Third step: Create Broker DatacenterBroker broker = createBroker(). int ram = 256.mipss[i].209. // number of cloud users Calendar calendar = Calendar.bw. //Cloudlet properties int id = 0. //Fourth step: Create one virtual machine vmlist = new ArrayList<Vm>().i<vmNum. int int[] mipss = new int int[]{278.289. boolean trace_flag = false false. trace_flag).vmm. long size = 10000.add(new new Vm(vmid. int num_user = 1.submitVmList(vmlist). } //submit vm list to the broker broker. vmid++.init(num_user. // mean trace events // Initialize the CloudSim library CloudSim.// before creating any entities. long bw = 1000.getInstance().i++){ for for(int new vmlist.286}. int i=0.

long fileSize = 300. CloudSim.lengths[i].bindCloudletsToVmsTimeAwared().49809. //bind the cloudlets to the vms.32018. the broker // will submit the bound cloudlets only to the specific VM //broker. UtilizationModel utilizationModel UtilizationModelFull(). 18336. broker.utilizationModel) . } //submit cloudlet list to the broker broker.long long[] lengths = long long[]{19365.31017}.fileSize.startSimulation(). This way. // Sixth step: Starts the simulation CloudSim.utilizationModel. cloudletList. new new outputSize.add(cloudlet).getCloudletReceivedList().utilizationModel. //add the cloudlets to the list cloudlet. long outputSize = 300. // Final step: Print results when simulation is over List<Cloudlet> newList = broker.20045.stopSimulation().31493.30727. //Print the debt of each user to each datacenter .i++){ for for(int Cloudlet cloudlet = Cloudlet(id.submitCloudletList(cloudletList).i < cloudletNum. id++. printCloudletList(newList). int i = 0.setUserId(brokerId).44157.pesNumber.bindCloudletsToVmsSimple(). new = //Fifth step: Create two Cloudlets cloudletList = new ArrayList<Cloudlet>().16754.

printLine("Unwanted errors happen"). // 3. new VmSchedulerTimeShared(peList) ) ). // This is our machine . A Machine contains one or more PEs or CPUs/Cores. new BwProvisionerSimple(bw). //host memory (MB) long storage = 1000000. //host storage int bw = 10000. new PeProvisionerSimple(mips))). new RamProvisionerSimple(ram). Create PEs and add these into a list. peList. storage. We need to create a list to store // our machine List<Host> hostList = new ArrayList<Host>(). new Pe(0. Log.datacenter0.printDebts().add(new need to store Pe id and MIPS Rating //4. int ram = 2048.printStackTrace(). int hostId=0. } catch (Exception e) { e. List<Pe> peList = new ArrayList<Pe>().add( new Host( hostId. // peList. Log. } } private static Datacenter createDatacenter(String name){ // Here are the steps needed to create a PowerDatacenter: // 1. // 2. Create Host with its id and list of PEs and add them to the list of machines hostList.printLine("TestAllocation finished!"). // PE and its properties int mips = 1000.

allocation policy: time. Datacenter datacenter = null null. we need to create a PowerDatacenter object.0. //we are not adding SAN devices by now //创建数据中心特征对象 DatacenterCharacteristics characteristics = new DatacenterCharacteristics( arch.0.0.// 5. OS. vmm. cost. // time zone this resource located double cost = 3. 0). } . costPerStorage. storageList. os.05. // the cost of using storage in this resource double costPerBw = 0. Create a DatacenterCharacteristics object that stores the // properties of a data center: architecture. // 6. of time zone // and its price (G$/Pe time unit). list // Machines.001. // the cost of using memory in this resource double costPerStorage = 0.printStackTrace(). costPerMem. // operating system String vmm = "Xen". // the cost of using processing in this resource double costPerMem = 0. new VmAllocationPolicySimple(hostList). costPerBw). double time_zone = 10. // system architecture String os = "Linux". hostList. characteristics. time_zone. String arch = "x86". // the cost of using bw in this resource LinkedList<Storage> storageList = new LinkedList<Storage>(). } catch (Exception e) { e. Finally. try { datacenter = new Datacenter(name. } return datacenter.or space-shared.

i < size.getVmId() . String indent = " ". Cloudlet cloudlet.printStackTrace().get(i). } catch (Exception e) { e. Log.##").getCloudletStatus() == Cloudlet.SUCCESS){ Log. Log. Log. to submit vms and cloudlets according //to the specific rules of the simulated scenario private static DatacenterBroker createBroker(){ DatacenterBroker broker = null null.printLine().print(indent + cloudlet. if (cloudlet.getResourceId() + indent + indent + indent + cloudlet. int i = 0. } return broker.printLine( indent + indent + cloudlet.//We strongly encourage users to develop their own broker policies.print("SUCCESS"). try { broker = new DatacenterBroker("Broker"). Log.size(). Log.getCloudletId() + indent + indent).printLine("========== OUTPUT =========="). i++) { for (int cloudlet = list. return null null.printLine("Cloudlet ID" + indent + "STATUS" + indent + "Data center ID" + indent + "VM ID" + indent + "Time" + indent + "Start Time" + indent + "Finish Time"). } /** * Prints the Cloudlet objects * @param list list of Cloudlets */ private static void printCloudletList(List<Cloudlet> list) { int size = list. DecimalFormat dft = new DecimalFormat("###.

72 241.23 *****Datacenter: Datacenter_0***** User id 3 Debt 91.28 0.38 6 SUCCESS 2 1 69.45 2 SUCCESS 2 2 242.1 172.39 7 SUCCESS 2 2 238.66 0.1 8 SUCCESS 2 3 147.01 211.58 242.81 242.96 69.format(cloudlet.65 481.76 1 SUCCESS 2 1 172.2 ********************************** TestAllocation finished! 69.getActualCPUTime()) + dft.38 358.format(cloudlet.format(cloudlet.76 135.1 5 SUCCESS 2 0 65.36 172. } } indent + } } bindCloudletsToVmsSimple()测试结果: 顺序分配策略 bindCloudletsToVmsSimple() ========== OUTPUT ========== Cloudlet ID STATUS Data center ID VM ID Time Start Time Finish Time 0 SUCCESS 2 0 69.35 0.55 0.45 3 SUCCESS 2 3 211.getFinishTime())).65 .+ indent + indent + indent + indent + dft.1 211.getExecStartTime())+ indent + dft.

78 3 SUCCESS 2 4 154.1 115.49 6 SUCCESS 2 4 70.23;贪心策略 283.49 9 SUCCESS 2 0 111.17 0.84 232.57 115.1 150.1: Broker: Postponing execution of cloudlet 1: bount VM not available 此问题待解决。。。 .78 238.vmCreate] Allocation of VM #1 to Host #0 failed by MIPS 0.58 283.77 0.16 224.51 4 SUCCESS 2 4 58.贪心策略 bindCloudletsToVmsTimeAwared() bindCloudletsToVmsTimeAwared()测试结果: ========== OUTPUT ========== Cloudlet ID STATUS Data center ID VM ID Time Start Time Finish Time 2 SUCCESS 2 0 115.68 0.1 154.27 7 SUCCESS 2 3 150.58 226.39 0.27 8 SUCCESS 2 2 232.2 ********************************** TestAllocation finished! 比较二者的完成时间: 顺序分配策略 481.1 5 SUCCESS 2 3 87.09 154.73 150.16,贪心策略提高了近 200 个时 间单位。 问题:测试代码是创建 10 个 cloudlet,5 个虚拟机,但最后结果只成功创建 了 8 个 cloudlet,4 个虚拟机? 错误提示为: [VmScheduler.87 *****Datacenter: Datacenter_0***** User id 3 Debt 91.58 224.

ee.ucl.Go to file-->>new project .1 如何在 Eclipse 添加自己的测试样例 启动 eclipse 选择 File->new ->Project -> java Project 在 Project name 那里写上你的工程名字,其它的默认就可以了.然后 finish. 在所建的 project 里面新建一个类。 在左侧的 Project explorer 下右键刚刚所建立的 project->new->class;在 name 处填写你的类名(这个类名要和你在记事本上写的的 java 的类要一致)。 然后 finish 就可以了.最后保存一下.同样在在 Project explorer 下找到你刚刚 建立的 project 下面的 src 下的你的那个类.右键->run as->java application 就可 以了。 6.0) .jar 放到 cloudsim 的 jars 文件夹下,在 Eclipse 里面右键点 击该 jar 文件,选择 Build Path,然后选 Add to Build Path 就可以了。 7、在 Netbeans 中使用 Cloudsim Step1 open Netbeans (any version greater then 5.uk/~mflanaga/java/#down 将 flanagan.6、问题及解决办法 6.2 由于 flanagan 包不存在导致一些例子不能运行的问题 添加 flanagan.ac.jar 支持,下载地址 http://www.

.Step 2 select "Java" folder then select first option java Application .then un-check the "create main class" press next.Press next Step3 Now give name to the project as you wish .

0.right click on it .click on "Add jars/Folders" Now browse the cloudsim folder which you have extracted from zip file .and go to "cloudsim-3. Step5 Go to library .2\jars" and select "cloudsim-3.2.a menu will come . .jar" .0.Step 4 Now your project is been created as shown.

.4 remain the same in step 5 copy and paste "org" folder from "cloudsim-3.2\source" and paste it into the source folder of your netbeans project as you copied the example folder.3.Step6 Now simply copy the "org" folder in "cloudsim-3.examples->>select any example .cloudbus.go to source and right click select Paste.right click on it and select "run" option the output will be displayed in the output window at the bottom.2\examples" and paste it to net beans source folder as shown.cloudsim.0. TO RUN EXAMPLE CODE FROM SOURCE CODE Step 1. Step 7 To run the example go to source ->> org.0.2.