- https://github.com/Cloudslab/iFogSim
- iFogSim 基于 CloudSim,扩展了基本的 CloudSim 类的抽象,提供了模拟具有大量雾节点和物联网设备(如传感器、执行器)的定制雾计算环境。iFogSim 的核心执行思想:**
Sense - Process - Actuate
**- iFogSim 可以实现对端到端延迟、网络拥塞、能耗、执行成本和 QoS 的评估
- iFogSim 主要有三个基本组件构成:
physical components
、logical components
、management components
iFogSim实验环境简介
- iFogSim 和 WorkflowSim 一样,都是基于 CloudSim 的。iFogSim 扩展了基本的 CloudSim 类的抽象,提供了模拟具有大量雾节点和物联网设备(如传感器、执行器)的定制雾计算环境。
- iFogSim 的核心执行思想:**
Sense - Process - Actuate
**,亦即 感知 - 处理 - 执行。 - iFogSim 可以实现对端到端延迟、网络拥塞、能耗、执行成本和 QoS 的评估
Components
- iFogSim 主要有三个基本组件构成:
physical components
- 物理组件包含雾设备(雾节点)
Fog devices
,雾设备按分层顺序排列,低等级的雾设备与传感器和执行器直接连接。在边缘云环境中,雾设备起到提供内存、CPU、网络等资源的作用,类似于云环境中数据中心的作用。
- 物理组件包含雾设备(雾节点)
logical components
- 逻辑组件包含应用程序模块
Application modules
和应用程序 “边”Application Edges
。应用程序就是由互相依赖的一系列应用程序模块构成。 - 应用程序模块用来执行传感器传输过来的任务(处理传感器传输过来的数据),应用程序模块之间的数据传输关系由应用程序 “边” 来描述。
- 逻辑组件包含应用程序模块
management components
- 管理组件包含控制器
Controller
和模块映射对象Module Mapping
。模块映射对象根据应用程序模块的要求,识别雾设备中的可用资源,并将其放置在其中。控制器对象根据模块映射对象提供的放置信息,在其指定的雾设备上启动应用程序模块,并定期管理雾设备的资源。- 简单地说,模块映射对象
Module Mapping
用于确定应用程序模块和雾设备之间的放置关系(如果设计了一个放置算法,那这里就是放置算法发生作用的地方),控制器对象Controller
基于该放置关系,对应用程序模块进行执行(执行后的结果就是从控制器对象这里得到的)。
- 简单地说,模块映射对象
- 管理组件包含控制器
hierarchical order
- 在 iFogSim 中,FogDevice 被划分为不同的层级
End Device
和 IoT 传感器、执行器直接进行连接Gateway Device
作为End Device
和云端之间的桥接
Simulation Steps
首先要创建物理组件,根据指定的配置创建雾设备,包括内存 ram、计算处理能力(mips)、执行开销 cost、上行和下行带宽、能耗。
- 在 iFogSim 中对应
Sensor
、Actuator
、FogDevice
类Sensor
上传的要处理的任务在 iFogSim 中用tuple
类来描述,上传任务的频率在Sensor
中定义
- 在 iFogSim 中对应
然后要创建逻辑组件,即要执行的应用程序模块
Application modules
和表示应用程序模块之间依赖关系的 “边”Application Edges
。这里要指定的配置包括任务的类型、数据传输方向、任务数据量、要传输的数据量等。在 iFogSim 中对应
Application
类逻辑组件可以被创建为不同的类型:
主 - 从类型:
顺序单向类型:
最后要创建管理组件,在管理组件中定义要执行的放置策略,并根据放置策略对应用程序进行执行。
- 在 iFogSim 中对应
Controller
、ModulePlacement
类
- 在 iFogSim 中对应
QA
Q:在 iFogSim 中,雾设备之间的层级关系是什么样的?
A:以
VRGameFog
为例,雾设备之间的层级关系见下图:更具体地来说,以
VRGameFog
为例,在 iFogSim 中有以下SimEntity
:
Q:应用程序模块放置在雾设备上的策略是如何确定的?
A:应用程序模块放置在雾设备上的策略是在
ModuleMapping
确定的,通过在ModuleMapping
中根据自己设计的算法确定Map<雾设备,放置在雾设备上的应用程序模块的集合>
,即应用程序模块和雾设备的放置关系。然后根据这个放置关系,在
ModulePlacement
中进行实际的应用模块在雾设备上的放置(真正地为应用模块分配计算资源),这个过程会确定Map<模块名称, 放置了该类模块的雾设备id集合>
和Map<雾设备的id, 在该雾设备上放置的AppModule集合>
。然后在
Controller
中,通过ModulePlacement
中已有的放置关系(已经真正地为应用模块分配计算资源了),将应用程序模块都启动起来。所以总体流程是:
在
ModuleMapping
中根据设计的算法确定放置关系(放置关系存放在Map<雾设备,放置在雾设备上的应用程序模块的集合>
中) —> 在
ModulePlacement
中根据ModuleMapping
的放置关系进行实际的应用模块在雾设备上的放置(实际放置以后,放置关系存放在Map<模块名称, 放置了该类模块的雾设备id集合>
和Map<雾设备的id, 在该雾设备上放置的AppModule集合>
中) —> 在
Controller
中根据实际的放置关系对任务进行执行ModuleMapping
中的放置关系可以理解为 “蓝图”,是概念上的放置关系ModulePlacement
中的放置关系可以理解为 “实际场景”,是真正地进行了放置
Q:iFogSim 的核心事件执行流程是什么样的?
A:接下来将以
类名::事件Tag::{事件函数}
的方式描述 iFogSim 核心事件的执行流程。注册应用和资源阶段:
FogDevice::FogEvents.SENSOR_JOINED::processSensorJoining(ev);
将传感器和对应的雾设备联系起来FogDevice::FogEvents.ACTUATOR_JOINED::processActuatorJoined(ev);
将执行器和对应的雾设备联系起来FogDevice::FogEvents.ACTIVE_APP_UPDATE::updateActiveApplications(ev);
告诉雾设备活跃的应用程序有哪些FogDevice::FogEvents.APP_SUBMIT::processAppSubmit(ev);
告诉雾设备应用程序有哪些
启动阶段:
FogDevice::FogEvents.LAUNCH_MODULE::processModuleArrival(ev);
将雾设备上的应用程序模块都启动起来,如果这个应用程序模块是 periodicTuple 的 sourceModule,则该雾设备还会让该应用模块不断地周期性发送任务(通过周期性地发送FogEvents.SEND_PERIODIC_TUPLE
信号来实现,即在FogEvents.SEND_PERIODIC_TUPLE
对应的处理方法中又发送该信号给自己)FogDevice::FogEvents.RESOURCE_MGMT::manageResources(ev);
定期的对能耗结果进行更新,实现定期的方式和上面的方法类似,通过在对应的处理方法中又发送该信号给自己实现Sensor::FogEvents.EMIT_TUPLE::transmit();
传感器周期性地发送要处理的任务
处理任务阶段:
Sensor::FogEvents.TUPLE_ACK::{}
如果传感器收到这个信号,就表示它已经成功地把任务发送给关联的雾设备FogDevice::FogEvents.TUPLE_ARRIVAL::processTupleArrival(ev)
雾设备处理发送给它的任务
Q:iFogSim 是怎么得到最终执行后的结果的?
A:最终执行后的结果都保存在
Controller
中,iFogSim 是直接在Controller
中输出结果了。具体而言,是在Controller
类的processEvent
方法中:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// Controller.processEvent(SimEvent ev)
public void processEvent(SimEvent ev) {
switch (ev.getTag()) {
case FogEvents.APP_SUBMIT:
processAppSubmit(ev);
break;
case FogEvents.TUPLE_FINISHED:
processTupleFinished(ev);
break;
case FogEvents.CONTROLLER_RESOURCE_MANAGE:
manageResources();
break;
case FogEvents.STOP_SIMULATION: // 在这个事件中将结果输出了, 然后系统直接退出
CloudSim.stopSimulation();
printTimeDetails();
printPowerDetails();
printCostDetails();
printNetworkUsageDetails();
System.exit(0);
break;
}
}Q:iFogSim 是怎么计算时间、能耗、开销等一系列相关参数的?
A:这其实是在 iFogSim 执行过程中不断更新的。具体而言,在 iFogSim 模拟的过程中,Entities 会不断地处理事件 Event,而在处理事件的具体方法中,就有可能会更新相关的时间、能耗、开销等参数,例如在
FogDevice
的processOtherEvent
方法中,有一些事件就会涉及到更新相关参数:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
protected void processOtherEvent(SimEvent ev) {
switch (ev.getTag()) {
case FogEvents.TUPLE_ARRIVAL:
// 处理任务到达事件
processTupleArrival(ev);
break;
case FogEvents.LAUNCH_MODULE:
// 处理模块启动事件,在这个事件中拥有PeriodicTuples的模块会开始周期性地发送任务
processModuleArrival(ev);
break;
case FogEvents.RELEASE_OPERATOR:
processOperatorRelease(ev);
break;
case FogEvents.SENSOR_JOINED:
// 该事件会向 sensor 发送一个 ACK 信号
processSensorJoining(ev);
break;
case FogEvents.SEND_PERIODIC_TUPLE:
// 该事件会创建一个tuple发送给entity自己
// 然后继续send(getId(), edge.getPeriodicity(), FogEvents.SEND_PERIODIC_TUPLE, edge);
// 用来周期性地发送任务
sendPeriodicTuple(ev);
break;
case FogEvents.APP_SUBMIT:
// 将应用程序加入applicationMap
processAppSubmit(ev);
break;
case FogEvents.UPDATE_NORTH_TUPLE_QUEUE:
updateNorthTupleQueue();
break;
case FogEvents.UPDATE_SOUTH_TUPLE_QUEUE:
updateSouthTupleQueue();
break;
case FogEvents.ACTIVE_APP_UPDATE:
// 将活跃的App的名称加入activeApplications
updateActiveApplications(ev);
break;
case FogEvents.ACTUATOR_JOINED:
// 将和当前entity相关的actuatorId加入到associatedActuatorIds
processActuatorJoined(ev);
break;
case FogEvents.LAUNCH_MODULE_INSTANCE:
updateModuleInstanceCount(ev);
break;
case FogEvents.MODULE_SEND:
moduleSend(ev);
break;
case FogEvents.MODULE_RECEIVE:
moduleReceive(ev);
break;
case FogEvents.RELEASE_MODULE:
processModuleTermination(ev);
break;
case FogEvents.RESOURCE_MGMT:
// 这个事件会定期的对能耗结果进行更新
manageResources(ev);
break;
case FogEvents.UPDATE_CLUSTER_TUPLE_QUEUE:
updateClusterTupleQueue();
break;
case FogEvents.START_DYNAMIC_CLUSTERING:
//This message is received by the devices to start their clustering
processClustering(this.getParentId(), this.getId(), ev);
break;
default:
break;
}
}