我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
标签 #计算机网络

零毫秒:去中心化网络:关于网络架构和节点查找的讨论

零毫秒,计划已久,也拖了很久,其概念一直都在我的脑海中,这可能是第一篇正式的“讨论”。

之所以是讨论,是因为我对整个系统的架构依旧迷茫。而相比之下,RootPanel(RP主机面板), JyBBS(论坛系统), 的蓝图则非常清晰,实现起来不过是时间问题而已。

目前最大的困难是没人和我讨论,这个项目几乎走在了世界前列,没有多少资料可以借鉴,希望正在读的《计算机网络——自顶向下方法》能给我一些帮助。

然而当前几天我看到又一个类似项目,比特信(BitMessage)的时候,不能再忍了。

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

面向信任模型

即默认假定网络中的节点都是受信任的,如: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所需储存的信息的表格:

M1Node90016 KiB
M2Node2.7万477 KiB
M3Node81万14 MiB
M4Node243万429 MiB
M5Node7290万13 GiB
M6Node2.2亿390 GiB
M7Node660亿11 TiB
M8Node2万亿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的负荷。

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

时间校准

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

TCP/IP 笔记(5.ICMP)

IP是不可靠的传输协议,并没有提供错误处理相关的功能. 错误处理的能力由ICMP(Internet Control Message Protocol,互联网控制消息协议)提供.

ICMP是配合IP运行的不可或缺的重要机制,IMCP也运行于网际层,利用IP的传输能力来发送消息.

TCP/IP的错误报告与信息性功能主要是通过ICMP来传达的.

ICMP可用于进行:

  • 流程控制

当数据报抵达的速度太快而来不及处理时,目的主机或中间网关会回传一个SQM(ICMP Source Quench Message)给发送方,要求数据报的来源停止传送.

  • 无法到达目的地

当无法将数据报送达目的地时,检测到此问题的系统会发出DUM(Destination Unreachable Message)给数据包的来源.

所谓目的地,可能是某网络或某主机,也可能是目标主机的通讯端口.

对于前者,由中间网关发出DUM, 后者则由目标主机发出DUM.

  • 重定向路由

网关通过RM(ICMP Redirect Message)让主机知道另一个网关或许是比较好的选择. 只有源主机与网关都位于同一个网络上时,才能使用该消息.

  • 检查远程主机

主机可利用EM(ICMP Echo Message)来检查远程主机的IP是否已经激活,以及是否能正常运行. 当一个系统收到EM后,他会将收到的数据返回给源主机.

ping命令使用的就是EM.

TCP/IP 笔记(4.IP路由选择和分段)

IP数据报头中的目标地址决定数据报的去处,它代表目标网络中的特定主机. 如果目标地址在本地网络,直接将数据报送到该主机即可.

如果目标地址指向外部网络,则将数据报发给网关,而决定发给哪个网关的过程,叫路由选择.

IP会为每个数据报选择路由.

路由选择

Internet网关(gateway)通常被称为IP路由器(IP router). 网关根据IP决定数据报传送的路径.

严格来说,网关能在不同的协议之间传输数据,路由器则在不同网络间,使用相同协议传输数据.

在TCP/IP术语中,网络设备分为网关和主机.

网关同时连接到多个网络,并可以在网络之间传输数据,而主机不能. 但如果主机被连接到多个网络,也可以被视为网关.

网关和主机最大的差别在于,主机的数据包必须逐层经过四层协议的处理,而在网关上,数据包只需上达网际层即可,因为IP会为数据包决定路由.

任何网络设备都只能将数据报送到与自己连接在同一物理网络上的其他设备. 若要向其他网络上的设备发送数据报,则必须先将数据报发给连接两个网络的网关,然后由网关转发给目标设备.

对于一个主机而言,它只需知道本地网关可以将数据报送往其他网络,不必也不能控制数据报在经过网关之后的转发路径.

这是因为不同的物理网络之间可能完全不兼容,一个网络中的数据报,必须经过网关的转换才能送达另一网络. 这样,数据报像接力棒一样可以跨越多个不同的物理网络,到达目标.

数据报的分段

因为不同的物理网络本质上的差异,连接不同种类物理网络的网关的IP模块可能会将数据报拆分成较小的片段(fragment). 如果网关两端连接的是相同种类的物理网络,则不必拆分数据报.

每一种物理网络,都有自己的最大传输单元(MTU, Maximum Transmission Unit)限制,也就是说,各种网络所能承载的最大数据报容量并不一致.

当数据报从MTU较大的网络流向MTU较小的网络时,网关就必须将数据报拆分成较小的传输单位. 这个过程叫分段.

分解后的数据报称为片段,其格式与普通数据报一样,报头的编号部分可以用来唯一地区分一个片段,并作为还原数据报的依据.

片段(分段)偏移量代表该片段在原数据报中的位置(顺序).

标记中的是否为最后一个片段(分段), 可使IP判断是否已经收集到了一个数据报的所有片段.

传送数据给传输层

当IP收到一个传送给本机的数据报时,它会去掉报头,将得到的数据交给正确的传输层协议(如TCP或UDP). 至于要交给哪一种传输层协议,则由协议号决定,每一种传输层协议都有自己的协议号,以便IP进行识别.

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2024-04-08.