经历过才能真的感受,做一个靠谱的人!
分类: 云计算
2013-09-24 16:04:28
CloudSim源码分析之DatacenterBroker--processEvent()(一)
每个CloudSim实体都继承并实现了SimEntity类的processEvent()方法,用来处理与其自身逻辑相关的事件,比如与DatacenterBroker相关的事件有:请求数据中心特征事件,虚拟机创建情况反馈事件,任务完成返回事件,仿真结束事件等。
CloudSim的事件都是在系统运行过程中不断产生的,并添加到等待队列,每个时钟要处理的事件会从等待队列(future)添加到延时队列中(deferred),在上一篇博文中详细分了runClockTick()方法,该方法实现在一个时钟心跳内处理在延时队列和等待队列中的事件,将队列中事件与相应的实体关联起来,利用该实体的processEvent()方法具体的处理事件。
DatacenterBroker是CloudSim中一个核心实体,它也有自己的事件处理方法,下面将详细分析其processEvent():
点击(此处)折叠或打开
1、processResourceCharacteristicsRequest(SimEvent ev)分析
点击(此处)折叠或打开
2、processResourceCharacteristics(ev)分析
- // 处理数据中心特征请求事件
- protected void processResourceCharacteristicsRequest(SimEvent ev) {
- // 这是数据中心ID列表,实际每个数据中心ID对应该数据中心的所有物理机列表
- setDatacenterIdsList(CloudSim.getCloudResourceList());
- // 初始化数据中心特征列表
- setDatacenterCharacteristicsList(new HashMap<Integer, DatacenterCharacteristics>());
- Log.printLine(CloudSim.clock() + ": " + getName() + ": Cloud Resource List received with "
- + getDatacenterIdsList().size() + " resource(s)");
- // 向每个数据中心发送特征请求,创建数据中心特征事件
- for (Integer datacenterId : getDatacenterIdsList()) {
- sendNow(datacenterId, CloudSimTags.RESOURCE_CHARACTERISTICS, getId());
- }
- }
点击(此处)折叠或打开
- // 处理数据中心返回的数据中心特征
- protected void processResourceCharacteristics(SimEvent ev) {
- // 获取数据中心返回的数据中心特征
- DatacenterCharacteristics characteristics = (DatacenterCharacteristics) ev.getData();
- // 添加数据中心特征ID与数据中心特征的映射
- getDatacenterCharacteristicsList().put(characteristics.getId(), characteristics);
- // DatacenterBroker获取了所有数据中心的特征
- if (getDatacenterCharacteristicsList().size() == getDatacenterIdsList().size()) {
- setDatacenterRequestedIdsList(new ArrayList<Integer>());
- // DatacenterBroker了解到所有数据中心后,开始向数据中心创建虚拟机
- createVmsInDatacenter(getDatacenterIdsList().get(0));
- }
- }
DatacenterBroker获取了所有数据中心特征,开始在数据中心创建虚拟机:
3、processVmCreate(ev)分析点击(此处)折叠或打开
- // 在数据中心上创建虚拟机
- protected void createVmsInDatacenter(int datacenterId) {
- // send as much vms as possible for this datacenter before trying the next one
- // 尽量在一个数据中心上创建更多的虚拟机
- int requestedVms = 0;
- String datacenterName = CloudSim.getEntityName(datacenterId);
- for (Vm vm : getVmList()) {
- if (!getVmsToDatacentersMap().containsKey(vm.getId())) {
- Log.printLine(CloudSim.clock() + ": " + getName() + ": Trying to Create VM #" + vm.getId()
- + " in " + datacenterName);
- // 向该数据中心发送虚拟机创建请求事件,等待该数据中心处理该事件
- sendNow(datacenterId, CloudSimTags.VM_CREATE_ACK, vm);
- requestedVms++;// 向某数据中心请求创建虚拟机的次数
- }
- }
- // 将该数据中心ID添加到数据中心请求列表
- getDatacenterRequestedIdsList().add(datacenterId);
- setVmsRequested(requestedVms);// 设置请求次数
- setVmsAcks(0);// 设置应答次数
- }
点击(此处)折叠或打开
- // 只是返回对虚拟机创建请求的一个响应,虚拟机的实际创建在这之前就完成了。
- protected void processVmCreate(SimEvent ev) {
- int[] data = (int[]) ev.getData();
- int datacenterId = data[0];
- int vmId = data[1];
- int result = data[2];
- if (result == CloudSimTags.TRUE) {
- // 添加虚拟机ID与数据中心ID的映射
- getVmsToDatacentersMap().put(vmId, datacenterId);
- // 将创建的虚拟机从vmList添加到vmCreatedList(vmList保存待创建的vm列表)
- getVmsCreatedList().add(VmList.getById(getVmList(), vmId));
- Log.printLine(CloudSim.clock() + ": " + getName() + ": VM #" + vmId
- + " has been created in Datacenter #" + datacenterId + ", Host #"
- + VmList.getById(getVmsCreatedList(), vmId).getHost().getId());
- } else {
- Log.printLine(CloudSim.clock() + ": " + getName() + ": Creation of VM #" + vmId
- + " failed in Datacenter #" + datacenterId);
- }
- incrementVmsAcks(); // 增加创建vm应答的次数
- // all the requested VMs have been created
- // 所有待创建的虚拟机都创建完毕
- if (getVmsCreatedList().size() == getVmList().size() - getVmsDestroyed()) {
- submitCloudlets(); // 提交用户任务至特定虚拟机
- } else {
- // all the acks received, but some VMs were not created
- // 所有的ack都收到了,但是有些vm未被创建
- if (getVmsRequested() == getVmsAcks()) {
- // find id of the next datacenter that has not been tried
- // 尝试在其他数据中心上创建虚拟机
- for (int nextDatacenterId : getDatacenterIdsList()) {
- if (!getDatacenterRequestedIdsList().contains(nextDatacenterId)) {
- createVmsInDatacenter(nextDatacenterId);
- return;
- }
- }
- // all datacenters already queried
- if (getVmsCreatedList().size() > 0) { // if some vm were created
- submitCloudlets(); // 提交用户任务至特定虚拟机
- } else { // no vms created. abort
- Log.printLine(CloudSim.clock() + ": " + getName()
- + ": none of the required VMs could be created. Aborting");
- finishExecution(); // 结束仿真
- }
- }
- }
- }
所有虚拟机创建成功后,向虚拟机分配云任务
点击(此处)折叠或打开
- // 将任务列表中的所有任务,分别提交给虚拟机
- protected void submitCloudlets() {
- int vmIndex = 0;
- for (Cloudlet cloudlet : getCloudletList()) {
- Vm vm;
- // if user didn't bind this cloudlet and it has not been executed yet
- // 如果该云任务还没有绑定虚拟机
- if (cloudlet.getVmId() == -1) {
- // 直接从已创建的虚拟机中从索引0开始找一台虚拟机,可是这台虚拟机(资源利用率、性能下降)可用吗?
- vm = getVmsCreatedList().get(vmIndex);
- } else { // submit to the specific vm // 该任务之前已经指定了虚拟
- vm = VmList.getById(getVmsCreatedList(), cloudlet.getVmId());
- if (vm == null) { // vm was not created // 指定的虚拟机创建失败,重新分配
- Log.printLine( CloudSim.clock() + ": " + getName() + ": Postponing execution of cloudlet "
- + cloudlet.getCloudletId() + ": bount VM not available");
- continue;
- }
- }
- Log.printLine(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(); // vmIndex加1,多于vm数时,再从第一台vm开始
- // 将该任务添加到已任务已提交列表
- getCloudletSubmittedList().add(cloudlet);
- }
- // remove submitted cloudlets from waiting list
- // 将已经提交的任务从cloudletList中移除
- for (Cloudlet cloudlet : getCloudletSubmittedList()) {
- getCloudletList().remove(cloudlet);
- }
- }
4、processCloudletReturn(ev)分析
点击(此处)折叠或打开
- // 处理任务完成返回事件
- protected void processCloudletReturn(SimEvent ev) {
- // 获取该执行完成的用户任务
- Cloudlet cloudlet = (Cloudlet) ev.getData();
- // 将该任务添加到已完成任务列表
- getCloudletReceivedList().add(cloudlet);
- Log.printLine(CloudSim.clock() + ": " + getName() + ": Cloudlet " + cloudlet.getCloudletId()
- + " received");
- cloudletsSubmitted--; // 任务提交数减一
- // 满足下面条件,说明所有用户任务都执行完毕
- if (getCloudletList().size() == 0 && cloudletsSubmitted == 0) { // all cloudlets executed
- Log.printLine(CloudSim.clock() + ": " + getName() + ": All Cloudlets executed. Finishing...");
- clearDatacenters(); // 清理数据中心
- finishExecution(); // 仿真结束
- } else { // some cloudlets haven't finished yet // 有些任务还没有执行结束
- // 所有任务都已经提交,但是有些任务阻塞了,可能是在等待虚拟机的创建
- if (getCloudletList().size() > 0 && cloudletsSubmitted == 0) {
- // all the cloudlets sent finished. It means that some bount
- // cloudlet is waiting its VM be created
- clearDatacenters(); // 清理数据中心
- createVmsInDatacenter(0); // 仿真结束
- }
- }
- }
5、shutdownEntity(),接收到END_OF_SIMULATION事件,仿真结束,清除所有实体。