本文的目的是在PeerSim中用Cycle-based模型实现一个简单的负载均衡算法。节点的状态有两种值:本地负载(local load)和配额(quota),其中配额是指节点在每个周期中允许传输的“负载”的大小。配额是必要的,是一个时间单元中能传输的负载上限。每个节点与和它距离最远的邻居节点交换配额值,这里“距离最远”是指与当前节点的负载差异最大。经过对比距离,协议将在负载均衡时选用push或pull的方式。
在每个周期之后,配额值将会被存储。协议并不关心拓扑管理,它依赖于其它组件来访问邻居节点(例如,Newscast,或者由IdleProtocol实现的静态拓扑)。
一. 必要的组件
一般来说只编写一个协议类是不足够的,还需要一些附加的组件。例如,为了在每个周期结束时为每个节点存储配额值,需要一个特定的Control对象。基本上来说,PeerSim是一个可替换的组件集合,所以在开发时需要注意模块化以让代码尽可能重用,出于这样的目的,我们这样设计下面的类:
- protocol 它基于peersim.vector.SimpleValueHolder,这是一个简单的基类,用于访问一个浮点变量。Aggreation协议也使用了同样的基类。
- ResetQuota 用于在每个周期结束时存储每个节点配额的control。
- QuotaObserver 一个control,用于监视quota参数,即覆盖网中交换的流量大小。
- initialization 这是在aggregation示例中的初始化器,这里也可以直接使用,因为它们实现了同样的接口SingleValueHolder。注意在example包中提供的初始化器是轻量级的,开发者应当更多地使用peersim.vector.*包中的初始化器。
- observers 可以使用aggreagation.AverageObserver,因为这些组件实现了相同接口。
Read more…
本文介绍了PeerSim的基本概念,并解析了两个示例以更清晰地说明PeeSim的仿真流程。
Peersim支持两种仿真模式,即Cycle-based的模型和传统的event-based的模型,本文专注于前者,
Cycle-based模型是一个简化的模型,拥有更好的伸缩性及性能,在拥有4GB内存的情况下,event-driven模式目前最多支持十万节点级别,而cycle-based模式则支持千万个节点级别。 但是Cycle-based模型缺少对传输层的仿真和并行处理,节点之间是直接通信的,仿真核心以一定的顺序周期性地给以节点控制。在运行时,可以进行任意的操作,如调用其它对象的方法并执行一些计算。
Cycle-based模型损失了一些真实性,虽然一些简单的协议可以忽略这些差别,但是在选择使用这个模型时,需要注意这些区别。我们可以相对简单地将Cycle-based的仿真移植到Event-driven引擎上,但在本文中不讨论这个话题。
一.基本介绍
PeerSim鼓励基于接口的模块化编程,每一个组件都能被其它实现了相同接口的组件代替,一般的仿真过程如下:
- 选择网络大小(即节点数量)。
- 选择要实验的一个或多个协议并进行初始化。
- 选择一个或多个Control对象来监视感兴趣的属性,并在仿真时修改一些参数(比如,网络大小,协议的内部状态,等等)。
- 根据配置文件,调用Simulator类运行仿真。
在仿真时创建的对象都是实现了一个或多个接口的类的实例,主要的接口如下所示:
| Node |
P2P网络是由节点组成的,节点是协议的容器。Node接口提供了对节点所包含的协议的访问方法,并为节点提供了固定的ID。 |
| CDProtocol |
这是一个特定的协议,被设计用来在Cycle-based模型中运行,它只定义了在每一个周期中要运行的操作。 |
| Linkable |
一般都由协议来实现,这个接口为其它协议提供了访问邻居节点集合的服务,节点间相同的linkable协议类的实例定义了一个覆盖网络。 |
| Control |
实现了这个接口的类可以在仿真期间的某个时间点调度执行,这些类一般用于观察或修改仿真过程。 |
Cycle-based仿真的生命周期是这样的:
- 读取配置文件(通过命令行参数传递进来),然后仿真器初始化网络中的节点和节点中的协议,每个节点都拥有相同的协议栈。节点和协议的实例是通过克隆来创建的,只有一个原型是通过构造方法创建,其它的节点和协议都是从这个原型中克隆而来。基于这个原因,协议类中clone方法的实现是很重要的。
- 初始化操作,设置每个协议的初始状态。初始化阶段是由Control对象控制运行的,仅在实验开始时运行一次。在配置文件中,初始化的组件可以由init前缀识别,在下面讨论的initializer对象也是controls,但为了标记其功能以区别于一般的Control对象,它被配置用来在初始阶段运行。
- 在初始化完成后,Cycle-based引擎在每一个周期中调用所有组件(protocols和controls)一次,直到完成了指定的周期数,或者某个组件决定终止仿真为止。在PeerSim中每一个对象(controls和protocols)都被赋以一个Scheduler对象,它定义了什么时候本组件将会被执行。在默认情况下,所有对象都会在每个周期中运行。但我们也可以配置一个protocol或control只在某些特定的周期中运行,也可以在每一个周期中指定组件的执行顺序。
Read more…
Zipf定律是文献计量学的重要定律之一,它和罗特卡定律、布拉德福定律一起被并称为文献计量学的三大定律。
对于CDN的内容管理,也近似符合Zipf 定律,就是大家常说对于内容的访问遵循80/20原则,也就是20%的内容,会占有80%的访问量。

zipf law
这里 r 表示一个单词的出现频率的排名,P(r)表示排名为r的单词的出现频率.
(单词频率分布中 C约等于0.1, a约等于1)
后人将这个分布称为zipf distribution,中文名称为齐普夫分布或Zeta 分布。这是一个离散事件分布,广泛应用于语言学,保险学,网络模拟,以及对稀疏事件的建模中。
它表明在英语单词中,只有极少数的词被经常使用,而绝大多数词很少被使用。实际上,包括汉语在内的许多国家的语言都有这种特点。这个定律后来在很多领域得到了同样的验证,包括网站的访问者数量、城镇的大小和每个国家公司的数量。。这个定理也在很多分布里面得到了验证,比如人们的收入,互联网的网站数量和访问比例,互联网内容和访问比例(其他分布两个常数有所不同,a越大,分布越密集,对于VOD来说某些时候符合双zipf分布)。
比起枯燥的公式,图表更具有说服力,下面是用三百个严格符合zipf 分布的数据点描绘成的图,其中横轴表示排名,纵轴表示访问的频率,分别使用线性坐标和对数坐标表示:

zipf distribution
可以看到对数坐标下是一条完美的直线。
Read more…
OMNet++ in a nutshell
本文适合对网络模拟器有一定了解的读者,阅读本文时,最好同时打开用户手册和API文档以便随时查阅。
1. 在omnetpp.org中提到的仿真模型和框架与OMNet++是什么关系?
OMNet++提供了基本的工具和机制来编写仿真代码,但它本身并不提供任何特定用于计算机网络仿真,系统架构仿真和任意其它领域的组件;具体的仿真是由一些仿真模型和框架如Mobility Framework或INET Framework来支持,这些模型独立于OMNet++开发,并有自己的发布周期。
2. OMNet++提供了什么?
一个C++库,它由仿真内核及一些用来创建仿真组件(简单模块和信息)的工具类(如随机数生成,统计收集,拓扑发现等);组装和配置这些组件的基础设施(NED语言,ini文件);运行时用户接口或仿真环境(TKenv,Cmdenv);一个用来设计,运行和评估仿真的IDE环境;实时仿真的扩展接口;MRIP,并行的分布式仿真,数据库连接等等这些组成。
3. OMNet++的仿真模型是什么样的?
OMNet++提供了一个基于组件的架构,模型是由可重用的组件或模块组成的。模块之间可以通过gates(在其它系统中称为ports,即端口)进行连接,以构成复合模块。每个仿真模型是一个复合模块类型的实例。这一层次(组件和拓扑)由NED文件来处理。例如,一个名为EtherMAC的组件可以用NED来描述:
//
// Ethernet CSMA/CD MAC
//
simple EtherMAC {
parameters:
string address; // others omitted for brevity
gates:
input phyIn; // to physical layer or the network
output phyOut; // to physical layer or the network
input llcIn; // to EtherLLC or higher layer
output llcOut; // to EtherLLC or higher layer
}
它可以使用在下面的Ethernet station的模型中:
//
// Host with an Ethernet interface
//
module EtherStation {
parameters: ...
gates: ...
input in; // for connecting to switch/hub, etc
output out;
submodules:
app: EtherTrafficGen;
llc: EtherLLC;
mac: EtherMAC;
connections:
app.out --> llc.hlIn;
app.in < -- llc.hlOut;
llc.macIn <-- mac.llcOut; llc.macOout --> mac.llcIn;
mac.phyIn < -- in; mac.phyOut --> out;
}
其中,注释能用来生成文档。简单模块,例如上面的EtherMAC,会与一个C++ 文件关联以提供行为,它是以simple关键字来声明的。复合模块则是用module关键字来声明的,为了仿真一个Ethernet LAN,应该创建一个复合模块EtherLAN并用network关键字来表示它可以通过自身运行。
network EtherLAN {
... (submodules of type EtherStation, etc) ...
}
NED文件可以在IDE中以图形化方式或文件模式编辑。
NED文件只定义了模型的结构(拓扑),其行为和模块参数的某个子集则是开放的,如前面所提到的,行为是通过在简单模块相关联的C++代码来定义的,而在NED文件中没有赋值的模块参数则从ini文件中获取它们的值。
Read more…
评论