上一篇文章<http://blog.youkuaiyun.com/wingter92/article/details/75003916>说到了CloudSim模拟流程的整体事件流,其中最为复杂和关键的自然是Cloudlet被提交到DC(DC对象开始process相关事件)之后的流程,本文就该流程在代码方面作简要分析。
由CLOUDLET_SUBMIT事件被DataCenter对象处理开始说起(没记错的话是DC完成VM创建并回复VM_CREATE_ACK类型事件之后,DCBroker随即向DC发送CLOUDLET_SUBMIT事件)。
下面列出的都是流程中关键函数:
*Note: 下文中DC代表DataCenter对象,tags.xxx代表xxx类型的事件,非关键参数省略,“=>”代表调用
DC.processEvent(tags.CLOUDLET_SUBMIT)
=> DC.processCloudletSubmit(event, ack) // 处理提交的该任务,逻辑是先更新DC中现有所有主机状态(有完成的有发事件),然后处理提交上来的这个cloudlet(封装在event里),从VmAllocationPolicy处getHost()获得分配的主机、VM,计算estimatedFinishTime,最后发送事件给自己:send(DC.id, estimatedFinishTime, VM_DC_EVENT);
=> DC.updateCloudletProcessing() // 该函数执行完后,DC中现有所有host上的所有VM的执行进度完成更新,取状态更新最早的host的更新时刻为smallertime,即下一事件或言模拟时刻 ,最后以该时刻调用DC.schedule(DC.id, delay=smallertime-current ,tags.VM_DC_EVENT)向自身发送事件VM_DC_EVENT;
for each host => host.updateVmsProcessing(clock()) //传入当前clock时刻,更新每个host执行进度,函数返回的是host上最早完成的那个VM的完成时间;
for each VM => vm.updateVmProcessing(clock, mips) // 传入当前clock时刻,更新每个VM执行进度,返回VM上最早完成的cloudlet的完成时间;
=> CloudletScheduler.updateVmProcessing(clock,mips)// 此处以timeShared型VM内任务调度(平分mips)的policy类实现为例
{
// 一个VM中可以有多个cloudlet在执行
timespan = now - previous;
for each cloudlet 调用ResCloudlet.updateCloudletFinishedSoFar( mips*timespan*#pe ) // 执行中的Cloudlet被封装为ResCloudlet,该函数更新其执行进度
for each cloudlet 计算remainingLength, 若remainingLength == 0, 调用CloudletScheduler.cloudletFinish(rescloud),然后remove掉该Cloudlet
for each cloudlet 再计算EstimatedFinishTime = remainingLength / (mips*#pe);
比较提交给该VM的所有cloudlet的EstimatedFinishTime,取最小,赋值给nextEvent作为VM下次状态改变的模拟时刻;
return nextEvent; // 返回下次状态改变的时刻,以推进时间轴
}
我现在想在CloudSim基础上扩展,开发出主机监控模块,本次代码流程分析给我的启发是:
1、可以在host.updateVmsProcessing(clock())被调用时,增加数据采集逻辑,实现非连续的主机性能、功耗数据采集;
2、事件的产生(即插入future的顺序)不是严格按时间轴的,for instance,新提交的cloudlet可能比原本在执行的cloudlet更快完成。通过查看future队列,发现其底层实现是sortedSet,而SimEvent的compareTo()显示是future是按event.time的升序排列。这说明我可能可以用某种方式直接向future中插入连续的自定义事件,该事件由我设计的PowerCollector类处理以实现采集逻辑。