1. CloudSim简介:

2009年4月8日,澳大利亚墨尔本大学的网格实验室和Gridbus项目宣布推出云计算仿真软件,称为CloudSim。它是在离散事件模拟包SimJava上开发的函数库,可在Windows和Linux系统上跨平台运行,CloudSim继承了GridSim的编程模型,支持云计算的研究和开发。

2. CloudSim提供了以下新的特点:

(1)支持大型云计算的基础设施的建模与仿真;
(2)一个自足的支持数据中心、服务代理人、调度和分配策略的平台。
(3)CloudSim 独特功能有:
  1. 提供虚拟化引擎,旨在数据中心节点上帮助建立和管理多重的、独立的、协同的的虚拟化服务;
  2. 在对虚拟化服务分配处理核心时能够在时间共享和空间共享之间灵活切换。CloudSim平台有助于加快云计算的算法、方法和规范的发展。CloudSim的组件工具均为开源的。CloudSim的软件结构框架和体系结构组件包括SimJava、GridSim、CloudSim、UserCode四个层次。
  3. CloudSim是在GridSim模型基础上发展而来,提供了云计算的特性,支持云计算的资源管理和调度模拟。
  4. 云计算与网格计算的一个显著区别是云计算采用了成熟的虚拟化技术,将数据中心的资源虚拟化为资源池,打包对外向用户提供服务,CloudSim体现了此特点,扩展部分实现了一系列接口,提供基于数据中心的虚拟化技术、虚拟化云的建模和仿真功能。通常,数据中心的一台主机的资源可以根据用户的需求映射到多台虚拟机上,因此,虚拟机之间存在对主机资源的竞争关系。CloudSim提供了资源的监测、主机到虚拟机的映射功能。
  5. CloudSim的CIS(Cloud Information Service)和DataCenterBroker实现资源发现和信息交互,是模拟调度的核心。用户自行开发的调度算法可在DataCenterBroker的方法中实现,从而实现调度算法的模拟。

3. 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类:实现数据中心的主机到虚拟机的映射。

4. CloudSim下载,CloudSim在IDEA中配置

CloudSim下载:
GitHub:https://github.com/Cloudslab/cloudsim
ClodSimPlus:https://cloudsimplus.org/
CloudSim在IDEA中配置: 👉哔哩哔哩

5. CloudSim环境配置

(1)JDK安装和配置
下载并配置好JDK1.8
(2)CloudSim配置
从http://www.gridbus.org/cloudsim/ 下载CloudSim 1.0 beta版,下载的是一个Zip包,解压压缩包即可。设置环境变量,在ClassPath中加入路径:C:/CLOUDSIM/jars/cloudsim.jar; C:/CLOUDSIM/jars/gridsim.jar; C:/CLOUDSIM/jars/simjava2.jar; 。

6. CloudSim的扩展

CloudSim是开源的,可以在windows Xp和linux上运行,用户可以根据自己的研究内容自行扩展CloudSim,加入自己的代码后,需要重新编译并发布平台。下面给出编译和生成平台的方法:
从http://ant.apache.org/ 下载Ant工具,解压到目录D:/apache-ant-1.7.1,设置环境变量,在PATH中加入:D:/apache-ant-1.7.1/bin;。将命令行切换到扩展的CloudSim路径(build.xml所在目录),在命令行下键入命令D:/CloudSim>ant,批量编译CloudSim源文件,生成的文件按照build.xml的设置存储到指定位置,编译成功后在命令行下键入D:/CloudSim>ant makejar命令打包生成new_cloudsim.jar。扩展的CloudSim平台生成成功。重设环境变量,在ClassPath中增加路径:D:/CloudSim/jars/new_cloudsim.jar;D:/CloudSim/jars/cloudsim.jar;D:/CloudSim/jars/g-ridsim.jar; D:/CloudSim/jars/simjava2.jar;,下一步在新的平台下编写自己的仿真验证程序。

7. 使用CloudSim仿真的一般步骤

//(1) 初始化GridSim 库
GridSim.init(num_user, calendar, trace_flag, exclude_from_file,exclude_from_processing, report_name);

//(2) 创建数据中心,在CloudSim仿真平台中,一个数据中心由一个或多个Machine组成,一个Machine是由一个或多个PEs或CPUs组成。
DataCenter datacenter0 = createDatacenter("Datacenter_0");

//(3) 创建代理Broker
DatacenterBroker broker = createBroker();
int brokerId = broker.get_id();

//(4) 创建虚拟机
vmlist = new VirtualMachineList();
//创建时为虚拟机指定Broker
VirtualMachine vm1 = new VirtualMachine(new VMCharacteristics(vmid,brokerId,size,memory,bw,vcpus,priority,vmm,new TimeSharedVMScheduler()));
//将虚拟机加入虚拟机列表
vmlist.add(vm1);
//向相应代理Broker提交虚拟机列表
broker.submitVMList(vmlist);

//(5) 创建云任务**
cloudletList = new CloudletList();
//创建时指定任务的用户ID,BrokerID          
Cloudlet cloudlet1 = new Cloudlet(id, length, file_size, output_size);
cloudlet1.setUserID(brokerId);
//将任务加入任务列表
cloudletList.add(cloudlet1);
//向代理Broker提交任务列表
broker.submitCloudletList(cloudletList);

//(6) 启动仿真
GridSim.startGridSimulation();

//(7) 在仿真结束后统计结果
CloudletList newList = broker.getCloudletList();
GridSim.stopGridSimulation();
printCloudletList(newList);
datacenter0.printDebts();
若是根据自己研究对平台进行了扩展,平台重生成后,就可以在仿真程序中调用自己编写的类、方法、成员变量等。

8. 使用CloudSim源码中 CloudSimExample1 的解读:

package org.cloudbus.cloudsim.examples;

/*
 * Title:        CloudSim Toolkit
 * Description:  CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation
 *               of Clouds
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 *
 * Copyright (c) 2009, The University of Melbourne, Australia
 */

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.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 data center with one host and run one cloudlet on it.
 * 演示如何使用一台主机创建一个数据中心并在其上运行一个cloudlet。
 * ContainerCloudSimExample1模拟了如何使用一台主机、一台VM、一个容器创建一个数据中心,并在其上运行一个云任务
 * ContainerCloudSimExample1为例,可将仿真流程分成三个阶段:初始化仿真环境,执行仿真,结束仿真,从这三个阶段对容器编程进行了解。
 */
public class CloudSimExample1 {
	/** The cloudlet list. */
	private static List<Cloudlet> cloudletList;
	/** The vmlist. */
	private static List<Vm> vmlist;

	/**
	 * 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.
			//在创建任何实体类之前,必须初始化CloudSim包
			int num_user = 1; // number of cloud users
			Calendar calendar = Calendar.getInstance(); // Calendar whose fields have been initialized with the current date and time.
 			boolean trace_flag = false; // trace events

			/* Comment Start - Dinesh Bhagwat 
			 * Initialize the CloudSim library.  初始化CloudSim库
			 *
			 * init()调用initCommonVariable(),initCommonVariable()又调用initialize()(这三个方法都在CloudSim.java中定义)
			 * init() invokes initCommonVariable() which in turn calls initialize() (all these 3 methods are defined in CloudSim.java).
			 *
			 * initialize()创建两个集合-SimEntity对象(表示模拟实体的命名实体)的ArrayList和 LinkedHashMap(名为entitiesByName,表示相同仿真实体的LinkedHashMap),每个SimEntity的名称作为键。
			 * initialize() creates two collections - an ArrayList of SimEntity Objects (named entities which denote the simulation entities) and
			 * a LinkedHashMap (named entitiesByName which denote the LinkedHashMap of the same simulation entities), with name of every SimEntity as the key.
			 *
			 * initialize()创造两个队列:一个future的SimEvent队列 和 一个deferred的SimEvenr队列
			 * initialize() creates two queues - a Queue of SimEvents (future) and another Queue of SimEvents (deferred).
			 *
			 * initialize()创造一个谓词的 HaspMap , 这些谓词用于为延迟队列选择特定事件
			 * initialize() creates a HashMap of of Predicates (with integers as keys) - these predicates are used to select a particular event from the deferred queue.
			 *
			 * initialize() 将模拟时钟设置为0,将running设置为flse
			 * initialize() sets the simulation clock to 0 and running (a boolean flag) to false.
			 *
			 * 一旦initialize()返回(请注意,我们现在使用的是initCommonVariable()方法),就会创建一个CloudSimShutDown(从SimEntity派生)实例
			 * Once initialize() returns (note that we are in method initCommonVariable() now), a CloudSimShutDown (which is derived from SimEntity) instance is created
			 *
			 * (numuser为1,名称为CloudSimShutDown,id为-1,state为RUNNABLE)。然后将此新实体添加到模拟中
			 * (with numuser as 1, its name as CloudSimShutDown, id as -1, and state as RUNNABLE). Then this new entity is added to the simulation
			 *
			 * 当被添加到模拟中时,其id更改为0(从早期的-1)。两个集合-entities和entitiesByName使用此SimEntity更新。
			 * While being added to the simulation, its id changes to 0 (from the earlier -1). The two collections - entities and entitiesByName are updated with this SimEntity.
			 *
			 * shutdownId(其默认值为-1)为0
			 * the shutdownId (whose default value was -1) is 0
			 *
			 * 一旦initCommonVariable()返回(请注意,我们现在使用的是init()方法),就会创建一个CloudInformationService(它也是从SimEntity派生的)实例
			 *  Once initCommonVariable() returns (note that we are in method init() now), a CloudInformationService (which is also derived from SimEntity) instance is created
			 *
			 * (名称为CloudInformatinService,id为-1,状态为RUNNABLE)。然后这个新实体也被添加到模拟中。
			 *  (with its name as CloudInformatinService, id as -1, and state as RUNNABLE). Then this new entity is also added to the simulation.
			 *
			 * 当被添加到模拟中时,simentity的id从其早期的值-1更改为1(这是下一个id)。两个集合-entities和entitiesByName使用此SimEntity更新。CIID(其默认值为-1)为1
			 * While being added to the simulation, the id of the SimEntitiy is changed to 1 (which is the next id) from its earlier value of -1. 
			 * The two collections - entities and entitiesByName are updated with this SimEntity.
			 * the cisId(whose default value is -1) is 1
			 * Comment End - Dinesh Bhagwat 
			 */

//			第一步:对于容器,在创建一些实体之前,初始化CloudSim工具包。num_user(云用户数量),calendar(日历), trace_flag(标志位)。
			CloudSim.init(num_user, calendar, trace_flag);

//			第二步:创建数据中心   ,数据中心是cloudSim 的资源提供者、需要列出其中一个来运行CloudSim模拟
			// 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 broker = createBroker();
			int brokerId = broker.getId();
//			第四步:创建虚拟机
			// Fourth step: Create one virtual machine
			vmlist = new ArrayList<Vm>();

			// VM description 虚拟机描述
			int vmid = 0;
			int mips = 1000;
			long size = 10000; // image size (MB)
			int ram = 512; // vm memory (MB)
			long bw = 1000;
			int pesNumber = 1; // number of cpus
			String vmm = "Xen"; // VMM name

			// create VM
			Vm vm = new Vm(vmid, brokerId, mips, pesNumber, ram, bw, size, vmm, new CloudletSchedulerTimeShared());

			// add the VM to the vmList 将创建的vm添加到虚拟机队列
			vmlist.add(vm);

			// submit vm list to the broker 将创建的vm提交给代理
			broker.submitVmList(vmlist);
//			第四步:创建一个 cloudlet
			// Fifth step: Create one Cloudlet
			cloudletList = new ArrayList<Cloudlet>();

			// Cloudlet properties  cloudlet描述
			int id = 0;
			long length = 400000;
			long fileSize = 300;
			long outputSize = 300;
			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  将cloudlet加入列表
			cloudletList.add(cloudlet);

			// submit cloudlet list to the broker 将cloudlet列表提交给代理
			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();
			System.out.println("打印CloudletList:");
			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) {

		//创建 PowerDatacenter 的步骤
		// Here are the steps needed to create a PowerDatacenter:
		// 1. We need to create a list to store  创建一个存储列表,来存储机器
		// our machine
		List<Host> hostList = new ArrayList<Host>();

		// 2. A Machine contains one or more PEs or CPUs/Cores.一台机器包含一个或多个PE或CPU
		// In this example, it will have only one core.
		List<Pe> peList = new ArrayList<Pe>();

		int mips = 1000;

		// 3. Create PEs and add these into a list. 创建PE并加入到列表中
		peList.add(new Pe(0, new PeProvisionerSimple(mips))); // need to store Pe id and MIPS Rating 需要存储Pe id和MIPS等级(此处只加了一个pe)

		// 4. Create Host with its id and list of PEs and add them to the list 创建具有id和PE列表的主机,并将他们添加到计算机列表中
		// 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
		//创建一个 DatacenterCharacteristics 对象来存储数据中心的属性:体系结构、操作系统、计算机列表、分配策略(时间或空间共享、时区及其价格)
		// 5. Create a DatacenterCharacteristics object that stores the properties of a data center: architecture, OS, list of
		// Machines, allocation policy: time- or space-shared, time zone
		// and its price (G$/Pe time unit).
		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 {
			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
//	我们强烈鼓励用户开发自己的代理策略,根据模拟场景的特定规则提交vm和cloudlet
//	此处,可以考虑如何改变代理策略
	/**
	 * 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()));
			}
		}
	}
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐