1、KAD网络调研心得,Kademlia网络模拟课堂报告 Shan Zifei, PKU,大纲,调研结果 系统功能 项目分工 代码规范,1.调研结果,调研目标 调研方法 主要调研结果,研究问题 锻炼能力 相互了解,1.1.调研目标,分别阅读发现问题 组长要有清晰了解 搜寻并分享资料 资料有针对性,避免让组员做无用功 集体讨论统一认识 形成思路 解决疑问,1.2.调研方法,Kademlia: 分布式哈希表(DHT)技术 以异或(XOR)算法为距离度量基础 下面从Kad的几个方面谈。,1.3.调研结果,Kad是P2P的网络,没有服务器(Server)。 节点即为Peer/Client。 节点信息: I
2、P地址 UDP端口 节点ID,1.3.1节点,每一个加入KAD网络的计算机都会被分配一个32位二进制数作为节点ID值。 判断两个节点的距离远近是基于数学上的异或的二进制运算,即两个节点距离为其节点ID异或得到的二进制数。 异或又称为环和,具有循环特性。采用异或操作作为距离的度量方法,可以将全部ID映射到一个环上(比如,采用格雷码作为映射方法)。,1.3.1节点,KAD中每个节点维护一个路由表,用以保存如何连接到其他节点的信息。 路由表是通过一些称之为K桶的表格构造起来的。 对每一个0i32,对应一个K桶,保存着与本节点已知距离介于区间 2i, 2(i+1) 的若干个节点的信息。 K桶中存储的信
3、息有:节点ID、节点IP地址和UDP端口信息(题目的基本要求只保存节点ID)。 本题目中要求每个K桶中保存最多10个节点信息,其中信息更新依据Least-recently Seen Eviction原则。,1.3.2节点路由表,K桶结构示意图,进一步分析,每一个K桶实际上都对定位了ID的一个二进制位。根据异或的运算性质分析,可以得到K桶中ID的储存规律。 设节点的ID为id,对于该节点第i位的K桶,满足:K桶中的节点ID的第i位与id的第i位不同,第i+131位与id的第i+131位相同。如下表:(设ID简化为5位,K桶容量简化为5个节点),K桶内节点ID规律示意图,由此我们可以看到,低位的K
4、桶定位更加精准,且难以达到桶满状态;高位的K桶低位都是随意的,定位不够精准,且容易达到桶满状态。,K桶的信息更新机制如下:每当节点x收到一个远程操作消息(包括下面要提到的四种消息)时,都要用发送者y的节点信息更新自己的K桶。具体步骤为: 1计算自己和发送者的距离:d(x,y) = ID(x) xor ID(y)。 2通过距离d选择对应的K桶进行更新操作: 3如果y的IP地址已经存在于这个K桶中,则把对应项移到该K桶的尾部。,K桶的更新,4如果y的IP地址没有记录在该K桶中: 如果该K桶的记录项小于k个,则直接把y的(IP address, UDP port, Node ID)信息插入队列尾部。
5、 如果该K桶的记录项大于k个,则选择k桶头部的节点z进行PING操作: 如果z没有响应,则从K桶中移除z的信息,并把y的信息插入队列尾部 如果z有响应,则把z的信息移到队列尾部,同时忽略y的信息。(这种操作基于“长时间在线的节点,未来长时间在线的可能性更大”的统计规律),K桶的更新,KAD协议包括四种远程操作:PING、STORE、FIND_NODE、FIND_VALUE。 注意这四种消息都是要即时更新接受者的K桶的。,1.3.3.远程操作(分布式版本),PING:探测一个节点是否在线。 向这个节点发送一个PING信息,并等待一个回复。如果超时则判断这个节点不在线。 STORE:通知一个节点储
6、存一个对。 Key值为资源ID,也是32位二进制数,用散列算法得到;value是资源信息(资源被存放在哪个节点),由这个信息可以获得特定资源的位置。,1.3.3.远程操作,FIND_NODE(ID, k):返回节点所知道的更接近目标ID的k个节点的信息。 这些节点的信息可以从一个单独的K桶获得,也可以从多个K桶获得(如果最接近目标ID的K桶未满)。 FIND_VALUE(key):返回节点内储存的资源地址或资源值。 如果节点内存放了资源地址,则返回资源地址(资源所在节点信息)。 如果节点内没有存放ID为key的资源,返回空串。,1.3.3.远程操作,通过K桶实现路由(查找)操作时,将由远及近,
7、依次定位节点ID,在O(logN)(N为ID空间,此处为232)的时间内完成查询操作。具体步骤如下:(注意使用迭代而不是递归),1.3.4.路由查询(lookup),在节点查询的时候,它先得到它K桶中离所查询的键值最近的K(题目要求为5)个节点,然后向这K个节点发起FIND_NODE消息请求,消息接收者收到这些请求消息后将在 他们的K桶中进行查询,如果他们知道离被查键更近的节点,他们就返回这些节点(最多K个)。 消息的请求者在收到响应后将使用它所收到的响应结果来更新它的 结果列表,这个结果列表总是保持K个最优节点(即离被搜索键更近的K个节点)。然后消息发起者将向这K个最优节点发起查询,不断地迭
8、代执行上述查询过程。 如果本次响应结果中的节点没有比前次响应结果中的节点离被搜索键值更近了,这个查询迭代也就终止了。当这个迭代终止的时候,响应结果集中的K个最优节点就是整个网络中离被搜索键值最近的K个节点。 由于每次FIND_NODE等待时间较长,可以进行并行查询,同时查询K个结点,可将O(Kp)变为 O(p)。p:每次通讯时间,1.3.4.路由查询(lookup),想要加入网络的节点首先要经历一个引导过程。在引导过程中,节点需要知道其他已加入该网络的某个节点的IP地址和端口号。 假如正在引导的那个节点还未加入网络,它会计算一个目前为止还未分配给其他节点的随机ID,直到离开网络,该节点会一直使
9、用该ID。(真实网络中这个ID是根据IP计算的) 正在加入网络的节点在它的某个K桶中插入引导节点(负责加入节点的初始化工作),然后向它的唯一邻居(引导节点)发起FIND_NODE操作请求来定位自己,这种“自我定位”将使得Kademlia的其他节点(收到请求的节点)能够使用新加入节点的节点ID填充他们的K桶;同时也能够使用那些查询过程的中间节点(位于新加入节点和引导节点的查询路径上的其他节点)来填充新加入节点的K桶。,1.3.5.加入网络,结点发布资源的过程为: 先计算资源的ID(通过散列函数) 资源ID与结点ID一样,是一个32位二进制数 寻找距离ID最近的k(5)个结点,用STORE操作通知
10、他们存储资源信息(资源ID,资源所在节点信息)对。 查找资源时,凭借资源的散列得到的ID,到距离ID最近的k个结点询问资源地址,再访问资源地址获取资源。,1.3.6.发布资源,2.系统功能,基础操作 分布式版本 Windows socket / boost 实现的网络通信 使用UDP协议而非TCP协议 多线程 界面,系统功能,3.项目分工,对组员的要求 分工方法 文件结构 初步分工,每个组员都应该充分了解项目的整体框架,并熟悉其他人的工作。 每个组员都应独立提交自己的cpp文件,并经过充分的调试,严格确保自己提交的代码的正确性。 每个组员提交的cpp文件应该严格遵守代码规范,并进行规范、充足的
11、注释。,3.1.项目对组员的要求,组长提供头文件,组员实现头文件中的函数 接口:头文件的函数声明 无需关心他人的函数实现,但要清楚函数作用 实现了任务的分离,3.2.项目分工方法,每个类一个.h头文件和一个对应的.cpp文件 头文件进行类的声明 cpp文件进行类中函数的实现 使用作用域符号,如 Address:Address() 头文件之间可能有互相引用的关系 每个类实现的cpp文件只引用自身对应的头文件 一个项目总的头文件kad.h: 全局变量(使用extern)和全局函数声明 头文件使用#ifndef #endif防止重复编译,3.3.文件结构设计,4.代码规范,统一编程环境 VS2008
12、 规范注释(详见课程网站要求),4.1.环境和注释,逻辑上有分隔的单元之间空一行。 注释统一使用/,尽量不要用/*/。 相邻行的注释尽量使用tab对齐。 每行字符数最好不超过99个,中文算两个字符 Void foo() 注意花括号前面要空一格,不要顶着小括号写,4.2.细节的代码规范,形成一套自己的规范就好。我的习惯是: 类名、函数名:不加下划线,每个单词首字母大写,本身就由大写字母组成的单词都大写。如:GetID,GetInfo,WeAreEECSers 变量名:单词之间加下划线,没有大写,如num_books 宏定义、常量名:全部大写,词之间加下划线_ 全局变量:尽量不使用,重要全局变量之前加“the_”, 如the_macs。,关于命名,以下运算符前后都不加空格: . (点) -(箭头) :(作用域运算符)等 以下运算符只有后面加空格: ,(逗号,这个挺重要):(冒号,初始化列表里可能用到) 其他大部分运算符两边都加空格,比如: + - * / = = != 还有一些小的地方,比如二维数组和之间不能加空格啦 另外行尾最好不要有多余空格。,关于空格,The End,Thanks!,