一个去中心化网络模型



纵观现在的互联网,个人认为它具有以下几个特点:

面向信任模型
即默认假定网络中的节点都是受信任的,如:IP和TCP, UDP数据报均不加密不签名,传输过程中的任何路由节点均可修改数据报。IP不提供担保,能否无误送达取决于中间路由节点。发信人向收信人发送数据报完全不需要收信人的同意,收信人无法拒收。

分层架构,在端点实现功能
即大多数功能在通信的两端实现,中间的路由无需关心,只需转发。如TCP的面向连接,排序,错误重传,IP的分段等等。
同时协议分层,上层协议更新不影响底层协议。

天生去中心化
互联网从未依赖于一个中心节点,每个路由都是独立工作的,这使得没有人能控制整个网络,除非控制每一个路由器。同时即使一处网络断开,被分割的各个部分也可以单独工作。

IPv6一定程度上解决了IPv4在上述特点中暴露的问题,IPv6的普及工作已经进行了十几年,仍没有显著成效。零毫秒希望在应用层组建一个去中心化网络,为上层应用提供身份验证,名称注册,加密传输,节点查找,信息广播/查询,组群,离线储存等功能。作为一个示例,零毫秒会首先实现一个即时通讯软件。

可以预见,在应用层进行数据报转发是非常不明智的。零毫秒也分为多层架构,在核心(最底层)只转发控制指令,实现最为基本的组网和节点查找功能,毕竟只要找到目标节点,即可进行点对点通讯。通过组件树状的结构化网络,为上层应用提供方便,使网络流量最小化。

零毫秒分层:

  • 核心层:组网,节点查找,身份验证,组群
  • 服务层:名称注册(加强版DNS), 信息广播和查询,离线储存
  • 应用层:应用自有协议,如即时通讯

零毫秒网络有树状的结构,每个树节点有30个子节点。最次一级叫NNode(Normal Node), 其余具有子节点的树节点叫MNode(Master Node). 由底向上,由多至少,按层级分别为M1Node, M2Node, M3Node, 可无限扩充。一个新节点接入网络时,只需知道网络中任意一个节点的地址(IP和端口), 即可通过它获取到M1Node列表,并逐个尝试接入。网络中第一个节点启动时,则直接默认自己是M1Node. MNode需要有公网IP, 或使用UPnP.

加入网络后,作为NNode, 可以向M1Node申请成为M1Node. 成为M1Node后可向M2Node申请成为M2Node, 如果没有M2Node, 则像其他M1Node申请成为第一个M2Node.
申请是否成功并非绝对,有多少节点通过了你的申请,你就成为了多少节点眼中的MNode. 处理申请时要考虑的因素包括:网络延迟,带宽,已有节点数量,历史信用等。

这可能让读者存在一些疑惑,最高级的MNode是否可以控制整个网络,进行破坏呢?事实上因为零毫秒会对每一个数据包进行加密和签名,所以即使是MNode也无法对数据包进行篡改。当然它可以选择不作为——不按约定转发数据包,但这种行为会很快地被发现,其他节点会很快自动地推选出另一个MNode. 同时可以在核心层实现一个简单的点对点信用系统(类似于电驴的积分系统), 每当上级MNode为自己提供服务时,即为对方增加一点信用值,当上级MNode出现丢包,网络中断时,即为对方减少信用值。一段时间后,该信用值将能够很好地评估对方是否适合成为一个MNode.

我们再来讨论该模型的负荷,很显然,整个网络的节点数量取决于MNode的层级,以30为底数呈指数关系,而整个网络的瓶颈在于最高级的MNode, 因为在接下来的设计中,MNode需要储存(缓存)其所有(直接或间接)子节点的信息。这些信息包括256 Byte的用户ID(公钥), 18 Byte的地址(兼容IPv6, 以及端口号), 可选的256 Byte的额外信息(如节点层级等等), 合集530 Byte.

下表是含有M1Node至M8Node的网络下,可容纳节点数与MNode所需储存的信息的表格:

M1Node 900 16 KiB
M2Node 2.7万 477 KiB
M3Node 81万 14 MiB
M4Node 243万 429 MiB
M5Node 7290万 13 GiB
M6Node 2.2亿 390 GiB
M7Node 660亿 11 TiB
M8Node 2万亿 330 TiB

以当前硬件水平而论,M1Node至M3Node, 甚至M4Node, 都可以运行于个人计算机。而M4Node和M5Node适合运行于服务器,M6Node可运行于高性能集群。至此,M6Node已可以容纳2.2亿个节点。至今内存的发展远未达到瓶颈,仍在以摩尔定律预测的速度更新,更何况MNode可通过散列表,数据库引擎等技术来降低内存占用,所以单就内存而言,我认为不存在瓶颈。

在这种树状结构下,节点查找显得十分有序:逐级向上查找即可。查询经过的节点数量在最不理想的情况下,和网络规模(节点数量)成对数关系。当然,前文只讨论了内存瓶颈,毫无疑问最顶层MNode会收到大量的查询请求。但我们可以非常简单地通过集群来处理查询。即使在极大规模的MNode, 如M7Node, 我们也可以通过两层集群轻松应对:路由将零毫秒的数据包(甚至可以不做区分,直接全部)随机发往第一个集群,读出被查询的ID, 进行散列后发往第二个集群中的散列值前缀指定的服务器。每个服务器只需处理指定散列前缀的查询。数据包加解密和序列化可由单独的服务器进行。

在具体实现方面,我选择了以RSA公私玥对作为用户标识,公钥为ID, 私钥为凭证,每个数据包均需签名,签名值同时可以作为一个数据包的编号。节点之间使用SSL连接,支持IPv6. 因为目前所讨论的内容只涉及控制指令,所有指令都无需加密,这样可以使节点列表等信息被中间节点所缓存。所以只需在节点之间加密即可,无需在端点之间进行加密。

我选择使用JSON来承载通讯协议,因为JSON应用广泛,被众多开发环境支持,易于调试,具有很好的扩展性,同时可作为流来使用。为提高传输性能,可以考虑使用其二进制版本BSON, 也可以JSON, BSON双支持,前者用于调试环境,后者用于生产环境。

我还需要指出目前设计存在的几个问题:

节点的聚合方式
30个节点依据什么聚合在一起?我更倾向于按网络情况聚合,这样可以保证在网络的任意部分都具有高速的连接。不过也可以考虑通过经常联系与否来进行聚合,毕竟在较低层级处理查询将显著减少顶级MNode的负荷。

单个节点如何估计网络规模,选择时机进行“升级”

时间校准
数据包中应当包含时间戳,以供今后查证,但很难找到一个去中心化的时间校准方式。

猜你喜欢

转载自blog.csdn.net/FYZDMMCpp/article/details/39670613
今日推荐