🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Go-libp2p Protocol Labs旗下目前有五个明星项目,每一个都有其独特的定位和功能。五个项目彼此独立又联系,旨在建立一个更安全、高效、开放的网络。在Protocol Labs的官网我们可以找到上面5个项目,即IPFS、Filecoin、Libp2p、IPLD、Multiformats。 ![](https://img.kancloud.cn/bd/5c/bd5c9ac8be4d0349b93e68e045ec280d_1926x1345.png) 其中,**Libp2p是一个模块化的网络栈**,通过将各种传输和P2P协议结合在一起,使得开发人员很容易构建大型、健壮的P2P网络。 ![](https://img.kancloud.cn/58/8b/588bb6d46df564b2534273db9886852a_1192x1055.png) Libp2p被用作IPFS的网络层,主要负责发现节点、连接节点、发现数据、传输数据。Libp2p 集成了各种传输协议和点对点协议,其主要作用是发现节点和内容,并且让不同的网络协议能够互相之间顺利的传送数据。开发人员可以使用 Libp2p 轻松构建大型,稳定的 p2p 网络。Libp2p 主要包含了如下技术实现: Transports:传输 Discovery:发现 Peer Routing: 对等端路由 NAT Traversal: NAT穿透 Content Routing: 内容路由 # Libp2p 架构和流程 该项目主要包括了如下几个模块: * **Peer Routing - 对等端路由** 用来决定使用哪些对等端路由指定的消息。这种路由机制可以递归甚至在广播/组播模式下完成。 对等端路由子系统暴露出一些接口,用来确定一条消息应该被路由到DHT中的哪些对等端。它接受一个key,且返回一个或多个PeerInfo对象。以下是两个对等端路由子系统的实例,第一个基于Kademlia DHT,第二个基于mDNS。然而,只要实现了同样的功能和接口,其他的对等端路由机制也可以被实现。 **kad-routing**实现了Kademlia路由表,每个对等端都保存着一个k桶集合,每个k桶中都包含着几个来自网络中其他对等端的PeerInfo对象。 **mDNS-routing**使用mDNS探测来识别局域网对等端是否有指定的key或者他们是否在线。 * **Swarm - 连接处理** 负责管理节点之间连接的创建、维护、销毁。包括协议多路复用、流多路复用、NAT穿透和连接中继,同时进行多路传输。 关于中继:由于NAT,反向代理,防火墙或不支持相同的传输(例如,go-ipfs与browser-ipfs),中继在某些情况下是很有必要的。中继连接使用起来和常规的连接差不多,也同样是端对端加密的。中继线路既是隧道传输,也是Swarm协议。传输是建立与接受连接的工具,swarm协议是中继连接的工具。 * **Distributed Record Store - 分布式记录存储** 存储和分发记录的系统,负责记录节点相关的各种信息,便于连接管理和内容寻址。 * **Discovery - 发现** 发现和识别网络中的其他节点。 mDNS-discovery是一种局域网上使用mDNS的发现协议。它发出mDNS信标来探测是否有更多可获得的节点。由于低延迟的特性,局域网节点是非常适用p2p协议的。 mDNS-discovery是一个独立的协议,不依赖于任何其它的libp2p协议。mDNS-discovery能够发现局域网中可用的节点,而不需要依赖于其它的基础组件。在内网、不与Internet骨干网连接的网络、暂时失去连接的网络中,这样做是非常有用的。 mDNS-discovery可以按照服务配置(例如,仅仅发现加入特定协议的节点,比如ipfs),也支持私有网络(发现属于同一个私有网络的节点)。 Random-walk是DHT(以及其它有路由表的协议)的发现协议。它会进行随机DHT查询,以便快速了解到大量的节点。这使得DHT(或其他协议)收敛的更快,其代价是一开始时的小负载。 Bootstrap-List是一种发现协议,它使用本地存储来缓存网络中可用的、高度稳定且可信的节点地址。这允许协议发现网络的其余部分。这本质上和DNS引导自身的方式基本相同。 **Libp2p 流程** 1. 运行 Libp2p 协议的节点在初始化之后需要通过各种方式发现更多的节点,比如Bootstrap list、mDNS、DHT 等,这主要由**Discovery(发现)模块**负责与实现。 2. Libp2p 会把这些获取到的节点信息存储在**分布式记录存储模块**中,供以后方便使用。 3. 当上层应用需要连接某个节点时,**节点路由模块**会找到多条不同的路径,**连接管理模块**会对这些路径进行尝试连接。(由于P2P网络本身的特性,节点之间的连接状况始终在动态变化,故不是所有路径都是可以成功连接的~) 4. 连接成功之后,上层应用将通过 Libp2p 与连接节点进行交互,互相传递数据 。 连接的建立过程,主要包括3个步骤,包括**地址解析、传输协议适配、双方协商。** **地址解析** 为了适应复杂的网络环境,libp2p 支持多种不同的底层协议,甚至 IPFS 社区专门立了一个项目来标准化节点的地址。目前 libp2p 主要支持以下几种地址格式: * `**/ip4/127.0.0.1/tcp/4001/ipfs/QmNodeID**`: 这种格式跟传统的 TCP 网络里是一样的,直接可以解析出对应的 IPv4 地址和端口号; * `**/ipfs/QmNodeID**`: 这种格式的地址适用于 IPFS 网络,只有节点ID的地址,需要节点路由模块找到节点对应的IP地址,然后再进行连接; * `**/dns4/http://ipfs.ipfsbit.com/tcp/443/wss/p2p-webrtc-star**`: 这种地址需要调用`multiaddr-dns`组件,把域名解析成IP地址,然后再进行连接; * `**/p2p-circuit/p2p/QmNodeID**`: 这种地址是relay地址,用于中继网络,需要首先连接一个中继节点,才能连接到目的节点; 通过地址解析,libp2p能获知如何才能连接到目的节点,下一步就是尝试建立连接。 **传输协议适配** 地址里面的`/tcp`、`/quic`、`/ws`、`/p2p`分别对应不同的传输协议实现。libp2p 定义了统一的传输协议接口标准,选择地址对应的传输协议,调用传输协议的连接函数尝试连接目的节点。 **双方协商** 连接建立之后,libp2p 会首先进行双方协商,确定对方支持哪些功能。负责协商功能的是identify协议,它是内置在 libp2p 的基础协议,能够交换节点的公钥、本地监听地址等。 协商完成后,连接两端的节点会找到共同支持的协议,并且初始化它们。初始化时会注册每种协议的handler(回调函数),当有协议数据到达时,相应的handler就会被调用。由于多种传输协议会复用同一个底层连接,所以连接会被拆分成多个“流(Stream)”。 Libp2p 可以通俗理解成适用于多种传输协议的P2P网络层。由于目前网络模式多种多样,比如4G 网络/宽带网络,拨号/固定公网IP,以及还有着各式各样的传输协议(TCP、UDP等等)和网络防火墙的通信阻碍,所以导致这个协议的实现是非常复杂的。 Libp2p 实现了在不同的网络模式下,节点之间能够互相进行通信并传送数据。 **通信模块-Streams** 网络层处理所有关于连接到一个节点的问题,并且暴漏出简单的双向流。用户既可以打开一个新的流(NewStream),也可以注册一个流处理器(SetStreamHandler)。之后用户可以自由的实现他想要的任何消息传递协议。这使得构造一个p2p协议更简单,因为连接、多传输支持、流控制等的复杂度得到了处理。