CloudSim 有什么众辨?
- 對(duì)各種組件進(jìn)行模擬
(1)云數(shù)據(jù)中心(Datacenter)
(2)物理機(jī)(Host)
(3)虛擬機(jī)(VM)
(4)服務(wù)代理商(DatacenterBroker)
(5)任務(wù)單元(Cloudlet)
(6)云信息服務(wù)(CIS)
- 對(duì)各種行為進(jìn)行模擬
(1)創(chuàng)建VM( VM_CREATE )
(2)刪除VM的數(shù)據(jù)( VM_DATA_DEL )
(3)遷移VM(VM_MIGRATE )
(4)任務(wù)提交( CLOUDLET_SUMIT )
(5)任務(wù)取消( CLOUDLET_CANCEL )
- 資源分配進(jìn)行模擬
(1)虛擬機(jī)的主機(jī)分配( VmAllocationPolicy )
(2)帶寬分配( BwProvisioner )
(3)內(nèi)存資源分配( RamProvisioner )
(4)總線時(shí)間分配( PeProvisioner )
繼承這些類可以實(shí)現(xiàn)自己的分配策略
組件類
實(shí)體 SimEntity
public abstract class SimEntity{
private String name;
private int id;
private SimEvent evbuf;
private int state;
...
public abstract void processEvent(SimEvent ev);
...
}
Datacenter 模擬
public class Datacenter extends SimEntity {
private DatacenterCharacteristics characteristics;
private String regionalCisName;
private VmAllocationPolicy vmAllocationPolicy;
private List<? extends Vm> vmList;
@Override
public void processEvent(SimEvent ev) {
.....
}
}
DatacenterCharacteristics 模擬
public class DatacenterCharacteristics {
private int id;
private String architecture;
private String os;
private List<? extends Host> hostList;
private double costPerSecond;
private String vmm;
private double costPerMem;
private double costPerStorage;
private double costPerBw;
......
}
Host 對(duì)主機(jī)的模擬
public class Host {
private int id;
private long storage;
private List<? extends Pe> peList;
private RamProvisioner ramProvisioner;
private BwProvisioner bwProvisioner;
private VmScheduler vmScheduler;
private List<? extends Vm> vmList;
private List<? extends Pe> peList;
public boolean vmCreate(Vm vm) {
getVmList().add(vm);
vm.setHost(this);
return true;
}
}
CIS 注冊(cè)機(jī)的模擬
public class CloudInformationService extends SimEntity {
private final List<Integer> resList;
private final List<Integer> arList;
@Override
public void processEvent(SimEvent ev) {
int id = -1; // requester id
switch ( ev.getTag() ) {
case CloudSimTags.REGISTER_RESOURCE:
resList.add( (Integer) );break;
case CloudSimTags.REGISTER_RESOURCE_AR:
resList.add( (Integer) ev.getData() );
arList.add( (Integer) ev.getData() ); break;
case CloudSimTags.RESOURCE_LIST:
id = ( (Integer) ev.getData() ).intValue();
super.send(id, 0L, ev.getTag(), resList); break;
}
}
Broker
屏蔽了云數(shù)據(jù)中心的內(nèi)部操作
如虛擬機(jī)的創(chuàng)建、管理
任務(wù)單元在虛擬機(jī)上的分配
用戶只需要提交自己的服務(wù)請(qǐng)求即可
它定義了一組操作肤粱,用于和用戶與數(shù)據(jù)中心的交互
event 事件
private final double time;
private double endWaitingTime;
private int entSrc;
private int entDst;
private final int tag;
private final Object data;
對(duì)云行為進(jìn)行模擬event,
用戶在編程接口向broker提交了創(chuàng)建vm的請(qǐng)求火的,就會(huì)觸發(fā)broker的一個(gè)方法
protected void createVmsInDatacenter(int datacenterId){
...
sendNow(datacenterId, CloudSimTags.VM_CREATE_ACK, vm);
...
}
public void processEvent(SimEvent ev) {
....
switch (ev.getTag()) {
...
case CloudSimTags.VM_CREATE_ACK:
processVmCreate(ev, true);
break;
...
}
}
對(duì)分配策略的模擬
處理單元分配( VmAllocationPolicy )
帶寬分配( BwProvisioner )
內(nèi)存資源分配( RamProvisioner )
總線時(shí)間分配( PeProvisioner )
public abstract boolean allocateHostForVm(Vm vm);
這個(gè)策略尋找能滿足 Vm 需求的Host,然后把Vm創(chuàng)建到這個(gè)Host上坦报。
自帶的策略分析VmAllocationPolicySimple
public boolean allocateHostForVm(Vm vm) {
...
moreFree = Integer.MIN_VALUE;
for (int i=0; i < freePesTmp.size(); i++) {
if (freePesTmp.get(i) > moreFree) {
moreFree = freePesTmp.get(i);
idx = i;
}
}
Host host = getHostList().get(idx);
result = host.vmCreate(vm);
...
用戶自行開發(fā)的調(diào)度算法可在 DataCenterBroker 的方法中實(shí)現(xiàn)上煤,從而實(shí)現(xiàn)調(diào)度算法的模擬休玩。
CloudSim 仿真步驟
- 初始化CloudSim 庫
CloudSim.init(num_user, calendar, trace_flag);
- 創(chuàng)建數(shù)據(jù)中心,在CloudSim平臺(tái)中,一個(gè)數(shù)據(jù)中心由一個(gè)或者多個(gè)Machine組成拴疤,一個(gè)Machine 是由一個(gè)或多個(gè) PEs 或 CPUs 組成永部。
Datacenter datacenter0 = createDatacenter("Datacenter_0");
- 創(chuàng)建代理 Broker
DatacenterBroker broker = createBroker();
int int int int brokerId = broker.getId();
- 創(chuàng)建虛擬機(jī)
vmlist = new new new new ArrayList<Vm>();
//VM 描述參數(shù)
int int int vmid = 0;
int int int int mips = 250;
long long long long size = 10000;
int int int int ram = 512;
long long long long bw = 1000;
int int int int pesNumber = 1;
String vmm = "Xen";
//創(chuàng)建時(shí)為虛擬機(jī)指定 Broker
Vm vm1 = new new new new Vm(vmid, brokerId, mips, pesNumber, ram, bw, size,
vmm, new new new new CloudletSchedulerTimeShared());
//將虛擬機(jī)加入虛擬機(jī)列表
vmlist.add(vm1);
//向相應(yīng)代理 Broker 提交虛擬機(jī)列表
broker.submitVmList(vmlist);
- 創(chuàng)建云任務(wù)
cloudletList = new new new new ArrayList<Cloudlet>();
//創(chuàng)建時(shí)指定任務(wù)的用戶 ID,BrokerID
//Cloudlet 描述參數(shù)
int int int int id = 0;
pesNumber=1;
long long long long length = 250000;
long long long long fileSize = 300;
long long long long outputSize = 300;
UtilizationModel utilizationModel =new new new new
UtilizationModelFull();
Cloudlet cloudlet1 = new new new new Cloudlet(id, length, pesNumber,
fileSize, outputSize, utilizationModel, utilizationModel,
utilizationModel);
cloudlet1.setUserId(brokerId); ……
//將任務(wù)加入任務(wù)列表
cloudletList.add(cloudlet1); ……
//向代理Broker提交任務(wù)列表
broker.submitCloudletList(cloudletList);
- 啟動(dòng)仿真
CloudSim.startSimulation();
7 輸出結(jié)果
List<Cloudlet> newList = broker.getCloudletReceivedList();
CloudSim.stopSimulation();
printCloudletList(newList);
datacenter0.printDebts();
默認(rèn)的調(diào)度策略
默認(rèn)的調(diào)度策略有兩個(gè) :
- 獨(dú)占的調(diào)度策略: 云任務(wù)或者虛擬機(jī)要求處理單元獨(dú)自占用, 如果比處理單元多的任務(wù)將會(huì)進(jìn)入等待隊(duì)列,直到資源可用呐矾。
- 時(shí)間分片策略: 處理單元共享的方式創(chuàng)建方法扬舒, 在相關(guān)對(duì)象的構(gòu)造函數(shù)期間傳遞新類
虛擬機(jī)分配策略在這個(gè)類中:
在數(shù)據(jù)中心中主機(jī)提供給一個(gè)虛擬機(jī)是一個(gè)簡(jiǎn)單的策略,即運(yùn)行最少虛擬機(jī)的主機(jī)接收下一個(gè)虛擬機(jī)凫佛。這個(gè)行為定義在VMAllocationPolicySimple類中。
DatacenterBroker—修改虛擬機(jī)提供請(qǐng)求被提交到數(shù)據(jù)中心的方式和云任務(wù)被提交和被分配給虛擬機(jī)的方式孕惜。
2) VmAllocationPolicy—你需要去擴(kuò)展這個(gè)抽象類去實(shí)現(xiàn)你自己的算法愧薛,為了確定哪一個(gè)主機(jī)分配給一個(gè)新的虛擬機(jī)。你也可以實(shí)現(xiàn)一個(gè)動(dòng)態(tài)虛擬機(jī)再分配算法通過實(shí)現(xiàn)optimizeAllocation方法衫画,它每一次構(gòu)件時(shí)被調(diào)用和在這個(gè)數(shù)據(jù)中心的當(dāng)前虛擬機(jī)所有集被傳送毫炉。
3) VmScheduler—在一個(gè)單獨(dú)主機(jī)上實(shí)現(xiàn)資源分配給虛擬機(jī)算法。
4) CloudletScheduler—在一個(gè)單獨(dú)的虛擬機(jī)實(shí)現(xiàn)調(diào)度云任務(wù)的算法削罩。
5) PowerVmAllocationPolicyMigrationAbstract—一個(gè)模板類為了實(shí)現(xiàn)功率監(jiān)控動(dòng)態(tài)虛擬機(jī)整合算法瞄勾,用于虛擬機(jī)在線遷移到動(dòng)態(tài)再分配虛擬機(jī)在每次構(gòu)件時(shí)。重寫的主要方法是optimizeAllocation弥激。
CloudSim 里面任務(wù)的執(zhí)行時(shí)間等于任務(wù)的指令長度(MI) 除以運(yùn)行該任務(wù)的虛擬機(jī)的執(zhí)行速度(MIPS), 即 T = MI/ MIPS
a进陡、如果一個(gè)虛擬機(jī)上同時(shí)運(yùn)行多個(gè)任務(wù),不論使用空間共享還是時(shí)間共享微服,
這些任務(wù)的執(zhí)行時(shí)間是一定的趾疚。(任務(wù)的總指令長度和虛擬機(jī)的執(zhí)行速度是一定
的)。
b以蕴、如果一個(gè)任務(wù)在某個(gè)虛擬機(jī)上執(zhí)行的時(shí)間最短糙麦,那么它在其他虛擬機(jī)上
的執(zhí)行時(shí)間也是最短的。
c丛肮、如果一個(gè)虛擬機(jī)的執(zhí)行速度最快赡磅,那么它不論執(zhí)行哪個(gè)任務(wù)都是最快的。
任務(wù)到虛擬機(jī)的分配策略
- 順序分配策略
在DatacenterBroker類中實(shí)現(xiàn)方法 bindCloudletsToVmsSimples(); 用于把一組任務(wù)按順序分配給一組虛擬機(jī)宝与,當(dāng)所有的虛擬機(jī)都有運(yùn)行任務(wù)后焚廊,再從第一個(gè)虛擬機(jī)從頭分配任務(wù)。
- 貪心策略
在DatacenterBroker類中實(shí)現(xiàn)bindCloudletsToVmsTimeAwared();
定義一個(gè)矩陣 time[i][j],表示任務(wù) i 在虛擬機(jī) j 上所需的執(zhí)行時(shí)間伴鳖。在初始化
矩陣 time 前,首先將任務(wù)按 MI 的大小降序排序,將虛擬機(jī)按 MIPS 的大小升序
排列节值。
從矩陣中行號(hào)為 0 的任務(wù)開始,每次都嘗試分配給最后一列對(duì)應(yīng)的虛擬機(jī),
如果該選擇相對(duì)于其他選擇是最優(yōu)的,就完成分配,否則將任務(wù)分配給使當(dāng)前結(jié)
果最優(yōu)的虛擬機(jī)。同時(shí),如果有多種分配方法都能使當(dāng)前結(jié)果最優(yōu),則將任務(wù)分
配給運(yùn)行任務(wù)最少的虛擬機(jī)榜聂。
// 順序分配
public void bindCloudletsToVmsSimple(){
int vmNum = vmList.size();
int cloudletNum = cloudletList.size();
int idx = 0;
for (int i=0;i<cloudletNum;i++){
cloudletList.get(i).setVmId(vmList.get(idx).getId());
idx = (idx+1)%vmNum;
}
}
// 貪心分配
public void bindCloudletsToVmsTimeAwared(){
int cloudletNum=cloudletList.size();
int vmNum=vmList.size();
//time[i][j] 表示任務(wù)i在虛擬機(jī)j上的執(zhí)行時(shí)間
double[][] time=new double[cloudletNum][vmNum];
//cloudletList按MI降序排列, vm按MIPS升序排列
Collections. sort (cloudletList, new CloudletComparator());
Collections. sort (vmList,new VmComparator());
//////////For test//////////////////////////////////
System. out .println("http:///////////For test///////////////");
for(int i=0;i<cloudletNum;i++){
System. out .print(cloudletList.get(i).getCloudletId()+":"+cloudletList.get
(i).getCloudletLength()+" ");
}
System. out .println();
for (int i=0;i< vmNum;i++){
System. out .print(vmList.get(i).getId()+":"+vmList.get(i).getMips()+" ");
}
System. out .println();
System. out .println("http://////////////////////////////////");
//////////////////////////////////////////////////////////////////////
for (int i=0;i<cloudletNum;i++){
for(int j=0;j<vmNum;j++){
time[i][j]= (double)cloudletList.get(i).getCloudletLength()/vmList.get(j).getMips();
System. out .print("time["+i+"]["+j+"]="+time[i][j]);
}
System. out .println();
//For test
}
double[] vmLoad=new double[vmNum];//在某個(gè)虛擬機(jī)上任務(wù)的總執(zhí)行時(shí)間
int[] vmTasks=new int[vmNum]; //在某個(gè)Vm上運(yùn)行的任務(wù)數(shù)量
double minLoad=0;//記錄當(dāng)前任務(wù)分配方式的最優(yōu)值
int idx=0;//記錄當(dāng)前任務(wù)最優(yōu)分配方式對(duì)應(yīng)的虛擬機(jī)列號(hào)
//第一個(gè)cloudlet分配給最快的vm
vmLoad[vmNum-1]=time[0][vmNum-1];
vmTasks[vmNum-1]=1;
cloudletList.get(0).setVmId(vmList.get(vmNum-1).getId());
for(int i=1;i<cloudletNum;i++){
minLoad=vmLoad[vmNum-1]+time[i][vmNum-1];
idx=vmNum-1;
for(int j=vmNum-2;j>=0;j--){
//如果當(dāng)前虛擬機(jī)未分配任務(wù),則比較完當(dāng)前任務(wù)分配給該虛擬機(jī)是否最優(yōu)
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;
}
//簡(jiǎn)單的負(fù)載均衡
else if(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());
System. out .print(i+"th "+"vmLoad["+idx+"]="+vmLoad[idx]+"minLoad="+minLoad);
System. out .println();
}
}
//Cloudlet根據(jù)MI降序排列
private class CloudletComparator implements Comparator<Cloudlet>{
@Override
public int compare(Cloudlet cl1, Cloudlet cl2){
return (int)(cl2.getCloudletLength()-cl1.getCloudletLength());
}
}
//Vm根據(jù)MIPS升序排列
private class VmComparator implements Comparator<Vm>{
@Override
public int compare(Vm vm1, Vm vm2){
return (int)(vm1.getMips()-vm2.getMips());
}
}
如果只是提交了任務(wù)列表和Vm列表搞疗,并未將任務(wù)分配給指定的虛擬機(jī),那么Datacenterbroker將會(huì), 檢測(cè)當(dāng)前有未使用的虛擬機(jī)匿乃,檢測(cè)有未分配的任務(wù)桩皿,使用順序的輪轉(zhuǎn)法進(jìn)行分配
具體可以看在Broker中源碼:
protected void submitCloudlets() {
int vmIndex = 0;
List<Cloudlet> successfullySubmitted = new ArrayList<Cloudlet>();
for (Cloudlet cloudlet : getCloudletList()) {
Vm vm;
// if user didn't bind this cloudlet and it has not been executed yet
if (cloudlet.getVmId() == -1) {
vm = getVmsCreatedList().get(vmIndex);
} else { // submit to the specific vm
vm = VmList.getById(getVmsCreatedList(), cloudlet.getVmId());
if (vm == null) { // vm was not created
if(!Log.isDisabled()) {
Log.printConcatLine(CloudSim.clock(), ": ", getName(), ": Postponing execution of cloudlet ",
cloudlet.getCloudletId(), ": bount VM not available");
}
continue;
}
}
if (!Log.isDisabled()) {
Log.printConcatLine(CloudSim.clock(), ": ", getName(), ": Sending cloudlet ",
cloudlet.getCloudletId(), " to VM #", vm.getId());
}
cloudlet.setVmId(vm.getId());
sendNow(getVmsToDatacentersMap().get(vm.getId()), CloudSimTags.CLOUDLET_SUBMIT, cloudlet);
cloudletsSubmitted++;
vmIndex = (vmIndex + 1) % getVmsCreatedList().size();
getCloudletSubmittedList().add(cloudlet);
successfullySubmitted.add(cloudlet);
}
// remove submitted cloudlets from waiting list
getCloudletList().removeAll(successfullySubmitted);
}