分布式计算、云计算与大数据 第2版 课件 第5章 云计算编程实践_第1页
分布式计算、云计算与大数据 第2版 课件 第5章 云计算编程实践_第2页
分布式计算、云计算与大数据 第2版 课件 第5章 云计算编程实践_第3页
分布式计算、云计算与大数据 第2版 课件 第5章 云计算编程实践_第4页
分布式计算、云计算与大数据 第2版 课件 第5章 云计算编程实践_第5页
已阅读5页,还剩104页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章云计算编程实践提纲5.1CloudSim体系结构和API介绍5.2CloudSim环境搭建和使用方法5.3CloudSim扩展编程5.4CloudSim的编程实践5.5OpenStack编程实践CloudSim体系结构CloudSim是一个通用、可扩展的新型仿真框架,支持无缝建模和模拟,并能进行云计算基础设施和管理服务的实验。这个仿真框架有如下几个特性:支持在单个物理节点上进行大规模云计算基础设施的仿真和实例化。提供一个独立的平台,供数据中心、服务代理、调度和分配策略进行建模。提供虚拟化引擎,可在一个数据中心节点创建和管理多个独立、协同的虚拟化服务。可以在共享空间和共享时间的处理核心分配策略之间灵活地切换虚拟化服务。

CloudSim方便用户在组成、配置和部署软件前评估和模拟软件,减少云计算环境下,访问基础设施产生的资金耗费。基于仿真的方法使用户可在一个可控的环境内免费地反复测试他们的服务,在部署之前调节性能瓶颈。CloudSim体系结构CloudSim采用分层的体系结构,其架构及其架构组件如下图所示。CloudSim核心模拟引擎GridSim原本是CloudSim的一个组成部分,但GridSim将SimJava库作为事件处理和实体间消息传递的框架,而SimJava在创建可伸缩仿真环境时暴露出一些不足:不支持在运行时通过编程方式重置仿真。不支持在运行时创建新的实体。SimJava的多线程机制导致性能开销与系统规模成正比,线程之间过多的上下文切换导致性能严重下降。多线程是系统调试变得更加复杂。CloudSim核心模拟引擎为了克服这些限制并满足更复杂的仿真场景,墨尔本大学的研究小组开发了一个全新的离散事件管理框架。离散事件管理框架相关的类1)CloudSim这是主类,负责管理事件队列和控制仿真事件的顺序执行,这些事件按照它们的时间参数构成有序队列。在每一步调度的仿真事件会从未来事件队列(FutureEventQueue)中被删除,并被转移到延时事件队列(DeferredEventQueue)中。每个实体调用事件处理方法会从延时事件队列中选择事件并执行相应的操作。这样灵活的管理方式,具有以下优势:支持实体失活操作。支持不同状态实体的上下文切换,暂停或继续仿真流程。支持运行中创建新实体。支持运行中终止或重启仿真流程。2)DeferredQueue实现CloudSim使用的延时事件队列。3)FutureQueue实现CloudSim使用的未来事件队列。离散事件管理框架相关的类4)CloudInformationService(CIS)提供资源注册、索引和发现能力的实体,支持两个基本操作:publish():允许实体使用CIS进行注册。search():允许实体发现其他实体的状态和位置,并且该实体在仿真结束时会通知其他实体。5)SimEntity代表一个仿真实体,该实体既能向其他实体发送消息,也能处理接收到的消息。所有的实体必须扩展该类并重写三个核心方法即startEntity()、processEvent()以及shutdownEntity()。它们分别定义了实体初始化、事件处理和实体销毁的行为。SimEntity类提供调度新事件和向其他实体发送消息的能力,其中消息传递的网络延时是由BRITE模型计算出来的。实体一旦建立就会使用CIS自动注册。6)CloudSimTags包含多个静态的事件或命令标签,决定Cloudsim实体在接收和发送事件时要采取的操作类型。离散事件管理框架相关的类7)SimEvent给出了在两个或多个实体间传递仿真事件的过程。SimEvent存储了关于事件的信息,包括事件的类型、初始化时间、事件发生的时间、结束时间、事件转发到目标实体的时间、资源标识、目标实体、事件标签及需要传输到目标实体的数据。8)CloudSimShutdown用于结束所有终端用户和代理实体,并向CIS发送仿真结束信号。9)Predicate这是一个抽象类,需要扩展,用于从延时队列中选择事件。10)PredicateAny表示匹配延时队列中的任何一个事件。CloudSim的类中有一个可以公开访问的实例CloudSim.SIM_ANY,因此不需要为该类创建新的实例。11)PredicateFrom表示被特定实体放弃的事件。离散事件管理框架相关的类12)PredicateNone表示不匹配延时队列中的任何一个事件。CloudSim的类中有一个可以公开访问的实例CloudSim.SIM_NONE,因此不需要为该类创建新的实例。13)PredicateNotFrom选择已经被特定对象发送的事件。14)PredicateType根据选择特定标签选择事件。15)PredicateNotType选择不满足特定标签选择事件。CloudSim层CloudSim的体系结构分为两层:CloudSim仿真层和用户代码层。CloudSim仿真层为云数据中心环境的模拟和仿真提供支持,包括虚拟机、内存、存储器和带宽的专用管理接口。CloudSim层又可以细化为5层:网络层云资源层云服务层虚拟机服务层用户接口结构层CloudSim层1)网络层CloudSim中云实体的内部网络建立在网络抽象概念之上。在这个模型下,不会为模拟的网络实体提供真实可用的组件,比如路由器和交换机,而是通过延时矩阵来实现。如图所示为5个CloudSim实体的延时矩阵,矩阵的元素eij代表一条消息通过网络从实体i传输到j产生的延时。CloudSim层1)网络层CloudSim的事件管理引擎利用实体交互的网络延时信息来表示消息在实体间发送的延时。这意味着当仿真时间达到t+d时,事件管理引擎就会从实体i转发到实体j。其中t表示消息最初被发送时的仿真时间,d表示实体i到j的网络延时。交互的消息传递图如图所示。CloudSim层2)云资源层与云相关的核心硬件基础设施均由该层数据中心组件来模拟。数据中心实体由一系列主机组成,主机负责管理虚拟机在其生命周期内的一系列操作。每个主机都代表云中的一个物理计算节点,它会被预先配置一些参数,如处理器能力(用MIPS表示)、内存、存储器及为虚拟机分配处理核的策略等,而且主机组件实现的接口支持单核和多核节点的建模与仿真。为了整合多朵云,需要对云协调器(CloudCoordinator)实体进行建模。该实体不仅负责和其他数据中心及终端用户的通信,还负责监控和管理数据中心实体的内部状态。在监控过程中收到的信息将会活跃于整个仿真过程中,并被作为云交互时进行调度决策的依据。注意,没有一个云提供类似于云协调器的功能,如果一个非仿真云系统的开发人员想要整合多朵云上的服务,必须开发一个自己的云协调组件。通过该组件管理和整合云数据中心,实现与外部实体的通信,协调独立于数据中心的核心对象。在模拟一次云整合时,有两个基本方面需要解决:通信和监控。通信由数据中心通过标准的基于事件的消息处理来解决,数据中心监控则由云协调器解决。CloudSim的每一个数据中心为了让自己成为联合云的一部分都需要实例化云协调器,云协调基于数据中心的状态,对交互云的负载进行调整,其中影响调整过程的事件集合通过传感器(Sensor)实体实现。为了启用数据中心主机的在线监控,会将跟踪主机状态的传感器和云协调器关联起来。在监控的每个步骤,云协调器都会查询传感器。如果云协调器的负载达到了预先配置的阈值,那么它就会和联合云中的其他协调器通信,尝试减轻其负载。CloudSim层3)云服务层虚拟机分配:这是主机创建虚拟机实例的一个过程,由虚拟机分配控制器(VmAllocationPolicy)完成,默认的调度策略是先来先服务。给虚拟机分配处理内核:由主机完成,需考虑给每个虚拟机分配多少处理核及给定虚拟机对于处理核的利用率有多高,可采用的分配策略包括:空间共享策略、时间共享策略以及按需给虚拟机分配内核。考虑下面这种情况,一个云主机只有一个处理核,而在这个主机上同时产生了两个实例化虚拟机的需求。尽管虚拟机上下文(通常指主存和辅存空间)实际上是相互隔离的,但是它们仍然会共享处理器核和系统总线。因此,每个虚拟机的可能硬件资源被主机的最大处理能力及可能系统带宽限制。在虚拟机的调度过程中,要防止已创建的虚拟机对处理能力的需求超过主机的能力。为了在不同环境下模拟不同的调度策略,CloudSim支持两种层次的虚拟机调度:主机层和虚拟机层。在主机层指定每个处理核可以分配给虚拟机的处理能力;在虚拟机层,虚拟机为在其内运行的单个应用服务(任务单元)分配一个固定的可用处理器能力。CloudSim层3)云服务层在上述的每一层,CloudSim都实现了基于时间共享和空间共享的调度策略。为了清楚地解释这些策略之间的区别及它们对应用服务性能的影响,可参见下图所示的一个简单的虚拟机调度场景。一台拥有两个CPU内核的主机将要运行两个虚拟机,每个虚拟机需要两个内核并要运行4个任务单元。更具体来说,VM1上将运行任务t1、t2、t3、t4,而VM2将运行任务任务t5、t6、t7、t8。图(a)中虚拟机和任务单元均采用空间共享策略。由于采用空间共享模式,且虚拟机需要两个内核,所以在特定时间段内只能运行一个虚拟机。因此,VM2只能在VM1执行完任务单元才会被分配内核。VM1中的任务调度也是一样的,由于每个任务单元只需要一个内核,所以t1和t2可以同时执行,t3、t4则在执行队列中等待t1、t2完成后再执行。图(b)虚拟机采用空间共享策略,任务单元采用时间共享策略。因此,在虚拟机的生命周期内,所有分配给虚拟机的任务单元在其生命周期内动态地切换上下文环境。图(c)虚拟机采用时间共享策略,任务单元采用空间共享策略。这种情况下,每个虚拟机都会收到内核分配的时间片,然后这些时间片以空间共享的方式分配给任务单元。由于任务单元基于空间共享策略这就意味着对于一台虚拟机,在任何一个时间段内,内核只会执行一个任务。图(d)虚拟机和任务单元采用时间共享策略。所有虚拟机共享处理器能力,且每个虚拟机同时将共享的能力分给其任务单元。这种情况下,任务单元不存在排队延时。CloudSim层4)虚拟机服务层在这一层提供了对虚拟机生命周期的管理,如将虚拟机分配给主机、虚拟机创建、虚拟机销毁以及虚拟机和迁移等,以及对任务单元的操作。5)用户接口结构层该层提供了任务单元和虚拟机实体的创建接口。用户代码层CloudSim的最高层是用户代码层,该层提供了一些基本的实体,通过扩展基本实体,云应用开发人员能够进行如下活动:生成工作负载分配请求和应用配置请求。模拟云可用性场景,并基于自定义的配置进行稳健性测试。为云及联合云实现了自定义的应用调度技术。CloudSim3.0API介绍CloudSim3.0的API如下图所示,可以分为以下几个包,关于CloudSimAPI的详细信息可以访问http://www//cloudsim/doc/api/index.html获取。CloudSim3.0API介绍CloudSim云模拟器的类设计图如下图所示。CloudSim3.0API介绍下面将对CloudSim的基础类进行介绍。1)BwProvisioner这个抽象类用于模拟虚拟机的带宽分配策略。云系统开发和研究人员可以通过扩展这个类反映其应用的需求的变化,实现自己的策略(基于优先级或服务质量)。BwProvisionerSimple允许虚拟机保留尽可能多的带宽,并受主机总可用带宽的限制。2)CloudCoordinator这个抽象类整合了云数据中心,负责周期性地监控数据中心资源的内部状态和执行动态负载均衡的决策。3)Cloudlet模拟云应用服务,每个应用服务都会拥有一个预分配的指令长度和其生命周期内所需的数据传输开销。4)CloudScheduler扩展实现了多种策略,包括空间共享和时间共享策略,用于决定虚拟机内的应用服务如何共享处理器能力。CloudSim3.0API介绍5)Datacenter模拟云提供商提供的核心基础设施及服务。6)DatacenterBroker模拟一个代理,负责根据服务质量需求协调SaaS提供商和云提供商。如右图所示,为Datacenter、CIS和DatacenterBroker之间信息交互的过程。在仿真初期,每个数据中心实体都会通过CIS进行注册,当用户请求到达时,CIS就会根据用户的应用请求,从列表中选择合适的云服务提供商。图中对交互的描述依赖于实际的情况,比如从DatacenterBroker到Datacenter的消息可能只是对下一个执行动作的一次确认。CloudSim3.0API介绍7)DatacenterCharacteristics包含数据中心资源的配置信息。8)Host模拟物理资源,比如计算机、存储服务器等,并封存了一些重要的信息。9)NetworkTopology模拟网络延时的信息,保存由BRITE拓扑生成器生成的网络拓扑信息。10)RamProvisioner这个抽象类代表虚拟机分配主存的策略。11)SanStorage模拟了云数据中心的存储区域网,主要用于存储大量数据。CloudSim3.0API介绍12)Sensor模拟由主流云提供商提供的真实服务,定义了两个方法:为性能参数设置最小值和最大值以及周期性地更新测量值。其实现必须通过实例化一个能够被云协调器使用地传感器组件。13)Vm模拟了由主机组建托管和管理的虚拟机。14)VmAllocationPolicy这个抽象类代表虚拟机监控器使用的调度策略,用于将虚拟机分配给主机。15)VmScheduler这个抽象类由一个主机组件实现,模拟为虚拟机分配处理核所用的策略,可以重写。提纲5.1CloudSim体系结构和API介绍5.2CloudSim环境搭建和使用方法5.3CloudSim扩展编程5.4CloudSim的编程实践5.5OpenStack编程实践环境配置1)JDK安装和配置从/technetwork/java/javase/downloads/index.html下载JDK最新版本并安装,CloudSim需要运行在JDK1.6以上版本。以JDK1.8.0_333为例,默认的安装目录为C:\ProgramFiles\Java\jdk1.8.0_333。设置环境变量如下:新建系统变量JAVA_HOME,将变量值设为JDK安装目录,即C:\ProgramFiles\Java\jdk1.8.0_333;在Path中加入路径%JAVA_HOME%\bin;在ClassPath中加入路径%JAVA_HOME%\lib\dt.jar、%JAVA_HOME%\lib\tools.jar。2)解压CloudSim从/cloudsim/下载CloudSim,本书以CloudSim5.0为例。将其解压缩到磁盘,例如C:\cloudsim-5.0。运行样例程序C:\cloudsim-5.0\modules\cloudsim-example\src\main\java\org\cloudbus\cloudsim\examples目录提供了一些CloudSim样例程序,包括8个基础样例程序和多个网络仿真和能耗仿真例子。基础样例模拟的环境如下:1)CloudSimExample1.java:创建一个一台主机、一个任务的数据中心。2)CloudSimExample2.java:创建一个一台主机、两个任务的数据中心。两个任务具有一样的处理能力和执行时间。3)CloudSimExample3.java:创建一个一台主机、两个任务的数据中心。两个任务队处理能力的需求不同,同时根据申请虚拟机的性能不太,所需的执行时间也不同。4)CloudSimExample4.java:创建两个数据中心,每个数据中心一台主机,并在其上运行两个云任务。5)CloudSimExample5.java:创建两个数据中心,每个数据中心一台主机,并在其上运行两个用户的云任务。6)CloudSimExample6.java:创建可扩展的仿真环境。7)CloudSimExample7.java:演示如何停止仿真。8)CloudSimExample8.java:演示如何在运行时添加实体。网络仿真的例子通过读取文件构建网络拓扑,网络拓扑包括节点距离、边时延等信息。能耗仿真的例子通过读取负载文件中的CPU利用率数据作为云任务的利用率,实现云任务负载的动态变化。例子通过动态迁移负载过高的主机中的虚拟机到负载低的主机,实现了负载动态适应的算法,并且应用能耗-CPU利用率模型计算数据中心消耗的能耗。运行步骤需要安装JDK及IDEA集成开发环境。Java版本要达到1.6或更高,CloudSim和旧版本的Java不兼容,如果安装非Sun公司的Java版本,比如GCJ或J++,也可能不兼容。本书使用JDK1.8.0_333和IDEA2020.2.3。为了方便查看和修改代码,通常选择在IDEA中执行,操作步骤如下。1)启动IDEA主程序,在IDEA主界面上选择OpenorImport命令(如图所示),导入一个项目。运行步骤2)根据CloudSim5.0解压到磁盘的路径,选择cloudsim-5.0目录,注意要选择第一个带黑点的文件夹,然后单击OK按钮,如下图所示。3)需要等待几分钟,直至所有文件导入完毕,如下图所示。运行步骤4)可以选择org.cloudbus.cloudsim.examples下的例子运行,这里运行CloudSimExample1。如左图所示,运行结果如右图所示。提纲5.1CloudSim体系结构和API介绍5.2CloudSim环境搭建和使用方法5.3CloudSim扩展编程5.4CloudSim的编程实践5.5OpenStack编程实践CloudSim扩展编程CloudSim是开源的,可以运行在Windows和Linux操作系统上,为用户提供了一系列可扩展的实体和方法,通过扩展这些接口实现用户自己的调度或分配策略,进行相关的性能测试。本书仅以任务调度策略为例。如DatacenterBroker类中提供的方法bindCloudletToVM(intcloudletId,intvmId),实现了将一个任务绑定到指定的虚拟机上运行。用户可以对该类进行扩展,实现自定义调度策略,下面将介绍两种调度策略:顺序分配策略贪心策略顺序分配策略新写一个方法bindCloudletsToVmsSimple(),用于把一组任务顺序分配给一组虚拟机,当所有的虚拟机都运行有任务后,再从第一个虚拟机开始从头分配任务。publicvoidbindCloudletsToVmsSimple(){intvmNum=vmList.size();intcloudletNum=cloudletList.size();intidx=0;for(inti=0;i<cloudletNum;i++){ //将任务绑定到指定id的虚拟机 cloudletList.get(i).setVmId(vmList.get(idx).getId()); idx=(idx+1)%vmNum; //循环遍历虚拟机}}贪心策略实际上,任务之间和虚拟机之间的配置(参数)都不可能完全一样。顺序分配策略实现简单,但是忽略了它们之间的差异因素,如任务的指令长度(MI)和虚拟机的执行速度(MIPS)等。这里为DatacenterBroker类再写一个新方法bindCloudletsToVmsTimeAwared(),该方法采用贪心策略,希望让所有任务的完成时间接近最短,并只考虑MI和MIPS两个参数的区别。通过分析CloudSim自带的样例程序,一个任务所需的执行时间等于任务的指令长度除以运行该任务的虚拟机的执行速度。读者也可以扩展相应的类,实现带宽、数据传输等对任务执行时间的影响。为了便于理解,不改变CloudSim当前的计算方式,即任务的执行时间只与MI和MIPS有关,在这个前提下,可以得出以下结论。(1)如果一个虚拟机上同时运行多个任务,不论使用空间共享还是时间共享,这些任务的总完成时间是一定的,因为任务的总指令长度和虚拟机的执行速度是一定的。(2)如果一个任务在某个虚拟机上的执行时间最短,那么它在其他虚拟机上的执行时间也是最短的。(3)如果一个虚拟机的执行速度最快,那么它不论执行哪个任务都比其他的虚拟机要快。定义一个矩阵time[i][j],表示任务i在虚拟机j所需的执行时间,显然time[i][j]=MI[i]/MIPS[j]。在初始化矩阵time前,首先将任务按MI的大小降序排序,将虚拟机按MIPS的大小升序排列,注意重新排序后矩阵time的行号和任务id不再一一对应,列号和虚拟机id的对应关系,也相应改变。初始化后,矩阵time的每一行、每一列的元素值都是降序排列的,然后再对time做贪心。选用的贪心策略是:从矩阵中行号为0的任务开始,每次都尝试分配给最后一列对应的虚拟机,如果该选择相对于其他选择是最优的,就完成分配,否则将任务分配给运行任务最少的虚拟机,实现一种简单的负载均衡。这种方式反映了越复杂的任务需要更快的虚拟机来处理,以解决复杂任务造成的瓶颈,降低所有任务的总执行时间。bindCloudletsToVmsTimeAwared(),该方法采用贪心策略,希望让所有任务的完成时间接近最短,并只考虑MI和MIPS两个参数的区别。贪心策略publicvoidbindCloudletsToVmsTimeAwared(){intcloudletNum=cloudletList.size();intvmNum=vmList.size();double[][]time=newdouble[cloudletNum][vmNum];//重新排列任务和虚拟机,需要导入包java.util.CollectionsCollections.sort(cloudletList,newCloudletComparator());

Collections.sort(vmList,newVmComparator());

//初始化矩阵time

for(inti=0;i<cloudletNum;i++){for(intj=0;j<vmNum;j++){time[i][j]=

(double)cloudletList.get(i).getCloudletLength()/vmList.get(j).getMips();}}double[]vmLoad=newdouble[vmNum]; //某个虚拟机上任务的总执行时间int[]vmTasks=newint[vmNum]; //某个虚拟机上运行的任务数doubleminLoad=0; //记录当前任务分配方式的最优值intidx=0; //记录当前任务最优分配方式对应的虚拟机列号//将行号为0的任务直接分配给列号最大的虚拟机vmLoad[vmNum-1]=time[0][vmNum-1];vmTasks[vmNum-1]=1;cloudletList.get(0).setVmId(vmList.get(vmNum-1).getId());for(inti=1;i<cloudletNum;i++){minLoad=vmLoad[vmNum-1]+time[i][vmNum-1];idx=vmNum-1;for(intj=vmNum-2;j>=0;j--){//如果当前虚拟机还未分配任务,且其执行当前任务的时间小于等于最小时间贪心策略//分配给该虚拟机是否最优,即可以退出循环if(vmLoad[j]==0){

if(minLoad>=time[i][j]){idx=j;break;}}//如果当前虚拟机分配了任务,且其执行当前任务后的时间小于最小时间if(minLoad>vmLoad[j]+time[i][j]){

minLoad=vmLoad[j]+time[i][j];

idx=j;}elseif(minLoad==vmLoad[j]+time[i][j]&&vmTasks[j]<vmTasks[idx])(

idx=j;}//如果当前虚拟机分配了任务,且其执行当前任务后的时间等于最小时间,且其分配的任务数小于最优分配方式对应的虚拟机}vmLoad[idx]+=time[i][idx];vmTasks[idx]++;cloudletList.get(i).setVmId(vmList.get(idx).getId());}}//根据指令长度降序排列任务,需要导入包java.util.ComparatorprivateclassCloudletComparatorimplementsComparator<Cloudlet>{ publicintcompare(Cloudletcl1,Cloudletcl2){ return(int)(c12.getCloudletLength()-cl1.getCloudletLength());}}//根据执行速度升序排列虚拟机privateclassVmComparatorimplementsComparator<Vm>{ @Override publicintcompare(Vmvm1,Vmvm2){ return(int)(vm1.getMips()-vm2.getMips()); }}仿真步骤仿真步骤如下所示:

(1)初始化CloudSim包(2)创建数据中心 a)创建主机列表。 b)创建PE列表。 c)创建PE并将其添加到上一步创建的PE列表中,可对其ID和MIPS进行设置。 d)创建主机,并将其添加到主机列表中,主机的配置参数有ID、内存、带宽、存储、PE及

虚拟机分配策略(时间或空间共享)。 e)创建数据中心特征对象,用来存储数据中心的属性,包含体系结构、操作系统、机器列表、分配策略(时间、空间共享)、时区以及各项费用(内存、外存、带宽和处理器资源的费用)。 f)最后,创建一个数据中心对象,它的主要参数有名称、特征对象、虚拟机分配策略、用于数据仿真的存储列表以及调度间隔。(3)创建数据中心代理数据中心代理负责在云计算中根据用户的QoS要求协调用户及服务供应商和部署服务任务。(4)创建虚拟机对虚拟机的参数进行设置,主要包括ID、用户ID、MIPS、CPU数量、内存、带宽、外存、虚拟机监控器、调度策略,并提交给任务代理。(5)创建云任务创建指定参数的云任务,设定任务的用户ID,并提交给任务代理。在这一步可以设置需要创建的云任务数量以及任务长度等信息。(6)在这一步调用自定义的任务调度策略,分配任务到虚拟机。(7)启动仿真。(8)在仿真结束后统计结果。详细实现代码下面是贪心策略的仿真核心代码,在org.cloudbus.cloudsim.examples包中新建类ExtendedExample2,实现代码如下(详细请参考5.3.2节代码):运行结果分析由于虚拟机对任务分配使用了空间共享策略,所以运行在同一个虚拟机上的任务,必须按顺序完成。左图为基于贪心策略的仿真结果,图中显示任务7、8被分配到了虚拟机0上运行,从任务开始执行的时间来看,任务8确实是在任务7完成后执行的。图中还显示了所有任务的最终分配结果及运行情况,用户可以据此验证自己的调度策略是否符合要求。右图为基于顺序分配策略的仿真结果,该方法的总执行时间为467.6,而贪心策略只需283.16,节省了约39%的时间。平台重编译实现自定义的调度算法后,用户就可以重新编译并打包CloudSim,来测试或发布自己的新平台。CloudSim平台重编译主要通过Ant工具完成。

从/下载Ant工具,本书使用的版本为1.8.2。将其解压到目录C:\apache-ant-1.8.2。设置环境变量,在Path中加入C:\apache-ant-1.7.1\bin。将命令行切换到扩展的CloudSim路径(build.xml所在目录),在命令行下输入命令C:\cloudsim-3.0.0>ant,批量编译CloudSim源文件,生成的文件会按照bulid.xml的设置存储到指定位置,编译成功后自动打包生成cloudsim-new.jar并存放在C:\cloudsim-3.0.0\jars。扩展的CloudSim平台生成后,在环境变量ClassPath中增加路径:C:\CloudSim\jars\cloudsim-new.jar。然后根据前面介绍的步骤,即可在新的平台下编写自己的仿真验证程序。提纲5.1CloudSim体系结构和API介绍5.2CloudSim环境搭建和使用方法5.3CloudSim扩展编程5.4CloudSim的编程实践5.5OpenStack编程实践CloudSim的编程实践本书中的CloudSim的编程实践主要包括以下三个:CloudSim任务调度编程:主要讲解org.cloudbus.cloudsim.examples包中的CloudSimExample1,CloudSimExample4。CloudSim网络编程:以work.NetworkExample1为例,该例子展示了如何创建一个有网络拓扑的数据中心并且在其上运行一个云任务。CloudSim能耗编程CloudSim的编程实践下面讲解org.cloudbus.cloudsim.examples包中的CloudSimExample1,CloudSimExample4。CloudSimExample1创建了一台主机、一个任务的数据中心,展示了数据中心,代理,主机,虚拟机,云任务等的简单使用以及云仿真基本流程。这是最简单的、最基本的一个程序。通过这一例子可以了解到使用CloudSim仿真的基本步骤,基本类的使用方法。云仿真的基本步骤是:(1)初始化CloudSim包;(2)创建数据中心Datacenter,创建过程创建主机列表List<Host>hostList;(3)创建数据中心代理DatacenterBroker;(4)创建虚拟机Vm;(5)创建云任务Cloudlet;(6)启动仿真;(7)统计结果并输出结果。任务调度编程CloudSimExample1publicclassCloudSimExample1{ privatestaticList<Cloudlet>cloudletList; //任务列表 privatestaticList<Vm>vmlist; //虚拟机列表 publicstaticvoidmain(String[]args){ Log.printLine("StartingCloudSimExample1..."); try{//第一步:初始化CloudSim包,必须在创建实体前调用

intnum_user=1; //用户数 Calendarcalendar=Calendar.getInstance();

booleantrace_flag=false; //表示是否跟踪

CloudSim.init(num_user,calendar,trace_flag);

//第二步:创建数据中心 //数据中心是云资源的提供者,至少需要一个数据中心来模拟云实验。 Datacenterdatacenter0=createDatacenter("Datacenter_0");

//第三步:创建数据中心代理DatacenterBrokerbroker=createBroker();intbrokerId=broker.getId();//第四步:创建虚拟机列表vmlist=newArrayList<Vm>();//设置虚拟机参数intvmid=0; //虚拟机idintmips=1000; //主频(MB)longsize=10000; //硬盘(MB)intram=512; //虚拟机内存(MB)任务调度编程CloudSimExample1 longbw=1000; //带宽(MB) intpesNumber=1; //CPU核数 Stringvmm="Xen"; //VMM名 //创建虚拟机

Vmvm=newVm(vmid,brokerId,mips,pesNumber,ram,bw,size,vmm,newCloudletSchedulerTimeShared()); //云任务调度使用时间共享策略 //添加到虚拟机列表 vmlist.add(vm); //提交虚拟机列表到代理 broker.submitVmList(vmlist); //第五步:创建云任务 cloudletList=newArrayList<Cloudlet>(); //任务参数 intid=0; //任务id longlength=400000; //任务计算量 longfileSize=300; //文件大小,影响传输的带宽花销 longoutputSize=300; //输出文件大小,影响传输的带宽花销 UtilizationModelutilizationModel=newUtilizationModelFull();Cloudletcloudlet=newCloudlet(id,length,pesNumber,fileSize,outputSize,utilizationModel,utilizationModel,utilizationModel);cloudlet.setUserId(brokerId); //设置任务用户Idcloudlet.setVmId(vmid); //设置虚拟机Id//添加任务到任务列表cloudletList.add(cloudlet);任务调度编程CloudSimExample1 //提交任务列表 broker.submitCloudletList(cloudletList); //第六步:启动仿真 CloudSim.startSimulation();

CloudSim.stopSimulation();//第七步:统计结果并输出结果List<Cloudlet>newList=broker.getCloudletReceivedList();printCloudletList(newList);Log.printLine("CloudSimExample1finished!");

}catch(Exceptione){e.printStackTrace();Log.printLine("Unwantederrorshappen");} } privatestaticDatacentercreateDatacenter(Stringname){//创建一个数据中心 //1.创建主机列表 List<Host>hostList=newArrayList<Host>();

//2.创建主机包含的PE或者CPU处理器列表//这个例子中,主机CPU只有一个核芯List<Pe>peList=newArrayList<Pe>(); //Pe是CPU单元intmips=1000; //Pe速率//3.创建核芯并添加到核芯列表peList.add(newPe(0,newPeProvisionerSimple(mips)));任务调度编程CloudSimExample1 //4.创建主机并添加到主机列表 inthostId=0;intram=2048; //内存(MB) longstorage=1000000; //硬盘存储intbw=10000; //带宽hostList.add(newHost(hostId,newRamProvisionerSimple(ram),newBwProvisionerSimple(bw),storage,peList,newVmSchedulerTimeShared(peList) )//虚拟机使用时间共享策略);//5.创建存储数据中心属性的数据中心特征对象Stringarch="x86"; //系统架构Stringos="Linux"; //操作系统Stringvmm="Xen"; //虚拟机监视器doubletime_zone=10.0; //时区doublecost=3.0; //单位时间成本doublecostPerMem=0.05; //单位内存成本doublecostPerStorage=0.001;

//单位存储成本doublecostPerBw=0.0; //单位带宽成本 LinkedList<Storage>storageList=newLinkedList<Storage>();//存储列表DatacenterCharacteristicscharacteristics=new

DatacenterCharacteristics(arch,os,vmm,hostList,time_zone,cost,

costPerMem,costPerStorage,costPerBw);//6.创建数据中心对象Datacenterdatacenter=null;

任务调度编程CloudSimExample1

try{

datacenter=newDatacenter(name,characteristics,new VmAllocationPolicySimple(hostList),storageList,0);

}catch(Exceptione){

e.printStackTrace();

}returndatacenter;} privatestaticDatacenterBrokercreateBroker(){//创建数据中心代理

DatacenterBrokerbroker=null;

try{

broker=newDatacenterBroker("Broker");}catch(Exceptione){

e.printStackTrace();

returnnull; } returnbroker;

} privatestaticvoidprintCloudletList(List<Cloudlet>list){//打印云任务的运行结果

intsize=list.size();Cloudletcloudlet;Stringindent="";Log.printLine();

任务调度编程CloudSimExample1

Log.printLine("==========OUTPUT==========")

Log.printLine("CloudletID"+indent+"STATUS"+indent +"DatacenterID"+indent+"VMID"+indent+"Time"+indent +"StartTime"+indent+"FinishTime");

DecimalFormatdft=newDecimalFormat("###.##"); for(inti=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())); } } }}

任务调度编程CloudSimExample1运行结果如下:任务调度编程CloudSimExample4CloudSimExample4展示了如何创建两个数据中心,每个数据中心有一台主机,并在其上运行两个云任务。代理会自动为虚拟机选择在哪个数据中心的哪个主机上创建的工作。CloudSimExample4.java关键代码(其他部分以省略号省略,详细请参考书5.4.1节代码):publicstaticvoidmain(String[]args){ Log.printLine("StartingCloudSimExample4..."); try{ …… //第二步::创建数据中心 //创建两个数据中心 Datacenterdatacenter0=createDatacenter("Datacenter_0"); Datacenterdatacenter1=createDatacenter("Datacenter_1"); …… //创建两个虚拟机 Vmvm1=newVm(vmid,brokerId,mips,pesNumber,ram,bw,size,vmm,newCloudletSchedulerTimeShared()); vmid++; Vmvm2=newVm(vmid,brokerId,mips,pesNumber,ram,bw,size,vmm,newCloudletSchedulerTimeShared()); //添加虚拟机到虚拟机列表 vmlist.add(vm1); vmlist.add(vm2);……//第五步:创建两个任务 …… Cloudletcloudlet1=newCloudlet(id,length,pesNumber,fileSize,outputSize,utilizationModel,utilizationModel,utilizationModel); cloudlet1.setUserId(brokerId);

任务调度编程CloudSimExample4 id++; Cloudletcloudlet2=newCloudlet(id,length,pesNumber,fileSize,outputSize,utilizationModel,utilizationModel,utilizationModel); cloudlet2.setUserId(brokerId); //添加任务到任务列表 cloudletList.add(cloudlet1); cloudletList.add(cloudlet2); broker.bindCloudletToVm(cloudlet1.getCloudletId(),vm1.getId()); broker.bindCloudletToVm(cloudlet2.getCloudletId(),vm2.getId()); …… //打印每个数据中心的成本 datacenter0.printDebts(); datacenter1.printDebts(); …… } catch(Exceptione){ …… } }任务调度编程CloudSimExample4运行结果如下:值得注意的是,由于数据中心的主机都用了VmSchdeulerSpaceShared策略,见createDatacenter()函数的代码,如下,而主机只有一个CPU核芯,故VM#1创建失败。hostList.add(newHost(hostId,newRamProvisionerSimple(ram), newBwProvisionerSimple(bw),storage,peList, newVmSchedulerSpaceShared(peList) ) );网络编程NetworkExample1

以work.NetworkExample1为例,该例子展示了如何创建一个有网络拓扑的数据中心并且在其上运行一个云任务。例子通过读取topology.brite文件来构造网络拓扑。网络拓扑的信息包括节点的位置,节点间的有向边,边时延,边带宽等信息。能够模拟基于网络位置,时延,带宽等的网络环境,有效地计算网络传输造成的花销。与前面例子不同的是,网络编程需要调用org.cloudbus.cloudsim.NetworkTopology构造网络拓扑图,然后把CloudSim实体与拓扑图的节点进行映射。下图为关键部分代码(详细请参考书5.4.2节代码):网络编程NetworkExample1

程序会寻找标记“Nodes:”和“Edges:”,Nodes是节点信息,其中第一列是节点序号,第二列是节点的横坐标,第三列是节点的纵坐标。Edges是边信息,第一列是边序号,第二列是始节点序号,第三列是终节点序号,第四列是边长度,第五列是边时延,第六列是边带宽。CloudSim中只用到了以上信息。如此,我们就能构造自己需要的网络拓扑了。

运行结果如下(注意:如“7.800000190734863:Broker:TryingtoCreateVM#0inDatacenter_0”中的7.800000190734863是CloudSim中的仿真时间)。CloudSim能耗编程

能耗模拟的例子有很多,代码实现都类似。这些例子通过读取负载文件中的CPU利用率数据作为云任务的利用率,实现云任务负载的动态变化。因此仿真过程中会出现主机的负载不平衡,程序通过动态迁移负载过高的主机中的虚拟机到负载低的主机,实现了负载动态适应的算法,并且应用能耗-CPU利用率模型计算数据中心消耗的能量。事实上,本节介绍的程序不仅适用于能耗编程,其更大的意义在于展示了虚拟机调度算法,可以计算虚拟机的迁移时间、服务等级协议(ServiceLevelAgreement,SLA)的违背率、主机利用率等指标。这样我们就能进行动态的虚拟机调度、任务调度、能耗模拟。

这些例子的差别在于虚拟机分配策略VmAllocationPolicy和虚拟机选择策略VmSelectionPolicy的不同。VmAllocationPolicy的作用是为虚拟机选择要放置的主机,而VmSelectionPolicy的作用是选择由于主机负载过高而要迁移的虚拟机。下面以org.cloudbus.cloudsim.examples.power.planetlab.IqrMc为例进行说明。IqrMc中使用了PowerVmAllocationPolicyMigrationInterQuartileRange的虚拟机分配策略和PowerVmSelectionPolicyMaximumCorrelation的虚拟机选择策略。InterQuartileRange是指四分位数间距,MaximumCorrelation是指最大相关系数。IqrMc.java的代码十分简单,但实际上这个例子比前面的例子复杂得多,因为具体实现的代码在其他类中。CloudSim能耗编程publicstaticvoidmain(String[]args)throwsIOException{ booleanenableOutput=false; booleanoutputToFile=true; StringinputFolder=IqrMc.class.getClassLoader().getResource("workload/planetlab").getPath(); StringoutputFolder="output"; Stringworkload="20110303";//负载数据 StringvmAllocationPolicy="iqr";//四分间距分配策略(InterQuartileRange) StringvmSelectionPolicy="mc";//最大相关系数选择策略(MaximumCorrelation) Stringparameter="1.5";//Iqr策略中的安全参数 newPlanetLabRunner( enableOutput, outputToFile, inputFolder, outputFolder, workload, vmAllocationPolicy, vmSelectionPolicy, parameter); }CloudSim能耗编程如果运行不了,出现错误如下:有可能是因为负载文件workload/planetlab/20110303的绝对路径中有空格,这样它在读取路径时会把空格转义为“%20”,因而读取文件失败。解决方法是:把“StringinputFolder=IqrMc.class.getClassLoader().getResource("workload/planetlab").getPath();”改为“StringinputFolder=IqrMc.class.getClassLoader().getResource("workload/planetlab").toURI().getPath();”,并且在throwsIOException后加上“,URISyntaxException”,即变成“throwsIOException,URISyntaxException”。CloudSim能耗编程PlanetLabRunner的源代码中通过org.cloudbus.cloudsim.examples.power.Helper类和org.cloudbus.cloudsim.examples.power.planetlab.PlanetLabHelper类创建了代理、云任务、虚拟机列表、主机列表。而数据中心是在其父类RunnerAbstract中创建的。publicclassPlanetLabRunnerextendsRunnerAbstract{ publicPlanetLabRunner( booleanenableOutput, booleanoutputToFile, StringinputFolder, StringoutputFolder, Stringworkload, StringvmAllocationPolicy, StringvmSelectionPolicy, Stringparameter){super( enableOutput, outputToFile, inputFolder, outputFolder, workload, vmAllocationPolicy, vmSelectionPolicy, parameter); }

CloudSim能耗编程 @Override protectedvoidinit(StringinputFolder){ try{ CloudSim.init(1,Calendar.getInstance(),false); broker=Helper.createBroker(); //创建代理 intbrokerId=broker.getId(); cloudletList=PlanetLabHelper.createCloudletListPlanetLab(brokerId,inputFolder); //创建云任务,其中云任务的利用率是读取负载文件的vmList=Helper.createVmList(brokerId,cloudletList.size());//创建虚拟机列表 hostList=Helper.createHostList(PlanetLabConstants.NUMBER_OF_HOSTS);//创建能耗主机列表 }catch(Exceptione){ e.printStackTrace(); Log.printLine("Thesimulationhasbeenterminatedduetoanunexpectederror"); System.exit(0); } }}CloudSim能耗编程

org.cloudbus.cloudsim.examples.power.RunnerAbstract的start()方法创建数据中心。并且定义了仿真的启动与结束。RunnerAbstract在其构造函数中会执行init()(由子类PlanetLabRunner具体实现)和start()方法。protectedvoidstart(StringexperimentName,StringoutputFolder,VmAllocationPolicyvmAllocationPolicy){ System.out.println("Starting"+experimentName); try{ PowerDatacenterdatacenter=(PowerDatacenter)Helper.createDatacenter( "Datacenter",PowerDatacenter.class,hostList,vmAllocationPolicy); datacenter.setDisableMigrations(false); broker.submitVmList(vmList); broker.submitCloudletList(cloudletList); CloudSim.terminateSimulation(Constants.SIMULATION_LIMIT); //设置仿真超时时间,超时则结束仿真 doublelastClock=CloudSim.startSimulation(); //仿真总时间 List<Cloudlet>newList=broker.getCloudletReceivedList(); Log.printLine("Received"+newList.size()+"cloudlets"); CloudSim.stopSimulation(); Helper.printResults(datacenter,vmList,lastClock,experimentName, Constants.OUTPUT_CSV,outputFolder); }catch(Exceptione){ e.printStackTrace(); Log.printLine("Thesimulationhasbeenterminatedduetoanunexpectederror"); System.exit(0); } Log.printLine("Finished"+experimentName); }CloudSim能耗编程创建云任务由org.cloudbus.cloudsim.examples.power.planetlab.PlanetLabHelper通过读取CPU利用率数据,构建负载动态变化的云任务。publicstaticList<Cloudlet>createCloudletListPlanetLab(intbrokerId,StringinputFolderName)throwsFileNotFoundException{ List<Cloudlet>list=newArrayList<Cloudlet>(); longfileSize=300; longoutputSize=300; UtilizationModelutilizationModelNull=newUtilizationModelNull(); FileinputFolder=newFile(inputFolderName); File[]files=inputFolder.listFiles(); //列出文件夹中的文件 for(inti=0;i<files.length;i++){ //1052个文件,1052个任务 Cloudletcloudlet=null; try{

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论